diff --git a/Cargo.lock b/Cargo.lock index d7f48c17f8726..9412bbaa16dbb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3538,6 +3538,7 @@ dependencies = [ "pallet-election-provider-support-benchmarking", "pallet-elections-phragmen", "pallet-fast-unstake", + "pallet-glutton", "pallet-grandpa", "pallet-identity", "pallet-im-online", @@ -4849,6 +4850,7 @@ dependencies = [ "node-testing", "pallet-balances", "pallet-contracts", + "pallet-glutton", "pallet-im-online", "pallet-root-testing", "pallet-sudo", @@ -5812,6 +5814,24 @@ dependencies = [ "substrate-test-utils", ] +[[package]] +name = "pallet-glutton" +version = "4.0.0-dev" +dependencies = [ + "blake2", + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-grandpa" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index aaa1c2a211183..182d14924b057 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -166,6 +166,7 @@ members = [ "frame/uniques", "frame/utility", "frame/vesting", + "frame/glutton", "frame/whitelist", "primitives/api", "primitives/api/proc-macro", diff --git a/bin/node/executor/Cargo.toml b/bin/node/executor/Cargo.toml index ffa8d38ee4b34..cb661f536f7b7 100644 --- a/bin/node/executor/Cargo.toml +++ b/bin/node/executor/Cargo.toml @@ -35,6 +35,7 @@ node-testing = { version = "3.0.0-dev", path = "../testing" } pallet-balances = { version = "4.0.0-dev", path = "../../../frame/balances" } pallet-contracts = { version = "4.0.0-dev", path = "../../../frame/contracts" } pallet-im-online = { version = "4.0.0-dev", path = "../../../frame/im-online" } +pallet-glutton = { version = "4.0.0-dev", path = "../../../frame/glutton" } pallet-sudo = { version = "4.0.0-dev", path = "../../../frame/sudo" } pallet-timestamp = { version = "4.0.0-dev", path = "../../../frame/timestamp" } pallet-treasury = { version = "4.0.0-dev", path = "../../../frame/treasury" } diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 1d2e6f057d517..4a3ba9117d773 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -85,6 +85,7 @@ pallet-nomination-pools-benchmarking = { version = "1.0.0", default-features = f pallet-nomination-pools-runtime-api = { version = "1.0.0-dev", default-features = false, path = "../../../frame/nomination-pools/runtime-api" } 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-glutton = { version = "4.0.0-dev", default-features = false, path = "../../../frame/glutton" } 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-insecure-randomness-collective-flip = { version = "4.0.0-dev", default-features = false, path = "../../../frame/insecure-randomness-collective-flip" } @@ -164,6 +165,7 @@ std = [ "node-primitives/std", "sp-offchain/std", "pallet-offences/std", + "pallet-glutton/std", "pallet-preimage/std", "pallet-proxy/std", "sp-core/std", @@ -242,6 +244,7 @@ runtime-benchmarks = [ "pallet-multisig/runtime-benchmarks", "pallet-nomination-pools-benchmarking/runtime-benchmarks", "pallet-offences-benchmarking/runtime-benchmarks", + "pallet-glutton/runtime-benchmarks", "pallet-preimage/runtime-benchmarks", "pallet-proxy/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", @@ -298,6 +301,7 @@ try-runtime = [ "pallet-multisig/try-runtime", "pallet-nomination-pools/try-runtime", "pallet-offences/try-runtime", + "pallet-glutton/try-runtime", "pallet-preimage/try-runtime", "pallet-proxy/try-runtime", "pallet-insecure-randomness-collective-flip/try-runtime", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 2c7969ebcd6b9..d889bcc6d2abe 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -362,6 +362,11 @@ impl pallet_scheduler::Config for Runtime { type Preimages = Preimage; } +impl pallet_glutton::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_glutton::weights::SubstrateWeight; +} + parameter_types! { pub const PreimageMaxSize: u32 = 4096 * 1024; pub const PreimageBaseDeposit: Balance = 1 * DOLLARS; @@ -1747,6 +1752,7 @@ construct_runtime!( Recovery: pallet_recovery, Vesting: pallet_vesting, Scheduler: pallet_scheduler, + Glutton: pallet_glutton, Preimage: pallet_preimage, Proxy: pallet_proxy, Multisig: pallet_multisig, @@ -1878,6 +1884,7 @@ mod benches { [pallet_recovery, Recovery] [pallet_remark, Remark] [pallet_scheduler, Scheduler] + [pallet_glutton, Glutton] [pallet_session, SessionBench::] [pallet_staking, Staking] [pallet_state_trie_migration, StateTrieMigration] diff --git a/frame/glutton/Cargo.toml b/frame/glutton/Cargo.toml new file mode 100644 index 0000000000000..c0f0312464ee6 --- /dev/null +++ b/frame/glutton/Cargo.toml @@ -0,0 +1,51 @@ +[package] +name = "pallet-glutton" +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 pushing a chain to its weight limits" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +blake2 = { version = "0.10.4", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +log = { version = "0.4.14", default-features = false } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, 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" } +sp-core = { version = "7.0.0", default-features = false, path = "../../primitives/core" } +sp-io = { version = "7.0.0", default-features = false, path = "../../primitives/io" } +sp-runtime = { version = "7.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "5.0.0", default-features = false, path = "../../primitives/std" } + +[dev-dependencies] +pallet-balances = { version = "4.0.0-dev", path = "../balances" } + +[features] +default = ["std"] +std = [ + "blake2/std", + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", +] +try-runtime = ["frame-support/try-runtime"] + +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] diff --git a/frame/glutton/README.md b/frame/glutton/README.md new file mode 100644 index 0000000000000..bcd6c51a6fced --- /dev/null +++ b/frame/glutton/README.md @@ -0,0 +1,9 @@ +# WARNING + +Do not use on value-bearing chains. This pallet is **only** intended for usage on test-chains. + +# Glutton Pallet + +The `Glutton` pallet gets the name from its property to consume vast amounts of resources. It can be used to push para-chains and their relay-chains to the limits. This is good for testing out theoretical limits in a practical way. + +The `Glutton` can be set to consume a fraction of the available unused weight of a chain. It accomplishes this by utilizing the `on_idle` hook and consuming a specific ration of the remaining weight. The rations can be set via `set_compute` and `set_storage`. Initially the `Glutton` needs to be initialized once with `initialize_pallet`. diff --git a/frame/glutton/src/benchmarking.rs b/frame/glutton/src/benchmarking.rs new file mode 100644 index 0000000000000..13576ae2f3d98 --- /dev/null +++ b/frame/glutton/src/benchmarking.rs @@ -0,0 +1,98 @@ +// 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. + +//! Glutton pallet benchmarking. +//! +//! Has to be compiled and run twice to calibrate on new hardware. + +#[cfg(feature = "runtime-benchmarks")] +use super::*; + +use frame_benchmarking::benchmarks; +use frame_support::{pallet_prelude::*, weights::constants::*}; +use frame_system::RawOrigin as SystemOrigin; + +use crate::Pallet as Glutton; +use frame_system::Pallet as System; + +benchmarks! { + initialize_pallet_grow { + let n in 0 .. 1_000; + }: { + Glutton::::initialize_pallet(SystemOrigin::Root.into(), n, None).unwrap() + } verify { + assert_eq!(TrashDataCount::::get(), n); + } + + initialize_pallet_shrink { + let n in 0 .. 1_000; + + Glutton::::initialize_pallet(SystemOrigin::Root.into(), n, None).unwrap(); + }: { + Glutton::::initialize_pallet(SystemOrigin::Root.into(), 0, Some(n)).unwrap() + } verify { + assert_eq!(TrashDataCount::::get(), 0); + } + + waste_ref_time_iter { + let i in 0..100_000; + }: { + Glutton::::waste_ref_time_iter(vec![0u8; 64], i); + } + + waste_proof_size_some { + let i in 0..5_000; + + (0..5000).for_each(|i| TrashData::::insert(i, [i as u8; 1024])); + }: { + (0..i).for_each(|i| { + TrashData::::get(i); + }) + } + + // For manual verification only. + on_idle_high_proof_waste { + (0..5000).for_each(|i| TrashData::::insert(i, [i as u8; 1024])); + let _ = Glutton::::set_compute(SystemOrigin::Root.into(), Perbill::from_percent(100)); + let _ = Glutton::::set_storage(SystemOrigin::Root.into(), Perbill::from_percent(100)); + }: { + let weight = Glutton::::on_idle(System::::block_number(), Weight::from_parts(WEIGHT_REF_TIME_PER_MILLIS * 100, WEIGHT_PROOF_SIZE_PER_MB * 5)); + } + + // For manual verification only. + on_idle_low_proof_waste { + (0..5000).for_each(|i| TrashData::::insert(i, [i as u8; 1024])); + let _ = Glutton::::set_compute(SystemOrigin::Root.into(), Perbill::from_percent(100)); + let _ = Glutton::::set_storage(SystemOrigin::Root.into(), Perbill::from_percent(100)); + }: { + let weight = Glutton::::on_idle(System::::block_number(), Weight::from_parts(WEIGHT_REF_TIME_PER_MILLIS * 100, WEIGHT_PROOF_SIZE_PER_KB * 20)); + } + + empty_on_idle { + }: { + // Enough weight do do nothing. + Glutton::::on_idle(System::::block_number(), T::WeightInfo::empty_on_idle()); + } + + set_compute { + }: _(SystemOrigin::Root, Perbill::from_percent(50)) + + set_storage { + }: _(SystemOrigin::Root, Perbill::from_percent(50)) + + impl_benchmark_test_suite!(Glutton, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/frame/glutton/src/lib.rs b/frame/glutton/src/lib.rs new file mode 100644 index 0000000000000..e9a46374a5ade --- /dev/null +++ b/frame/glutton/src/lib.rs @@ -0,0 +1,292 @@ +// 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. + +//! # Glutton Pallet +//! +//! Pallet that consumes `ref_time` and `proof_size` of a block. Based on the +//! `Compute` and `Storage` parameters the pallet consumes the adequate amount +//! of weight. + +#![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 blake2::{Blake2b512, Digest}; +use frame_support::{pallet_prelude::*, weights::WeightMeter}; +use frame_system::pallet_prelude::*; +use sp_runtime::{traits::Zero, Perbill}; +use sp_std::{vec, vec::Vec}; + +pub use pallet::*; +pub use weights::WeightInfo; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From + IsType<::RuntimeEvent>; + + /// Weight information for this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// The pallet has been (re)initialized by root. + PalletInitialized { reinit: bool }, + /// The computation limit has been updated by root. + ComputationLimitSet { compute: Perbill }, + /// The storage limit has been updated by root. + StorageLimitSet { storage: Perbill }, + } + + #[pallet::error] + pub enum Error { + /// The pallet was already initialized. + /// + /// Set `witness_count` to `Some` to bypass this error. + AlreadyInitialized, + } + + /// Storage value used to specify what percentage of the left over `ref_time` + /// to consume during `on_idle`. + #[pallet::storage] + pub(crate) type Compute = StorageValue<_, Perbill, ValueQuery>; + + /// Storage value used the specify what percentage of left over `proof_size` + /// to consume during `on_idle`. + #[pallet::storage] + pub(crate) type Storage = StorageValue<_, Perbill, ValueQuery>; + + /// Storage map used for wasting proof size. + /// + /// It contains no meaningful data - hence the name "Trash". The maximal number of entries is + /// set to 65k, which is just below the next jump at 16^4. This is important to reduce the proof + /// size benchmarking overestimate. The assumption here is that we won't have more than 65k * + /// 1KiB = 65MiB of proof size wasting in practice. However, this limit is not enforced, so the + /// pallet would also work out of the box with more entries, but its benchmarked proof weight + /// would possibly be underestimated in that case. + #[pallet::storage] + pub(super) type TrashData = StorageMap< + Hasher = Twox64Concat, + Key = u32, + Value = [u8; 1024], + QueryKind = OptionQuery, + MaxValues = ConstU32<65_000>, + >; + + /// The current number of entries in `TrashData`. + #[pallet::storage] + pub(crate) type TrashDataCount = StorageValue<_, u32, ValueQuery>; + + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + assert!( + !T::WeightInfo::waste_ref_time_iter(1).ref_time().is_zero(), + "Weight zero; would get stuck in an infinite loop" + ); + assert!( + !T::WeightInfo::waste_proof_size_some(1).proof_size().is_zero(), + "Weight zero; would get stuck in an infinite loop" + ); + } + + fn on_idle(_: BlockNumberFor, remaining_weight: Weight) -> Weight { + let mut meter = WeightMeter::from_limit(remaining_weight); + if !meter.check_accrue(T::WeightInfo::empty_on_idle()) { + return T::WeightInfo::empty_on_idle() + } + + let proof_size_limit = Storage::::get().mul_floor(meter.remaining().proof_size()); + let computation_weight_limit = + Compute::::get().mul_floor(meter.remaining().ref_time()); + let mut meter = WeightMeter::from_limit(Weight::from_parts( + computation_weight_limit, + proof_size_limit, + )); + + Self::waste_at_most_proof_size(&mut meter); + Self::waste_at_most_ref_time(&mut meter); + + meter.consumed + } + } + + #[pallet::call] + impl Pallet { + /// Initializes the pallet by writing into `TrashData`. + /// + /// Only callable by Root. A good default for `trash_count` is `5_000`. + #[pallet::call_index(0)] + #[pallet::weight( + T::WeightInfo::initialize_pallet_grow(witness_count.unwrap_or_default()) + .max(T::WeightInfo::initialize_pallet_shrink(witness_count.unwrap_or_default())) + )] + pub fn initialize_pallet( + origin: OriginFor, + new_count: u32, + witness_count: Option, + ) -> DispatchResult { + ensure_root(origin)?; + + let current_count = TrashDataCount::::get(); + ensure!( + current_count == witness_count.unwrap_or_default(), + Error::::AlreadyInitialized + ); + + if new_count > current_count { + (current_count..new_count).for_each(|i| TrashData::::insert(i, [i as u8; 1024])); + } else { + (new_count..current_count).for_each(TrashData::::remove); + } + + Self::deposit_event(Event::PalletInitialized { reinit: witness_count.is_some() }); + TrashDataCount::::set(new_count); + Ok(()) + } + + /// Set the `Compute` storage value that determines how much of the + /// block's weight `ref_time` to use during `on_idle`. + /// + /// Only callable by Root. + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::set_compute())] + pub fn set_compute(origin: OriginFor, compute: Perbill) -> DispatchResult { + ensure_root(origin)?; + Compute::::set(compute); + + Self::deposit_event(Event::ComputationLimitSet { compute }); + Ok(()) + } + + /// Set the `Storage` storage value that determines the PoV size usage + /// for each block. + /// + /// Only callable by Root. + #[pallet::call_index(2)] + #[pallet::weight(T::WeightInfo::set_storage())] + pub fn set_storage(origin: OriginFor, storage: Perbill) -> DispatchResult { + ensure_root(origin)?; + Storage::::set(storage); + + Self::deposit_event(Event::StorageLimitSet { storage }); + Ok(()) + } + } + + impl Pallet { + /// Waste at most the remaining proof size of `meter`. + /// + /// Tries to come as close to the limit as possible. + pub(crate) fn waste_at_most_proof_size(meter: &mut WeightMeter) { + let Ok(n) = Self::calculate_proof_size_iters(&meter) else { + return; + }; + + meter.defensive_saturating_accrue(T::WeightInfo::waste_proof_size_some(n)); + + (0..n).for_each(|i| { + TrashData::::get(i); + }); + } + + /// Calculate how many times `waste_proof_size_some` should be called to fill up `meter`. + fn calculate_proof_size_iters(meter: &WeightMeter) -> Result { + let base = T::WeightInfo::waste_proof_size_some(0); + let slope = T::WeightInfo::waste_proof_size_some(1).saturating_sub(base); + + let remaining = meter.remaining().saturating_sub(base); + let iter_by_proof_size = + remaining.proof_size().checked_div(slope.proof_size()).ok_or(())?; + let iter_by_ref_time = remaining.ref_time().checked_div(slope.ref_time()).ok_or(())?; + + if iter_by_proof_size > 0 && iter_by_proof_size <= iter_by_ref_time { + Ok(iter_by_proof_size as u32) + } else { + Err(()) + } + } + + /// Waste at most the remaining ref time weight of `meter`. + /// + /// Tries to come as close to the limit as possible. + pub(crate) fn waste_at_most_ref_time(meter: &mut WeightMeter) { + let Ok(n) = Self::calculate_ref_time_iters(&meter) else { + return; + }; + meter.defensive_saturating_accrue(T::WeightInfo::waste_ref_time_iter(n)); + + let clobber = Self::waste_ref_time_iter(vec![0u8; 64], n); + + // By casting it into a vec we can hopefully prevent the compiler from optimizing it + // out. Note that `Blake2b512` produces 64 bytes, this is therefore impossible - but the + // compiler does not know that (hopefully). + debug_assert!(clobber.len() == 64); + if clobber.len() == 65 { + TrashData::::insert(0, [clobber[0] as u8; 1024]); + } + } + + /// Wastes some `ref_time`. Receives the previous result as an argument. + /// + /// The ref_time of one iteration should be in the order of 1-10 ms. + pub(crate) fn waste_ref_time_iter(clobber: Vec, i: u32) -> Vec { + let mut hasher = Blake2b512::new(); + + // Blake2 has a very high speed of hashing so we make multiple hashes with it to + // waste more `ref_time` at once. + (0..i).for_each(|_| { + hasher.update(clobber.as_slice()); + }); + + hasher.finalize().to_vec() + } + + /// Calculate how many times `waste_ref_time_iter` should be called to fill up `meter`. + fn calculate_ref_time_iters(meter: &WeightMeter) -> Result { + let base = T::WeightInfo::waste_ref_time_iter(0); + let slope = T::WeightInfo::waste_ref_time_iter(1).saturating_sub(base); + if !slope.proof_size().is_zero() || !base.proof_size().is_zero() { + return Err(()) + } + + match meter + .remaining() + .ref_time() + .saturating_sub(base.ref_time()) + .checked_div(slope.ref_time()) + { + Some(0) | None => Err(()), + Some(i) => Ok(i as u32), + } + } + } +} diff --git a/frame/glutton/src/mock.rs b/frame/glutton/src/mock.rs new file mode 100644 index 0000000000000..c8be354f48e28 --- /dev/null +++ b/frame/glutton/src/mock.rs @@ -0,0 +1,80 @@ +// 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 super::*; +use crate as pallet_glutton; + +use frame_support::traits::{ConstU32, ConstU64}; +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}, + Glutton: pallet_glutton::{Pallet, Event}, + } +); + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type RuntimeCall = RuntimeCall; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + 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 Config for Test { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + +pub fn new_test_ext() -> sp_io::TestExternalities { + let t = frame_system::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/glutton/src/tests.rs b/frame/glutton/src/tests.rs new file mode 100644 index 0000000000000..d2d2d4edec421 --- /dev/null +++ b/frame/glutton/src/tests.rs @@ -0,0 +1,226 @@ +// This file is part of Substrate. + +// Copyright (C) 2023 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 the glutton pallet. + +use super::*; +use mock::{new_test_ext, Glutton, RuntimeOrigin, System, Test}; + +use frame_support::{assert_err, assert_noop, assert_ok, weights::constants::*}; + +#[test] +fn initialize_pallet_works() { + new_test_ext().execute_with(|| { + assert_eq!(TrashData::::get(0), None); + + assert_noop!( + Glutton::initialize_pallet(RuntimeOrigin::signed(1), 3, None), + DispatchError::BadOrigin + ); + assert_noop!( + Glutton::initialize_pallet(RuntimeOrigin::none(), 3, None), + DispatchError::BadOrigin + ); + + assert_ok!(Glutton::initialize_pallet(RuntimeOrigin::root(), 2, None)); + System::assert_last_event(Event::PalletInitialized { reinit: false }.into()); + assert_err!( + Glutton::initialize_pallet(RuntimeOrigin::root(), 2, None), + Error::::AlreadyInitialized + ); + + assert_eq!(TrashData::::get(0), Some([0; 1024])); + assert_eq!(TrashData::::get(1), Some([1; 1024])); + assert_eq!(TrashData::::get(2), None); + + assert_eq!(TrashDataCount::::get(), 2); + + assert_ok!(Glutton::initialize_pallet(RuntimeOrigin::root(), 20, Some(2))); + + assert_eq!(TrashDataCount::::get(), 20); + assert_eq!(TrashData::::iter_keys().count(), 20); + }); +} + +#[test] +fn expand_and_shrink_trash_data_works() { + new_test_ext().execute_with(|| { + assert_eq!(TrashDataCount::::get(), 0); + + assert_ok!(Glutton::initialize_pallet(RuntimeOrigin::root(), 5000, None)); + assert_eq!(TrashDataCount::::get(), 5000); + assert_eq!(TrashData::::iter_keys().count(), 5000); + + assert_ok!(Glutton::initialize_pallet(RuntimeOrigin::root(), 8000, Some(5000))); + assert_eq!(TrashDataCount::::get(), 8000); + assert_eq!(TrashData::::iter_keys().count(), 8000); + + assert_ok!(Glutton::initialize_pallet(RuntimeOrigin::root(), 6000, Some(8000))); + assert_eq!(TrashDataCount::::get(), 6000); + assert_eq!(TrashData::::iter_keys().count(), 6000); + + assert_noop!( + Glutton::initialize_pallet(RuntimeOrigin::root(), 0, None), + Error::::AlreadyInitialized + ); + assert_ok!(Glutton::initialize_pallet(RuntimeOrigin::root(), 0, Some(6000))); + assert_eq!(TrashDataCount::::get(), 0); + assert_eq!(TrashData::::iter_keys().count(), 0); + }); +} + +#[test] +fn setting_compute_works() { + new_test_ext().execute_with(|| { + assert_eq!(Compute::::get(), Perbill::from_percent(0)); + + assert_ok!(Glutton::set_compute(RuntimeOrigin::root(), Perbill::from_percent(70))); + assert_eq!(Compute::::get(), Perbill::from_percent(70)); + System::assert_last_event( + Event::ComputationLimitSet { compute: Perbill::from_percent(70) }.into(), + ); + + assert_noop!( + Glutton::set_compute(RuntimeOrigin::signed(1), Perbill::from_percent(30)), + DispatchError::BadOrigin + ); + assert_noop!( + Glutton::set_compute(RuntimeOrigin::none(), Perbill::from_percent(30)), + DispatchError::BadOrigin + ); + }); +} + +#[test] +fn setting_storage_works() { + new_test_ext().execute_with(|| { + assert_eq!(Storage::::get(), Perbill::from_percent(0)); + + assert_ok!(Glutton::set_storage(RuntimeOrigin::root(), Perbill::from_percent(30))); + assert_eq!(Storage::::get(), Perbill::from_percent(30)); + System::assert_last_event( + Event::StorageLimitSet { storage: Perbill::from_percent(30) }.into(), + ); + + assert_noop!( + Glutton::set_storage(RuntimeOrigin::signed(1), Perbill::from_percent(90)), + DispatchError::BadOrigin + ); + assert_noop!( + Glutton::set_storage(RuntimeOrigin::none(), Perbill::from_percent(90)), + DispatchError::BadOrigin + ); + }); +} + +#[test] +fn on_idle_works() { + new_test_ext().execute_with(|| { + assert_ok!(Glutton::set_compute(RuntimeOrigin::root(), Perbill::from_percent(100))); + assert_ok!(Glutton::set_storage(RuntimeOrigin::root(), Perbill::from_percent(100))); + + Glutton::on_idle(1, Weight::from_ref_time(20_000_000)); + }); +} + +/// Check that the expected is close enough to the consumed weight. +#[test] +fn on_idle_weight_high_proof_is_close_enough_works() { + new_test_ext().execute_with(|| { + assert_ok!(Glutton::set_compute(RuntimeOrigin::root(), Perbill::from_percent(100))); + assert_ok!(Glutton::set_storage(RuntimeOrigin::root(), Perbill::from_percent(100))); + + let should = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, WEIGHT_PROOF_SIZE_PER_MB * 5); + let got = Glutton::on_idle(1, should); + assert!(got.all_lte(should), "Consumed too much weight"); + + let ratio = Perbill::from_rational(got.proof_size(), should.proof_size()); + assert!( + ratio >= Perbill::from_percent(99), + "Too few proof size consumed, was only {:?} of expected", + ratio + ); + + let ratio = Perbill::from_rational(got.ref_time(), should.ref_time()); + assert!( + ratio >= Perbill::from_percent(99), + "Too few ref time consumed, was only {:?} of expected", + ratio + ); + }); +} + +#[test] +fn on_idle_weight_low_proof_is_close_enough_works() { + new_test_ext().execute_with(|| { + assert_ok!(Glutton::set_compute(RuntimeOrigin::root(), Perbill::from_percent(100))); + assert_ok!(Glutton::set_storage(RuntimeOrigin::root(), Perbill::from_percent(100))); + + let should = Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, WEIGHT_PROOF_SIZE_PER_KB * 20); + let got = Glutton::on_idle(1, should); + assert!(got.all_lte(should), "Consumed too much weight"); + + let ratio = Perbill::from_rational(got.proof_size(), should.proof_size()); + // Just a sanity check here. + assert!( + ratio >= Perbill::from_percent(80), + "Too few proof size consumed, was only {:?} of expected", + ratio + ); + + let ratio = Perbill::from_rational(got.ref_time(), should.ref_time()); + assert!( + ratio >= Perbill::from_percent(99), + "Too few ref time consumed, was only {:?} of expected", + ratio + ); + }); +} + +#[test] +fn waste_at_most_ref_time_weight_close_enough() { + new_test_ext().execute_with(|| { + let mut meter = + WeightMeter::from_limit(Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, u64::MAX)); + // Over-spending fails defensively. + Glutton::waste_at_most_ref_time(&mut meter); + + // We require it to be under-spend by at most 1%. + assert!( + meter.consumed_ratio() >= Perbill::from_percent(99), + "Consumed too few: {:?}", + meter.consumed_ratio() + ); + }); +} + +#[test] +fn waste_at_most_proof_size_weight_close_enough() { + new_test_ext().execute_with(|| { + let mut meter = + WeightMeter::from_limit(Weight::from_parts(u64::MAX, WEIGHT_PROOF_SIZE_PER_MB * 5)); + // Over-spending fails defensively. + Glutton::waste_at_most_proof_size(&mut meter); + + // We require it to be under-spend by at most 1%. + assert!( + meter.consumed_ratio() >= Perbill::from_percent(99), + "Consumed too few: {:?}", + meter.consumed_ratio() + ); + }); +} diff --git a/frame/glutton/src/weights.rs b/frame/glutton/src/weights.rs new file mode 100644 index 0000000000000..1e09d02c69d1c --- /dev/null +++ b/frame/glutton/src/weights.rs @@ -0,0 +1,324 @@ +// This file is part of Substrate. + +// Copyright (C) 2023 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_glutton +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-02-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-ehxwxxsd-project-145-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/substrate +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/substrate/.git/.artifacts/bench.json +// --pallet=pallet_glutton +// --chain=dev +// --header=./HEADER-APACHE2 +// --output=./frame/glutton/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_glutton. +pub trait WeightInfo { + fn initialize_pallet_grow(n: u32, ) -> Weight; + fn initialize_pallet_shrink(n: u32, ) -> Weight; + fn waste_ref_time_iter(i: u32, ) -> Weight; + fn waste_proof_size_some(i: u32, ) -> Weight; + fn on_idle_high_proof_waste() -> Weight; + fn on_idle_low_proof_waste() -> Weight; + fn empty_on_idle() -> Weight; + fn set_compute() -> Weight; + fn set_storage() -> Weight; +} + +/// Weights for pallet_glutton using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: Glutton TrashDataCount (r:1 w:1) + /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:0 w:1000) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// The range of component `n` is `[0, 1000]`. + fn initialize_pallet_grow(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `499` + // Minimum execution time: 9_248 nanoseconds. + Weight::from_ref_time(9_582_000) + .saturating_add(Weight::from_proof_size(499)) + // Standard Error: 1_144 + .saturating_add(Weight::from_ref_time(1_624_225).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + } + /// Storage: Glutton TrashDataCount (r:1 w:1) + /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:0 w:1000) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// The range of component `n` is `[0, 1000]`. + fn initialize_pallet_shrink(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `65` + // Estimated: `499` + // Minimum execution time: 10_210 nanoseconds. + Weight::from_ref_time(7_260_854) + .saturating_add(Weight::from_proof_size(499)) + // Standard Error: 1_459 + .saturating_add(Weight::from_ref_time(1_053_844).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(n.into()))) + } + /// The range of component `i` is `[0, 100000]`. + fn waste_ref_time_iter(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 605 nanoseconds. + Weight::from_ref_time(1_102_112) + .saturating_add(Weight::from_proof_size(0)) + // Standard Error: 28 + .saturating_add(Weight::from_ref_time(120_597).saturating_mul(i.into())) + } + /// Storage: Glutton TrashData (r:5000 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// The range of component `i` is `[0, 5000]`. + fn waste_proof_size_some(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `119036 + i * (1053 ±0)` + // Estimated: `0 + i * (3016 ±0)` + // Minimum execution time: 464 nanoseconds. + Weight::from_ref_time(552_000) + .saturating_add(Weight::from_proof_size(0)) + // Standard Error: 1_962 + .saturating_add(Weight::from_ref_time(5_780_304).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(i.into()))) + .saturating_add(Weight::from_proof_size(3016).saturating_mul(i.into())) + } + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:1738 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + fn on_idle_high_proof_waste() -> Weight { + // Proof Size summary in bytes: + // Measured: `1955391` + // Estimated: `5242806` + // Minimum execution time: 55_398_405 nanoseconds. + Weight::from_ref_time(55_594_848_000) + .saturating_add(Weight::from_proof_size(5242806)) + .saturating_add(T::DbWeight::get().reads(1740_u64)) + } + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:6 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + fn on_idle_low_proof_waste() -> Weight { + // Proof Size summary in bytes: + // Measured: `11717` + // Estimated: `19094` + // Minimum execution time: 98_888_667 nanoseconds. + Weight::from_ref_time(99_157_239_000) + .saturating_add(Weight::from_proof_size(19094)) + .saturating_add(T::DbWeight::get().reads(8_u64)) + } + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn empty_on_idle() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `998` + // Minimum execution time: 3_967 nanoseconds. + Weight::from_ref_time(4_121_000) + .saturating_add(Weight::from_proof_size(998)) + .saturating_add(T::DbWeight::get().reads(2_u64)) + } + /// Storage: Glutton Compute (r:0 w:1) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn set_compute() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_112 nanoseconds. + Weight::from_ref_time(7_484_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: Glutton Storage (r:0 w:1) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn set_storage() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_056 nanoseconds. + Weight::from_ref_time(7_414_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + /// Storage: Glutton TrashDataCount (r:1 w:1) + /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:0 w:1000) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// The range of component `n` is `[0, 1000]`. + fn initialize_pallet_grow(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `499` + // Minimum execution time: 9_248 nanoseconds. + Weight::from_ref_time(9_582_000) + .saturating_add(Weight::from_proof_size(499)) + // Standard Error: 1_144 + .saturating_add(Weight::from_ref_time(1_624_225).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) + } + /// Storage: Glutton TrashDataCount (r:1 w:1) + /// Proof: Glutton TrashDataCount (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:0 w:1000) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// The range of component `n` is `[0, 1000]`. + fn initialize_pallet_shrink(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `65` + // Estimated: `499` + // Minimum execution time: 10_210 nanoseconds. + Weight::from_ref_time(7_260_854) + .saturating_add(Weight::from_proof_size(499)) + // Standard Error: 1_459 + .saturating_add(Weight::from_ref_time(1_053_844).saturating_mul(n.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(n.into()))) + } + /// The range of component `i` is `[0, 100000]`. + fn waste_ref_time_iter(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 605 nanoseconds. + Weight::from_ref_time(1_102_112) + .saturating_add(Weight::from_proof_size(0)) + // Standard Error: 28 + .saturating_add(Weight::from_ref_time(120_597).saturating_mul(i.into())) + } + /// Storage: Glutton TrashData (r:5000 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + /// The range of component `i` is `[0, 5000]`. + fn waste_proof_size_some(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `119036 + i * (1053 ±0)` + // Estimated: `0 + i * (3016 ±0)` + // Minimum execution time: 464 nanoseconds. + Weight::from_ref_time(552_000) + .saturating_add(Weight::from_proof_size(0)) + // Standard Error: 1_962 + .saturating_add(Weight::from_ref_time(5_780_304).saturating_mul(i.into())) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(i.into()))) + .saturating_add(Weight::from_proof_size(3016).saturating_mul(i.into())) + } + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:1738 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + fn on_idle_high_proof_waste() -> Weight { + // Proof Size summary in bytes: + // Measured: `1955391` + // Estimated: `5242806` + // Minimum execution time: 55_398_405 nanoseconds. + Weight::from_ref_time(55_594_848_000) + .saturating_add(Weight::from_proof_size(5242806)) + .saturating_add(RocksDbWeight::get().reads(1740_u64)) + } + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton TrashData (r:6 w:0) + /// Proof: Glutton TrashData (max_values: Some(65000), max_size: Some(1036), added: 3016, mode: MaxEncodedLen) + fn on_idle_low_proof_waste() -> Weight { + // Proof Size summary in bytes: + // Measured: `11717` + // Estimated: `19094` + // Minimum execution time: 98_888_667 nanoseconds. + Weight::from_ref_time(99_157_239_000) + .saturating_add(Weight::from_proof_size(19094)) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + } + /// Storage: Glutton Storage (r:1 w:0) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: Glutton Compute (r:1 w:0) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn empty_on_idle() -> Weight { + // Proof Size summary in bytes: + // Measured: `4` + // Estimated: `998` + // Minimum execution time: 3_967 nanoseconds. + Weight::from_ref_time(4_121_000) + .saturating_add(Weight::from_proof_size(998)) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + } + /// Storage: Glutton Compute (r:0 w:1) + /// Proof: Glutton Compute (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn set_compute() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_112 nanoseconds. + Weight::from_ref_time(7_484_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: Glutton Storage (r:0 w:1) + /// Proof: Glutton Storage (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn set_storage() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 7_056 nanoseconds. + Weight::from_ref_time(7_414_000) + .saturating_add(Weight::from_proof_size(0)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } +}