From 35513dd7f2c73fa63339bdc6dd32d2a229d43caf Mon Sep 17 00:00:00 2001 From: Marian Radu Date: Wed, 15 Jul 2026 15:48:08 +0300 Subject: [PATCH 1/9] pallet-revive: extend cold/hot pricing to call opcodes and code loads --- .../src/weights/pallet_revive.rs | 29 +++ substrate/frame/revive/src/access_list.rs | 205 ++++++++++----- substrate/frame/revive/src/benchmarking.rs | 170 ++++++++++++- substrate/frame/revive/src/exec.rs | 83 +++++- substrate/frame/revive/src/exec/mock_ext.rs | 7 + substrate/frame/revive/src/exec/tests.rs | 239 ++++++++++++++++-- substrate/frame/revive/src/lib.rs | 7 +- .../evm/instructions/contract/call_helpers.rs | 14 +- substrate/frame/revive/src/vm/mod.rs | 77 +++++- substrate/frame/revive/src/vm/pvm.rs | 20 +- .../frame/revive/src/vm/runtime_costs.rs | 143 +++++++++-- substrate/frame/revive/src/weights.rs | 62 +++++ 12 files changed, 893 insertions(+), 163 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs index 4f81b56f9855..dc41e926a8c1 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs @@ -139,6 +139,14 @@ impl pallet_revive::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot load re-reads a blob already in the proof). + fn call_with_pvm_code_per_byte_hot(c: u32, ) -> Weight { + Weight::from_parts(179_867_634, 0) + .saturating_add(Weight::from_parts(1_579, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(2)) + } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:2 w:0) @@ -165,6 +173,14 @@ impl pallet_revive::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot load re-reads a blob already in the proof). + fn call_with_evm_code_per_byte_hot(c: u32, ) -> Weight { + Weight::from_parts(127_674_465, 0) + .saturating_add(Weight::from_parts(1_780, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(2)) + } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:2 w:0) @@ -1306,6 +1322,19 @@ impl pallet_revive::WeightInfo for WeightInfo { .saturating_add(Weight::from_parts(0, 4212)) .saturating_add(T::DbWeight::get().reads(3)) } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot call re-reads state already in the proof). + fn seal_call_hot() -> Weight { + Weight::from_parts(94_926_944, 0) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(1)) + } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot call re-reads state already in the proof). + fn seal_delegate_call_hot() -> Weight { + Weight::from_parts(39_798_000, 0) + .saturating_add(T::DbWeight::get().reads(3)) + } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) diff --git a/substrate/frame/revive/src/access_list.rs b/substrate/frame/revive/src/access_list.rs index d12ae457118c..31d2db0de8b5 100644 --- a/substrate/frame/revive/src/access_list.rs +++ b/substrate/frame/revive/src/access_list.rs @@ -23,7 +23,7 @@ use alloc::vec::Vec; use frame_support::{BoundedBTreeSet, BoundedVec}; -use sp_core::{ConstU32, H160}; +use sp_core::{ConstU32, H160, H256}; use crate::{exec::Key, limits}; @@ -32,15 +32,15 @@ use crate::{exec::Key, limits}; /// memory cost. pub const MAX_INLINE_KEY_LEN: usize = 36; -/// Maximum number of distinct `(address, slot)` entries tracked in the -/// access list within a single transaction. +/// Maximum number of distinct entries tracked in the access list within a +/// single transaction. /// /// Bounds the working memory `AccessList` can allocate per transaction. /// EIP-2929 does not specify a structural cap; Ethereum relies on gas to /// implicitly bound growth. /// /// Past this cap, new touches bill cold without being added to the set; -/// slots already tracked continue to bill hot. +/// entries already tracked continue to bill hot. /// /// Memory grows discontinuously due to the runtime allocator (sc-allocator) /// rounding allocations up to power-of-2 size classes. @@ -105,6 +105,34 @@ impl From<&Key> for Slot { } } +/// Warmth of an access-list entry. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum Warmth { + /// Entry is in the access list. + Hot, + /// Entry is not in the access list; when `revertible` is true, the touch + /// journals the entry under the open frame, so a `rollback_frame` drops + /// it and the entry becomes cold again. + Cold { revertible: bool }, +} + +impl Warmth { + pub fn cold_nonrevertible() -> Self { + Self::Cold { revertible: false } + } + + pub fn is_hot(&self) -> bool { + matches!(self, Self::Hot) + } + + pub fn non_revertible(self) -> Self { + match self { + Self::Hot => Self::Hot, + Self::Cold { .. } => Self::Cold { revertible: false }, + } + } +} + /// Classification of a storage access for pricing. #[cfg_attr(test, derive(PartialEq, Eq))] #[derive(Clone, Copy, Debug)] @@ -115,27 +143,62 @@ pub enum StorageAccessKind { Transient, } -/// Warmth of a persistent storage access. Describes the slot's state -/// **before** the access. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Warmth { - /// Slot was already in the access list before this access. - Hot, - /// Slot was not in the access list before this access; the touch adds - /// it (so the next access to the same slot returns `Hot`). `revertible` - /// is true when the entry was journaled under an open frame, so a - /// `rollback_frame` can drop it and the slot becomes cold again. - Cold { revertible: bool }, +impl StorageAccessKind { + /// See [`Warmth::non_revertible`]. + pub fn non_revertible(self) -> Self { + match self { + Self::Persistent(warmth) => Self::Persistent(warmth.non_revertible()), + Self::Transient => Self::Transient, + } + } } -impl Warmth { - /// Whether this was the first access to the slot this transaction. - #[cfg(any(test, feature = "runtime-benchmarks"))] - pub(crate) fn is_cold(&self) -> bool { - matches!(self, Self::Cold { .. }) +/// A state access of an opcode, tracked by the access list. +#[derive(Clone, Copy)] +pub enum StateAccess { + Call { target: H160 }, + DelegateCall { target: H160 }, +} + +impl StateAccess { + /// The state access of a call or delegate call. + pub fn call(target: H160, delegate: bool) -> Self { + if delegate { Self::DelegateCall { target } } else { Self::Call { target } } + } + + /// The accessed address. + pub fn target(&self) -> H160 { + match self { + Self::Call { target } | Self::DelegateCall { target } => *target, + } + } + + /// Expands into the state items the opcode reads; `warmth_of` supplies + /// each item's warmth. + pub fn expand(self, mut warmth_of: impl FnMut(AccessEntry) -> Warmth) -> StateAccessKind { + match self { + Self::Call { target } => StateAccessKind::Call { + account: warmth_of(AccessEntry::Account { address: target }), + contract_info: warmth_of(AccessEntry::ContractInfo { address: target }), + }, + Self::DelegateCall { target } => StateAccessKind::DelegateCall { + contract_info: warmth_of(AccessEntry::ContractInfo { address: target }), + }, + } } } +/// Warmth of the read state items, one variant per [`StateAccess`] opcode. +#[cfg_attr(test, derive(PartialEq, Eq))] +#[derive(Clone, Copy, Debug)] +pub enum StateAccessKind { + /// A call reads the target's account state and contract metadata. + Call { account: Warmth, contract_info: Warmth }, + /// A delegate call runs in the caller's context and reads only the + /// target's contract metadata. + DelegateCall { contract_info: Warmth }, +} + /// Snapshot of per-transaction access-list counters. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct AccessListMetrics { @@ -147,17 +210,21 @@ pub struct AccessListMetrics { pub hot: u32, } -/// One entry per `(storage slot, contract address)` accessed in the current tx. -/// -/// Field order is `slot, address` so the derived `Ord` decides on `slot` -/// first, the most-discriminating field in the typical access pattern (one -/// contract touching many slots within a transaction). +/// One entry per distinct state item accessed in the current transaction. #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Clone)] -pub struct AccessEntry { - /// Slot identifier. - pub slot: Slot, - /// Contract whose child trie is being touched. - pub address: H160, +pub enum AccessEntry { + /// Account-level state of `address`. + Account { address: H160 }, + /// A contract storage slot. Field order is `slot, address` so comparison + /// decides on `slot` first, the most-discriminating field in the typical + /// access pattern (one contract touching many slots within a transaction). + Storage { slot: Slot, address: H160 }, + /// Contract metadata of `address`. + ContractInfo { address: H160 }, + /// Code blob and code metadata (`PristineCode` + `CodeInfoOf`). Keyed by + /// code hash, not address: code is deduplicated, so two contracts sharing + /// a blob genuinely share its load cost within a transaction. + Code { hash: H256 }, } /// Per-transaction access list with per-frame rollback support. Layout @@ -166,9 +233,9 @@ pub struct AccessEntry { /// /// # Safety invariant /// -/// Callers touch the `AccessList` before charging gas, so reverts must roll back the touches -/// they made. Without that, an out-of-gas at the cold charge after the touch would leave the slot -/// warm without the cold charge being paid, and a later access would then be billed hot. +/// Storage opcodes touch before charging, so reverts must roll back the +/// touches the reverted frame made; otherwise an out-of-gas at the charge +/// would leave the entry warm without its cold cost ever being paid. #[derive(Default)] pub struct AccessList { @@ -230,10 +297,16 @@ impl AccessList { } } - /// Non-mutating sibling of [`touch`](Self::touch). A peek never journals, so - /// a cold result is always non-revertible. + /// Non-mutating sibling of [`touch`](Self::touch): the `Warmth` a touch + /// of this entry would return. pub fn peek(&self, entry: &AccessEntry) -> Warmth { - if self.accessed.contains(entry) { Warmth::Hot } else { Warmth::Cold { revertible: false } } + if self.accessed.contains(entry) { + Warmth::Hot + } else if self.is_full() { + Warmth::cold_nonrevertible() + } else { + Warmth::Cold { revertible: self.in_nested_frame() } + } } /// Whether the set is at the entry cap. @@ -246,10 +319,12 @@ impl AccessList { !self.checkpoints.is_empty() } - /// Register the entry, returning whether it was cold or hot. + /// Register the entry, returning its warmth **before** this touch: the + /// first touch of an entry returns `Cold` although the entry is tracked + /// from now on. /// /// Past [`MAX_ACCESS_LIST_ENTRIES`], new entries are billed cold without - /// being journaled; previously-hot slots continue to bill hot. + /// being journaled; previously-hot entries continue to bill hot. pub fn touch(&mut self, entry: AccessEntry) -> Warmth { let kind = if self.is_full() { // Past the cap: bill by membership, but never journal. @@ -295,39 +370,41 @@ mod tests { fn nested_commit_then_parent_rollback_drops_all() { let mut al = AccessList::new(); let (a, b, c, d) = ( - AccessEntry { address: H160::zero(), slot: Slot::Fix([0xA; 32]) }, - AccessEntry { address: H160::zero(), slot: Slot::Fix([0xB; 32]) }, - AccessEntry { address: H160::zero(), slot: Slot::Fix([0xC; 32]) }, - AccessEntry { address: H160::zero(), slot: Slot::Fix([0xD; 32]) }, + AccessEntry::Storage { address: H160::zero(), slot: Slot::Fix([0xA; 32]) }, + AccessEntry::Account { address: H160::zero() }, + AccessEntry::ContractInfo { address: H160::zero() }, + AccessEntry::Code { hash: H256::repeat_byte(0xD) }, ); // Root frame: cold, but no checkpoint covers it, so it is not revertible. assert_eq!(al.touch(a.clone()), Warmth::Cold { revertible: false }, "A: first touch cold"); - assert!(!al.touch(a.clone()).is_cold(), "A: second touch hot"); + assert!(al.touch(a.clone()).is_hot(), "A: second touch hot"); al.enter_frame(); assert_eq!(al.frame_depth(), 1); - // Inside F1: journaled under the open checkpoint, so it is revertible. - assert_eq!(al.touch(b.clone()), Warmth::Cold { revertible: true }, "B in F1: cold"); - assert!(!al.touch(a.clone()).is_cold(), "A in F1: hot via parent"); + assert_eq!(al.touch(b.clone()), Warmth::Cold { revertible: true }, "B in frame 1: cold"); + assert!(al.touch(a.clone()).is_hot(), "A in frame 1: hot via parent"); al.enter_frame(); - assert!(al.touch(c.clone()).is_cold(), "C in F2: cold"); + assert!(!al.touch(c.clone()).is_hot(), "C in frame 2: cold"); al.commit_frame(); assert_eq!(al.frame_depth(), 1); - assert!(!al.peek(&c).is_cold(), "C: survives F2 commit"); + assert!(al.peek(&c).is_hot(), "C: survives frame 2 commit"); - assert!(al.touch(d.clone()).is_cold(), "D in F1: cold"); + assert!(!al.touch(d.clone()).is_hot(), "D in frame 1: cold"); assert_eq!(al.metrics().size, 4); al.rollback_frame(); assert_eq!(al.frame_depth(), 0); - assert!(!al.peek(&a).is_cold(), "A: first frame, survives F1 revert"); - assert!(al.peek(&b).is_cold(), "B: inserted by F1, rolled back"); - assert!(al.peek(&c).is_cold(), "C: F2-committed-into-F1, gone when F1 reverts"); - assert!(al.peek(&d).is_cold(), "D: inserted by F1, rolled back"); + assert!(al.peek(&a).is_hot(), "A: first frame, survives frame 1 revert"); + assert!(!al.peek(&b).is_hot(), "B: inserted by frame 1, rolled back"); + assert!( + !al.peek(&c).is_hot(), + "C: frame-2-committed-into-frame-1, gone when frame 1 reverts" + ); + assert!(!al.peek(&d).is_hot(), "D: inserted by frame 1, rolled back"); // Counters never decrement, even for entries that later roll back: // A (cold) + B,C,D (cold) -> 4 cold; A,A (hot) -> 2 hot. Only A still hot, @@ -345,11 +422,11 @@ mod tests { // Fill to the cap with distinct addresses. for i in 0..MAX_ACCESS_LIST_ENTRIES { let address = H160::from_low_u64_be(i as u64); - assert!(al.touch(AccessEntry { address, slot: Slot::Fix([0; 32]) }).is_cold()); + assert!(!al.touch(AccessEntry::Storage { address, slot: Slot::Fix([0; 32]) }).is_hot()); } assert_eq!(al.metrics().size, MAX_ACCESS_LIST_ENTRIES); - let new_entry = AccessEntry { + let new_entry = AccessEntry::Storage { address: H160::from_low_u64_be(MAX_ACCESS_LIST_ENTRIES as u64), slot: Slot::Fix([0; 32]), }; @@ -363,21 +440,21 @@ mod tests { ); al.commit_frame(); assert_eq!(al.metrics().size, MAX_ACCESS_LIST_ENTRIES, "set size stays at cap"); - assert!(al.peek(&new_entry).is_cold(), "past-cap entry is not tracked"); + assert!(!al.peek(&new_entry).is_hot(), "past-cap entry is not tracked"); - assert!(al.touch(new_entry).is_cold(), "past cap re-touch: still cold (not tracked)"); + assert!(!al.touch(new_entry).is_hot(), "past cap re-touch: still cold (not tracked)"); - let existing = AccessEntry { address: H160::zero(), slot: Slot::Fix([0; 32]) }; - assert!(!al.touch(existing).is_cold(), "existing entry still hot at cap"); + let existing = AccessEntry::Storage { address: H160::zero(), slot: Slot::Fix([0; 32]) }; + assert!(al.touch(existing).is_hot(), "existing entry still hot at cap"); } #[test] fn peek_does_not_mutate() { let mut al = AccessList::new(); - let entry = AccessEntry { address: H160::zero(), slot: Slot::Fix([1; 32]) }; + let entry = AccessEntry::Storage { address: H160::zero(), slot: Slot::Fix([1; 32]) }; - assert!(al.peek(&entry).is_cold(), "untouched entry: cold"); - assert!(al.peek(&entry).is_cold(), "repeated query: still cold"); + assert!(!al.peek(&entry).is_hot(), "untouched entry: cold"); + assert!(!al.peek(&entry).is_hot(), "repeated query: still cold"); assert_eq!( al.metrics(), AccessListMetrics { size: 0, cold: 0, hot: 0 }, @@ -386,8 +463,8 @@ mod tests { al.touch(entry.clone()); - assert!(!al.peek(&entry).is_cold(), "after touch: hot"); - assert!(!al.peek(&entry).is_cold(), "repeated query: still hot"); + assert!(al.peek(&entry).is_hot(), "after touch: hot"); + assert!(al.peek(&entry).is_hot(), "repeated query: still hot"); assert_eq!( al.metrics(), AccessListMetrics { size: 1, cold: 1, hot: 0 }, diff --git a/substrate/frame/revive/src/benchmarking.rs b/substrate/frame/revive/src/benchmarking.rs index 5c4ca57bd329..e0e45f1405be 100644 --- a/substrate/frame/revive/src/benchmarking.rs +++ b/substrate/frame/revive/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use crate::{ Pallet as Contracts, - access_list::{AccessEntry, AccessList, MAX_ACCESS_LIST_ENTRIES}, + access_list::{AccessEntry, AccessList, MAX_ACCESS_LIST_ENTRIES, StateAccess}, call_builder::{CallSetup, Contract, VmBinaryModule, caller_funding, default_deposit_limit}, evm::{ TransactionLegacyUnsigned, TransactionSigned, TransactionUnsigned, @@ -192,6 +192,80 @@ mod benchmarks { Ok(()) } + /// A hot call re-reads state already in the proof: exempt the callee's keys. + fn whitelist_callee_keys(callee: &Contract, code_hash: H256) { + for key in [ + frame_system::Account::::hashed_key_for(&callee.account_id), + OriginalAccount::::hashed_key_for(&callee.address), + AccountInfoOf::::hashed_key_for(&callee.address), + CodeInfoOf::::hashed_key_for(&code_hash), + PristineCode::::hashed_key_for(&code_hash), + ] { + frame_benchmarking::benchmarking::add_to_whitelist(key.into()); + } + } + + /// Shared setup of the hot call benches: deploys `$module` as the callee, + /// makes it hot (access list warmed, keys whitelisted), and binds + /// `$do_call` to a zero-value call (or, with the `delegate` prefix, a + /// delegate call) to it. + macro_rules! hot_call_setup { + ($do_call:ident, $module:expr) => { + hot_call_setup!(@setup runtime, memory, callee_len, deposit_len, $module, false); + let mut $do_call = || { + runtime.bench_call( + memory.as_mut_slice(), + pack_hi_lo(0, 0), // flags + callee_ptr + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit + pack_hi_lo(callee_len, callee_len + deposit_len), // deposit_ptr + value_ptr + pack_hi_lo(0, 0), // input_data_len + input_data_ptr + pack_hi_lo(0, SENTINEL), // output_len_ptr + output_ptr (skip) + ) + }; + }; + (delegate $do_call:ident, $module:expr) => { + hot_call_setup!(@setup runtime, memory, callee_len, _deposit_len, $module, true); + let mut $do_call = || { + runtime.bench_delegate_call( + memory.as_mut_slice(), + pack_hi_lo(0, 0), // flags + address_ptr + u64::MAX, // ref_time_limit + u64::MAX, // proof_size_limit + callee_len, // deposit_ptr + pack_hi_lo(0, 0), // input_data_len + input_data_ptr + pack_hi_lo(0, SENTINEL), // output_len_ptr + output_ptr (skip) + ) + }; + }; + (@setup $runtime:ident, $memory:ident, $callee_len:ident, $deposit_len:ident, + $module:expr, $delegate:expr) => { + let callee_contract = Contract::::with_index(1, $module, vec![])?; + let callee = callee_contract.account_id.clone(); + let code_hash = callee_contract.info()?.code_hash; + + whitelist_callee_keys::(&callee_contract, code_hash); + + let callee_bytes = callee.encode(); + let $callee_len = callee_bytes.len() as u32; + + let value_bytes = U256::zero().encode(); + + let deposit: BalanceOf = (u32::MAX - 100).into(); + let deposit_bytes = Into::::into(deposit).encode(); + let $deposit_len = deposit_bytes.len() as u32; + + let mut setup = CallSetup::::default(); + setup.set_storage_deposit_limit(deposit); + setup.set_origin(ExecOrigin::from_account_id(setup.contract().account_id.clone())); + + let (mut ext, _) = setup.ext(); + ext.touch_call_target(StateAccess::call(callee_contract.address, $delegate), code_hash); + let mut $runtime = pvm::Runtime::<_, [u8]>::new(&mut ext, vec![]); + let mut $memory = memory!(callee_bytes, deposit_bytes, value_bytes,); + }; + } + // This benchmarks the overhead of loading a code of size `c` byte from storage and into // the execution engine. // @@ -223,6 +297,20 @@ mod benchmarks { Ok(()) } + #[benchmark(pov_mode = Measured)] + fn call_with_pvm_code_per_byte_hot(c: Linear<0, { 100 * 1024 }>) -> Result<(), BenchmarkError> { + hot_call_setup!(do_call, VmBinaryModule::sized(c)); + + let result; + #[block] + { + result = do_call(); + } + + assert_eq!(result.unwrap(), ReturnErrorCode::Success); + Ok(()) + } + // This benchmarks the overhead of loading a code of size `c` byte from storage and into // the execution engine. /// This is similar to `call_with_pvm_code_per_byte` but for EVM bytecode. @@ -257,6 +345,20 @@ mod benchmarks { Ok(()) } + #[benchmark(pov_mode = Measured)] + fn call_with_evm_code_per_byte_hot(c: Linear<1, { 10 * 1024 }>) -> Result<(), BenchmarkError> { + hot_call_setup!(do_call, VmBinaryModule::evm_init_code_for_runtime_size(c)); + + let result; + #[block] + { + result = do_call(); + } + + assert_eq!(result.unwrap(), ReturnErrorCode::Success); + Ok(()) + } + // Measure the amount of time it takes to compile a single basic block. // // (basic_block_compilation(1) - basic_block_compilation(0)).ref_time() @@ -1965,7 +2067,7 @@ mod benchmarks { fn near_full_access_list() -> crate::access_list::AccessList { let mut al = AccessList::new(); for i in 0..(MAX_ACCESS_LIST_ENTRIES - 1) { - al.touch(AccessEntry { + al.touch(AccessEntry::Storage { slot: worst_case_slot(), address: H160::from_low_u64_be(i as u64), }); @@ -1977,14 +2079,16 @@ mod benchmarks { fn access_list_touch_cold_full() -> Result<(), BenchmarkError> { let mut al = near_full_access_list(); // Insert a new entry (u64::MAX is past the fill range, so the touch is cold). - let entry = - AccessEntry { slot: worst_case_slot(), address: H160::from_low_u64_be(u64::MAX) }; + let entry = AccessEntry::Storage { + slot: worst_case_slot(), + address: H160::from_low_u64_be(u64::MAX), + }; let outcome; #[block] { outcome = al.touch(entry); } - assert!(outcome.is_cold()); + assert!(!outcome.is_hot()); Ok(()) } @@ -1992,42 +2096,46 @@ mod benchmarks { fn access_list_touch_hot_full() -> Result<(), BenchmarkError> { let mut al = near_full_access_list(); // Re-touch an entry that is already present (address zero is in the fill range). - let entry = AccessEntry { slot: worst_case_slot(), address: H160::zero() }; + let entry = AccessEntry::Storage { slot: worst_case_slot(), address: H160::zero() }; let outcome; #[block] { outcome = al.touch(entry); } - assert!(!outcome.is_cold()); + assert!(outcome.is_hot()); Ok(()) } #[benchmark(pov_mode = Ignored)] fn access_list_touch_cold_empty() -> Result<(), BenchmarkError> { let mut al = AccessList::new(); - let entry = - AccessEntry { slot: worst_case_slot(), address: H160::from_low_u64_be(u64::MAX) }; + let entry = AccessEntry::Storage { + slot: worst_case_slot(), + address: H160::from_low_u64_be(u64::MAX), + }; let outcome; #[block] { outcome = al.touch(entry); } - assert!(outcome.is_cold()); + assert!(!outcome.is_hot()); Ok(()) } #[benchmark(pov_mode = Ignored)] fn access_list_touch_hot_single_element() -> Result<(), BenchmarkError> { let mut al = AccessList::new(); - let entry = - AccessEntry { slot: worst_case_slot(), address: H160::from_low_u64_be(u64::MAX) }; + let entry = AccessEntry::Storage { + slot: worst_case_slot(), + address: H160::from_low_u64_be(u64::MAX), + }; al.touch(entry.clone()); let outcome; #[block] { outcome = al.touch(entry); } - assert!(!outcome.is_cold()); + assert!(outcome.is_hot()); Ok(()) } @@ -2038,7 +2146,10 @@ mod benchmarks { fn access_list_rollback_amortization() -> Result<(), BenchmarkError> { let mut al = near_full_access_list(); al.enter_frame(); - al.touch(AccessEntry { slot: worst_case_slot(), address: H160::from_low_u64_be(u64::MAX) }); + al.touch(AccessEntry::Storage { + slot: worst_case_slot(), + address: H160::from_low_u64_be(u64::MAX), + }); #[block] { al.rollback_frame(); @@ -2406,6 +2517,22 @@ mod benchmarks { ); } + // Call a target whose account state, contract metadata, and code are hot, + // as if an identical call already ran in the same transaction. + #[benchmark(pov_mode = Measured)] + fn seal_call_hot() -> Result<(), BenchmarkError> { + hot_call_setup!(do_call, VmBinaryModule::dummy()); + + let result; + #[block] + { + result = do_call(); + } + + assert_eq!(result.unwrap(), ReturnErrorCode::Success); + Ok(()) + } + // d: 1 if the associated pre-compile has a contract info that needs to be loaded // i: size of the input data #[benchmark(pov_mode = Measured)] @@ -2504,6 +2631,21 @@ mod benchmarks { assert_eq!(result.unwrap(), ReturnErrorCode::Success); Ok(()) } + // Delegate-call a target whose contract metadata and code are hot, as if + // an identical delegate call already ran in the same transaction. + #[benchmark(pov_mode = Measured)] + fn seal_delegate_call_hot() -> Result<(), BenchmarkError> { + hot_call_setup!(delegate do_call, VmBinaryModule::dummy()); + + let result; + #[block] + { + result = do_call(); + } + + assert_eq!(result.unwrap(), ReturnErrorCode::Success); + Ok(()) + } // t: with or without some value to transfer // d: with or without dust value to transfer diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 7961f6be88b9..dc0ed2c1f7d1 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -19,7 +19,9 @@ use crate::{ AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, Code, CodeInfo, CodeInfoOf, CodeRemoved, Config, ContractInfo, Error, Event, ImmutableData, ImmutableDataOf, LOG_TARGET, Pallet as Contracts, RuntimeCosts, TrieId, - access_list::{AccessEntry, AccessList, StorageAccessKind}, + access_list::{ + AccessEntry, AccessList, StateAccess, StateAccessKind, StorageAccessKind, Warmth, + }, address::{self, AddressMapper}, deposit_payment::Deposit as _, evm::{block_storage, fees::InfoT as _, transfer_with_dust}, @@ -554,6 +556,9 @@ pub trait PrecompileExt: sealing::Sealed { /// Non-mutating sibling of `touch_storage_access`. fn peek_storage_access(&self, transient: bool, key: &Key) -> StorageAccessKind; + /// Warmth of the state items `opcode` reads. + fn peek_access(&self, opcode: StateAccess) -> StateAccessKind; + /// Charges `diff` from the meter. fn charge_storage(&mut self, diff: &Diff) -> DispatchResult; } @@ -585,10 +590,12 @@ pub trait Executable: Sized { /// Load the executable from storage. /// /// # Note - /// Charges size base load weight from the weight meter. + /// Charges the load from the weight meter; `warmth` picks the cold or + /// hot cost. fn from_storage( code_hash: H256, meter: &mut ResourceMeter, + warmth: Warmth, ) -> Result; /// Load the executable from EVM bytecode @@ -1013,6 +1020,8 @@ where input_data: &Vec, ) -> Result)>, ExecError> { origin.ensure_mapped()?; + // Created before the stack so the first frame's touches land in it. + let mut access_list = AccessList::new(); let Some((first_frame, executable)) = Self::new_frame( args, value, @@ -1022,6 +1031,7 @@ where true, input_data, exec_config, + &mut access_list, )? else { return Ok(None); @@ -1047,13 +1057,22 @@ where first_frame, frames: Default::default(), transient_storage: TransientStorage::new(limits::TRANSIENT_STORAGE_BYTES), - access_list: AccessList::new(), + access_list, exec_config, _phantom: Default::default(), }; Ok(Some((stack, executable))) } + /// Registers the state items `opcode` reads, so later accesses bill hot. + fn touch_access(access_list: &mut AccessList, opcode: StateAccess) { + // Precompile targets are priced without warmth: not registered. + if is_precompile::(&opcode.target()) { + return; + } + opcode.expand(|entry| access_list.touch(entry)); + } + /// Construct a new frame. /// /// This does not take `self` because when constructing the first frame `self` is @@ -1067,12 +1086,24 @@ where origin_is_caller: bool, input_data: &[u8], exec_config: &ExecConfig, + access_list: &mut AccessList, ) -> Result, ExecutableOrPrecompile)>, ExecError> { let (account_id, contract_info, executable, delegate, entry_point) = match frame_args { FrameArgs::Call { dest, cached_info, delegated_call } => { let address = T::AddressMapper::to_address(&dest); let precompile = >::get(address.as_fixed_bytes()); + // Placed after the depth and reentrancy gates, which abort + // before any state is read, and before the contract-info load + // below. That load reads storage even when it finds no contract + // (a plain account): the read is in the PoV, so warming the + // target is correct even when no frame is built. + let access = match &delegated_call { + None => StateAccess::Call { target: address }, + Some(delegated) => StateAccess::DelegateCall { target: delegated.callee }, + }; + Self::touch_access(access_list, access); + // which contract info to load is unaffected by the fact if this // is a delegate call or not let mut contract = match (cached_info, &precompile) { @@ -1115,7 +1146,9 @@ where else { return Ok(None); }; - let executable = E::from_storage(info.code_hash, meter)?; + let code_warmth = + access_list.touch(AccessEntry::Code { hash: info.code_hash }); + let executable = E::from_storage(info.code_hash, meter, code_warmth)?; ExecutableOrPrecompile::Executable(executable) } } else { @@ -1125,13 +1158,12 @@ where _phantom: Default::default(), } } else { - let executable = E::from_storage( - contract - .as_contract() - .expect("When not a precompile the contract was loaded above; qed") - .code_hash, - meter, - )?; + let code_hash = contract + .as_contract() + .expect("When not a precompile the contract was loaded above; qed") + .code_hash; + let code_warmth = access_list.touch(AccessEntry::Code { hash: code_hash }); + let executable = E::from_storage(code_hash, meter, code_warmth)?; ExecutableOrPrecompile::Executable(executable) } }; @@ -1234,6 +1266,7 @@ where false, input_data, self.exec_config, + &mut self.access_list, )? { self.frames.try_push(frame).map_err(|_| Error::::MaxCallDepthReached)?; Ok(Some(executable)) @@ -1901,6 +1934,19 @@ where self.block_number = block_number; } + /// Touches the access-list entries `opcode` reads, plus the code, as if the call already ran. + #[cfg(feature = "runtime-benchmarks")] + pub(crate) fn touch_call_target(&mut self, opcode: StateAccess, code_hash: H256) { + Self::touch_access(&mut self.access_list, opcode); + self.access_list.touch(AccessEntry::Code { hash: code_hash }); + } + + /// Per-transaction access list metrics (testing). + #[cfg(test)] + pub(crate) fn access_list_metrics(&self) -> crate::access_list::AccessListMetrics { + self.access_list.metrics() + } + fn block_hash(&self, block_number: U256) -> Option { let Ok(block_number) = BlockNumberFor::::try_from(block_number) else { return None; @@ -2105,7 +2151,12 @@ where E::from_evm_init_code(initcode, sender.clone())? }, Code::Existing(hash) => { - let executable = E::from_storage(*hash, self.frame_meter_mut())?; + // The code load of an instantiation is always billed cold. + let executable = E::from_storage( + *hash, + self.frame_meter_mut(), + Warmth::cold_nonrevertible(), + )?; ensure!(executable.code_info().is_pvm(), >::EvmConstructedFromHash); executable }, @@ -2614,7 +2665,7 @@ where } let address = self.address(); StorageAccessKind::Persistent( - self.access_list.touch(AccessEntry { address, slot: key.into() }), + self.access_list.touch(AccessEntry::Storage { address, slot: key.into() }), ) } @@ -2624,10 +2675,14 @@ where } let address = self.address(); StorageAccessKind::Persistent( - self.access_list.peek(&AccessEntry { address, slot: key.into() }), + self.access_list.peek(&AccessEntry::Storage { address, slot: key.into() }), ) } + fn peek_access(&self, opcode: StateAccess) -> StateAccessKind { + opcode.expand(|entry| self.access_list.peek(&entry)) + } + fn charge_storage(&mut self, diff: &Diff) -> DispatchResult { assert!(self.has_contract_info()); self.top_frame_mut().frame_meter.record_contract_storage_changes(diff) diff --git a/substrate/frame/revive/src/exec/mock_ext.rs b/substrate/frame/revive/src/exec/mock_ext.rs index 621a2cc377b6..6712ec8309b5 100644 --- a/substrate/frame/revive/src/exec/mock_ext.rs +++ b/substrate/frame/revive/src/exec/mock_ext.rs @@ -272,6 +272,13 @@ impl PrecompileExt for MockExt { panic!("MockExt::peek_storage_access") } + fn peek_access( + &self, + _opcode: crate::access_list::StateAccess, + ) -> crate::access_list::StateAccessKind { + panic!("MockExt::peek_access") + } + fn charge_storage(&mut self, _diff: &Diff) -> DispatchResult { Ok(()) } diff --git a/substrate/frame/revive/src/exec/tests.rs b/substrate/frame/revive/src/exec/tests.rs index a528c33e7e92..c864793d5bd8 100644 --- a/substrate/frame/revive/src/exec/tests.rs +++ b/substrate/frame/revive/src/exec/tests.rs @@ -23,7 +23,9 @@ use super::*; use crate::{ AddressMapper, Error, Pallet, ReentrancyProtection, - access_list::{MAX_ACCESS_LIST_ENTRIES, MAX_INLINE_KEY_LEN, Warmth}, + access_list::{ + MAX_ACCESS_LIST_ENTRIES, MAX_INLINE_KEY_LEN, StateAccess, StateAccessKind, Warmth, + }, exec::ExportedFunction::*, metering::TransactionMeter, test_utils::*, @@ -142,6 +144,7 @@ impl Executable for MockExecutable { fn from_storage( code_hash: H256, _meter: &mut ResourceMeter, + _warmth: Warmth, ) -> Result { Loader::mutate(|loader| { loader.map.get(&code_hash).cloned().ok_or(Error::::CodeNotFound.into()) @@ -200,6 +203,14 @@ fn exec_trapped() -> ExecResult { Err(ExecError { error: >::ContractTrapped.into(), origin: ErrorOrigin::Callee }) } +/// `MockExecutable::from_storage` with a cold, non-revertible warmth. +fn from_storage_cold( + code_hash: H256, + meter: &mut crate::metering::ResourceMeter, +) -> Result { + MockExecutable::from_storage(code_hash, meter, Warmth::cold_nonrevertible()) +} + #[test] fn it_works() { parameter_types! { @@ -621,7 +632,7 @@ fn input_data_to_instantiate() { TransactionMeter::::new_from_limits(WEIGHT_LIMIT, deposit_limit::()) .unwrap(); - let executable = MockExecutable::from_storage(input_data_ch, &mut meter).unwrap(); + let executable = from_storage_cold(input_data_ch, &mut meter).unwrap(); set_balance(&ALICE, min_balance * 10_000); let result = MockStack::run_instantiate( @@ -1092,7 +1103,7 @@ fn refuse_instantiate_with_value_below_existential_deposit() { ExtBuilder::default().existential_deposit(15).build().execute_with(|| { let mut meter = TransactionMeter::::new_from_limits(WEIGHT_LIMIT, 0).unwrap(); - let executable = MockExecutable::from_storage(dummy_ch, &mut meter).unwrap(); + let executable = from_storage_cold(dummy_ch, &mut meter).unwrap(); assert_matches!( MockStack::run_instantiate( @@ -1124,7 +1135,7 @@ fn instantiation_work_with_success_output() { set_balance(&ALICE, min_balance * 1000); let mut meter = TransactionMeter::::new_from_limits(WEIGHT_LIMIT, min_balance * 100).unwrap(); - let executable = MockExecutable::from_storage(dummy_ch, &mut meter).unwrap(); + let executable = from_storage_cold(dummy_ch, &mut meter).unwrap(); let instantiated_contract_address = assert_matches!( MockStack::run_instantiate( @@ -1173,7 +1184,7 @@ fn instantiation_fails_with_failing_output() { let min_balance = ::Currency::minimum_balance(); let mut meter = TransactionMeter::::new_from_limits(WEIGHT_LIMIT, min_balance * 100).unwrap(); - let executable = MockExecutable::from_storage(dummy_ch, &mut meter).unwrap(); + let executable = from_storage_cold(dummy_ch, &mut meter).unwrap(); set_balance(&ALICE, min_balance * 1000); let instantiated_contract_address = assert_matches!( @@ -1334,7 +1345,7 @@ fn termination_from_instantiate_succeeds() { let mut meter = TransactionMeter::::new_from_limits(WEIGHT_LIMIT, deposit_limit::()) .unwrap(); - let executable = MockExecutable::from_storage(terminate_ch, &mut meter).unwrap(); + let executable = from_storage_cold(terminate_ch, &mut meter).unwrap(); set_balance(&ALICE, 10_000); let result = MockStack::run_instantiate( @@ -1520,7 +1531,7 @@ fn recursive_call_during_constructor_is_balance_transfer() { let mut meter = TransactionMeter::::new_from_limits(WEIGHT_LIMIT, deposit_limit::()) .unwrap(); - let executable = MockExecutable::from_storage(code, &mut meter).unwrap(); + let executable = from_storage_cold(code, &mut meter).unwrap(); set_balance(&ALICE, min_balance * 10_000); let result = MockStack::run_instantiate( @@ -1704,8 +1715,7 @@ fn minimum_balance_must_return_converted_balance() { let mut meter = TransactionMeter::::new_from_limits(WEIGHT_LIMIT, deposit_limit::()) .unwrap(); - let succ_fail_executable = - MockExecutable::from_storage(succ_fail_code, &mut meter).unwrap(); + let succ_fail_executable = from_storage_cold(succ_fail_code, &mut meter).unwrap(); set_balance(&ALICE, min_balance * 10_000); assert_ok!(MockStack::run_instantiate( @@ -1787,13 +1797,10 @@ fn nonce() { let mut meter = TransactionMeter::::new_from_limits(WEIGHT_LIMIT, deposit_limit::()) .unwrap(); - let fail_executable = MockExecutable::from_storage(fail_code, &mut meter).unwrap(); - let success_executable = - MockExecutable::from_storage(success_code, &mut meter).unwrap(); - let succ_fail_executable = - MockExecutable::from_storage(succ_fail_code, &mut meter).unwrap(); - let succ_succ_executable = - MockExecutable::from_storage(succ_succ_code, &mut meter).unwrap(); + let fail_executable = from_storage_cold(fail_code, &mut meter).unwrap(); + let success_executable = from_storage_cold(success_code, &mut meter).unwrap(); + let succ_fail_executable = from_storage_cold(succ_fail_code, &mut meter).unwrap(); + let succ_succ_executable = from_storage_cold(succ_succ_code, &mut meter).unwrap(); set_balance(&ALICE, min_balance * 10_000); set_balance(&BOB, min_balance * 10_000); @@ -2840,7 +2847,7 @@ fn immutable_data_set_overrides() { let addr = MockStack::run_instantiate( ALICE, - MockExecutable::from_storage(hash, &mut meter).unwrap(), + from_storage_cold(hash, &mut meter).unwrap(), &mut meter, U256::zero(), vec![], @@ -3212,9 +3219,10 @@ fn cold_hot_revertible_only_inside_nested_frame() { #[test] fn cold_hot_past_cap_touch_is_not_revertible() { let child_code_hash = MockLoader::insert(Call, |ctx, _| { - // Fill the access list to its cap with distinct slots. Each is below the - // cap when touched, so it journals and is revertible. - for i in 0..MAX_ACCESS_LIST_ENTRIES as u32 { + // Fill the remaining access list capacity with distinct slots. Each + // slot is below the cap when touched, so it journals and is revertible. + let already_tracked = ctx.ext.access_list_metrics().size; + for i in 0..(MAX_ACCESS_LIST_ENTRIES - already_tracked) as u32 { let mut slot = [0u8; 32]; slot[..4].copy_from_slice(&i.to_le_bytes()); assert_matches!( @@ -3299,3 +3307,194 @@ fn cold_hot_3level_commit_then_revert_drops_committed() { run_root_call(CHARLIE_ADDR, vec![]); }); } + +#[test] +fn cold_hot_call_target_warms_across_calls() { + // The second call to the same target prices its account state, contract + // metadata, and code as hot. + let child_code_hash = MockLoader::insert(Call, |_, _| exec_success()); + + let root_code_hash = MockLoader::insert(Call, |ctx, _| { + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), + StateAccessKind::Call { + account: Warmth::Cold { .. }, + contract_info: Warmth::Cold { .. } + }, + "an uncalled target starts cold", + ); + let before = ctx.ext.access_list_metrics(); + + assert_matches!(run_child_call(ctx.ext, &BOB_ADDR, vec![]), Ok(_)); + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), + StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + "account state and contract metadata are hot after the first call", + ); + let mid = ctx.ext.access_list_metrics(); + assert_eq!( + mid.cold - before.cold, + 3, + "first call: account + contract info + code touch cold", + ); + assert_eq!(mid.hot, before.hot, "first call adds no hot touches"); + + assert_matches!(run_child_call(ctx.ext, &BOB_ADDR, vec![]), Ok(_)); + let after = ctx.ext.access_list_metrics(); + assert_eq!(after.hot - mid.hot, 3, "second call: account + contract info + code hot"); + assert_eq!(after.cold, mid.cold, "second call adds no cold touches"); + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + place_contract(&BOB, child_code_hash); + place_contract(&CHARLIE, root_code_hash); + run_root_call(CHARLIE_ADDR, vec![]); + }); +} + +#[test] +fn cold_hot_delegate_call_leaves_target_account_cold() { + // A delegate call reads only the target's contract metadata and code, so + // a later plain call to the same target still prices the account state + // cold. + let child_code_hash = MockLoader::insert(Call, |_, _| exec_success()); + + let root_code_hash = MockLoader::insert(Call, |ctx, _| { + let before = ctx.ext.access_list_metrics(); + assert_matches!(ctx.ext.delegate_call(&CallResources::NoLimits, BOB_ADDR, vec![]), Ok(_)); + let after = ctx.ext.access_list_metrics(); + assert_eq!(after.cold - before.cold, 2, "delegate call: contract info + code touch cold"); + assert_eq!(after.hot, before.hot, "delegate call adds no hot touches"); + assert_matches!( + ctx.ext.peek_access(StateAccess::DelegateCall { target: BOB_ADDR }), + StateAccessKind::DelegateCall { contract_info: Warmth::Hot } + ); + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), + StateAccessKind::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Hot }, + "delegate call warms contract metadata but not account state", + ); + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + place_contract(&BOB, child_code_hash); + place_contract(&CHARLIE, root_code_hash); + run_root_call(CHARLIE_ADDR, vec![]); + }); +} + +#[test] +fn cold_hot_reverted_caller_drops_target_warmth_but_keeps_own() { + // B calls DJANGO and then reverts: DJANGO's warmth (touched while B ran) + // is dropped, while B's own warmth (touched by root before B ran) + // persists — the caller's touch of a target survives the target's revert. + let grandchild_code_hash = MockLoader::insert(Call, |_, _| exec_success()); + + let b_code_hash = MockLoader::insert(Call, |ctx, _| { + assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); + Err("revert B".into()) + }); + + let root_code_hash = MockLoader::insert(Call, |ctx, _| { + let _ = run_child_call(ctx.ext, &BOB_ADDR, vec![]); + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), + StateAccessKind::Call { + account: Warmth::Cold { .. }, + contract_info: Warmth::Cold { .. } + }, + "B's revert drops the warmth of targets B touched", + ); + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), + StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + "the caller's touch of B persists even though B reverted", + ); + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + place_contract(&DJANGO, grandchild_code_hash); + place_contract(&BOB, b_code_hash); + place_contract(&CHARLIE, root_code_hash); + run_root_call(CHARLIE_ADDR, vec![]); + }); +} + +#[test] +fn cold_hot_call_to_plain_account_warms_target() { + // Calling an address without code still warms its account state and the + // contract-info absence proof; no code entry is added. + let root_code_hash = MockLoader::insert(Call, |ctx, _| { + let plain_account = H160::from_low_u64_be(0x777); + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: plain_account }), + StateAccessKind::Call { + account: Warmth::Cold { .. }, + contract_info: Warmth::Cold { .. } + } + ); + let before = ctx.ext.access_list_metrics(); + + assert_matches!(run_child_call(ctx.ext, &plain_account, vec![]), Ok(_)); + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: plain_account }), + StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + "a call to a plain account warms it", + ); + let after = ctx.ext.access_list_metrics(); + assert_eq!(after.cold - before.cold, 2, "account + contract info; no code entry"); + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + place_contract(&BOB, root_code_hash); + run_root_call(BOB_ADDR, vec![]); + }); +} + +#[test] +fn cold_hot_shared_code_hash_is_hot_across_addresses() { + // Two contracts share one code hash: calling the second prices its + // account entries cold, but the shared code blob is already hot. + let shared_code_hash = MockLoader::insert(Call, |_, _| exec_success()); + + let root_code_hash = MockLoader::insert(Call, |ctx, _| { + assert_matches!(run_child_call(ctx.ext, &BOB_ADDR, vec![]), Ok(_)); + let mid = ctx.ext.access_list_metrics(); + + assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); + let after = ctx.ext.access_list_metrics(); + assert_eq!(after.cold - mid.cold, 2, "second address: account + contract info cold"); + assert_eq!(after.hot - mid.hot, 1, "second address: shared code blob hot"); + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + place_contract(&BOB, shared_code_hash); + place_contract(&DJANGO, shared_code_hash); + place_contract(&CHARLIE, root_code_hash); + run_root_call(CHARLIE_ADDR, vec![]); + }); +} + +#[test] +fn cold_hot_first_frame_warms_entry_target() { + // The first frame's touches are seeded at stack creation, so a reentrant + // self-call prices hot. + let root_code_hash = MockLoader::insert(Call, |ctx, _| { + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), + StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + "the entry target's entries are seeded by the first frame", + ); + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + place_contract(&BOB, root_code_hash); + run_root_call(BOB_ADDR, vec![]); + }); +} diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 48fb0cde4e17..8026542925f9 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -1886,7 +1886,12 @@ impl Pallet { } }, Code::Existing(code_hash) => { - let executable = ContractBlob::from_storage(code_hash, &mut transaction_meter)?; + // The code load of an instantiation is always billed cold. + let executable = ContractBlob::from_storage( + code_hash, + &mut transaction_meter, + access_list::Warmth::cold_nonrevertible(), + )?; ensure!(executable.code_info().is_pvm(), >::EvmConstructedFromHash); executable }, diff --git a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs index 9821973df163..05f92a34c7e0 100644 --- a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs +++ b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs @@ -17,6 +17,7 @@ use crate::{ Pallet, RuntimeCosts, + access_list::StateAccess, precompiles::{All as AllPrecompiles, Precompiles}, vm::{ Ext, @@ -83,12 +84,13 @@ pub fn charge_call_gas<'a, E: Ext>( .charge_or_halt(RuntimeCosts::PrecompileDecode(input_len as u32))?; }, None => { - // Regular CALL / DELEGATECALL base cost / CALLCODE not supported - interpreter.ext.charge_or_halt(if scheme.is_delegate_call() { - RuntimeCosts::DelegateCallBase - } else { - RuntimeCosts::CallBase - })?; + // Regular CALL / DELEGATECALL base cost / CALLCODE not supported. + + // Charged from the current access-list state; the list is updated + // during frame execution. + let access = StateAccess::call(callee, scheme.is_delegate_call()); + let cost = RuntimeCosts::CallBase(interpreter.ext.peek_access(access)); + interpreter.ext.charge_or_halt(cost)?; interpreter .ext diff --git a/substrate/frame/revive/src/vm/mod.rs b/substrate/frame/revive/src/vm/mod.rs index 41f38805f228..622a0a53e4d4 100644 --- a/substrate/frame/revive/src/vm/mod.rs +++ b/substrate/frame/revive/src/vm/mod.rs @@ -26,7 +26,9 @@ pub use runtime_costs::RuntimeCosts; use crate::{ AccountIdOf, BalanceOf, CodeInfoOf, CodeRemoved, Config, Error, ExecConfig, ExecError, - HoldReason, LOG_TARGET, Pallet, PristineCode, StorageDeposit, Weight, deposit_payment, + HoldReason, LOG_TARGET, Pallet, PristineCode, StorageDeposit, Weight, + access_list::Warmth, + deposit_payment, exec::{ExecResult, Executable, ExportedFunction, Ext}, frame_support::ensure, metering::{ResourceMeter, State, Token}, @@ -123,36 +125,52 @@ impl ExportedFunction { struct CodeLoadToken { code_len: u32, code_type: BytecodeType, + warmth: Warmth, } impl CodeLoadToken { - fn from_code_info(code_info: &CodeInfo) -> Self { - Self { code_len: code_info.code_len, code_type: code_info.code_type } + fn from_code_info(code_info: &CodeInfo, warmth: Warmth) -> Self { + Self { code_len: code_info.code_len, code_type: code_info.code_type, warmth } } } impl Token for CodeLoadToken { fn weight(&self) -> Weight { + let size_cost = |bench: fn(u32) -> Weight| bench(self.code_len).saturating_sub(bench(0)); + let base = runtime_costs::warm_base::( + &[self.warmth], + runtime_costs::CostPair { + cold: || match self.code_type { + BytecodeType::Pvm => size_cost(T::WeightInfo::call_with_pvm_code_per_byte), + BytecodeType::Evm => size_cost(T::WeightInfo::call_with_evm_code_per_byte), + }, + hot: || match self.code_type { + BytecodeType::Pvm => size_cost(T::WeightInfo::call_with_pvm_code_per_byte_hot), + BytecodeType::Evm => size_cost(T::WeightInfo::call_with_evm_code_per_byte_hot), + }, + }, + ); match self.code_type { // the proof size impact is accounted for in the `call_with_pvm_code_per_byte` // strictly speaking we are double charging for the first BASIC_BLOCK_SIZE // instructions here. Let's consider this as a safety margin. - BytecodeType::Pvm => T::WeightInfo::call_with_pvm_code_per_byte(self.code_len) - .saturating_sub(T::WeightInfo::call_with_pvm_code_per_byte(0)) - .saturating_add( - T::WeightInfo::basic_block_compilation(1) - .saturating_sub(T::WeightInfo::basic_block_compilation(0)) - .set_proof_size(0), - ), - BytecodeType::Evm => T::WeightInfo::call_with_evm_code_per_byte(self.code_len) - .saturating_sub(T::WeightInfo::call_with_evm_code_per_byte(0)), + BytecodeType::Pvm => base.saturating_add( + T::WeightInfo::basic_block_compilation(1) + .saturating_sub(T::WeightInfo::basic_block_compilation(0)) + .set_proof_size(0), + ), + BytecodeType::Evm => base, } } } #[cfg(test)] pub fn code_load_weight(code_len: u32) -> Weight { - Token::::weight(&CodeLoadToken { code_len, code_type: BytecodeType::Pvm }) + Token::::weight(&CodeLoadToken { + code_len, + code_type: BytecodeType::Pvm, + warmth: Warmth::cold_nonrevertible(), + }) } impl ContractBlob { @@ -326,9 +344,10 @@ impl Executable for ContractBlob { fn from_storage( code_hash: H256, meter: &mut ResourceMeter, + warmth: Warmth, ) -> Result { let code_info = >::get(code_hash).ok_or(Error::::CodeNotFound)?; - meter.charge_weight_token(CodeLoadToken::from_code_info(&code_info))?; + meter.charge_weight_token(CodeLoadToken::from_code_info(&code_info, warmth))?; let code = >::get(&code_hash).ok_or(Error::::CodeNotFound)?; Ok(Self { code, code_info, code_hash }) } @@ -395,3 +414,33 @@ pub(crate) fn exec_error_into_return_code( (err, _) => Err(err), } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::Test; + + #[test] + fn code_load_cold_hot_pricing() { + let weight_of = |code_type, warmth| { + Token::::weight(&CodeLoadToken { code_len: 1024, code_type, warmth }) + }; + + for code_type in [BytecodeType::Pvm, BytecodeType::Evm] { + let cold = weight_of(code_type, Warmth::cold_nonrevertible()); + let hot = weight_of(code_type, Warmth::Hot); + let cold_revertible = weight_of(code_type, Warmth::Cold { revertible: true }); + assert!( + cold.ref_time() > hot.ref_time(), + "expected cold > hot ref_time for {code_type:?}: cold={cold:?} hot={hot:?}", + ); + assert!(cold.proof_size() > 0, "cold proof_size {code_type:?}: {cold:?}"); + assert_eq!(hot.proof_size(), 0, "hot proof_size {code_type:?}: {hot:?}"); + assert!( + cold_revertible.ref_time() > cold.ref_time(), + "expected revertible > non-revertible ref_time for {code_type:?}: \ + rev={cold_revertible:?} non={cold:?}", + ); + } + } +} diff --git a/substrate/frame/revive/src/vm/pvm.rs b/substrate/frame/revive/src/vm/pvm.rs index 70449296b9fd..65979e24e0b7 100644 --- a/substrate/frame/revive/src/vm/pvm.rs +++ b/substrate/frame/revive/src/vm/pvm.rs @@ -21,6 +21,7 @@ pub mod env; use crate::{ Code, Config, Error, LOG_TARGET, Pallet, ReentrancyProtection, RuntimeCosts, SENTINEL, + access_list::StateAccess, exec::{CallResources, ExecError, ExecResult, Ext, Key}, limits, metering::ChargedAmount, @@ -278,11 +279,11 @@ enum CallType { } impl CallType { - fn cost(&self) -> RuntimeCosts { - match self { - CallType::Call { .. } => RuntimeCosts::CallBase, - CallType::DelegateCall => RuntimeCosts::DelegateCallBase, - } + /// Base cost of the call, charged from the current access-list state; + /// the list is updated during frame execution. + fn cost(&self, ext: &impl Ext, callee: &sp_core::H160) -> RuntimeCosts { + let access = StateAccess::call(*callee, matches!(self, CallType::DelegateCall)); + RuntimeCosts::CallBase(ext.peek_access(access)) } } @@ -493,8 +494,8 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { let key = self.decode_key(memory, key_ptr, key_len)?; if value_len > max_size { - // Don't warm the slot on a failed validation as the storage was not accessed. - let access_kind = self.ext.peek_storage_access(transient, &key); + // A peek registers nothing, so no rollback is owed: strip the prepayment. + let access_kind = self.ext.peek_storage_access(transient, &key).non_revertible(); self.charge_gas(RuntimeCosts::SetStorage { new_bytes: value_len, old_bytes: max_size, @@ -645,7 +646,10 @@ impl<'a, E: Ext, M: ?Sized + Memory> Runtime<'a, E, M> { self.charge_gas(RuntimeCosts::PrecompileWithInfoBase)? }, Some(_) => self.charge_gas(RuntimeCosts::PrecompileBase)?, - None => self.charge_gas(call_type.cost())?, + None => { + let cost = call_type.cost(&*self.ext, &callee); + self.charge_gas(cost)? + }, }; // we do check this in exec.rs but we want to error out early diff --git a/substrate/frame/revive/src/vm/runtime_costs.rs b/substrate/frame/revive/src/vm/runtime_costs.rs index 4b7a1a84201e..71888105a60c 100644 --- a/substrate/frame/revive/src/vm/runtime_costs.rs +++ b/substrate/frame/revive/src/vm/runtime_costs.rs @@ -17,7 +17,7 @@ use crate::{ Config, - access_list::{StorageAccessKind, Warmth}, + access_list::{StateAccessKind, StorageAccessKind, Warmth}, limits, metering::Token, weightinfo_extension::OnFinalizeBlockParts, @@ -114,10 +114,8 @@ pub enum RuntimeCosts { GetStorage { len: u32, kind: StorageAccessKind }, /// Weight of the `takeStorage` precompile / `seal_take_transient_storage`. TakeStorage { len: u32, kind: StorageAccessKind }, - /// Base weight of calling `seal_call`. - CallBase, - /// Weight of calling `seal_delegate_call` for the given input size. - DelegateCallBase, + /// Base weight of a call-family opcode. + CallBase(StateAccessKind), /// Weight of calling a precompile. PrecompileBase, /// Weight of calling a precompile that has a contract info. @@ -217,7 +215,7 @@ macro_rules! cost_args { } impl RuntimeCosts { - /// Extra ref_time a hot storage access pays to look up the block's overlay. + /// Extra ref_time a hot state read pays to look up the block's overlay. fn hot_storage_overlay_overhead() -> Weight { let per_read = |weight_fn: fn(u32) -> Weight| weight_fn(1).saturating_sub(weight_fn(0)); per_read(T::WeightInfo::overlay_probe_full) @@ -232,25 +230,62 @@ impl RuntimeCosts { transient: impl FnOnce() -> Weight, ) -> Weight { match kind { - StorageAccessKind::Persistent(Warmth::Cold { revertible }) => { - let cost = cold() - .saturating_add(T::WeightInfo::access_list_touch_cold_full()) - .saturating_sub(T::WeightInfo::access_list_touch_cold_empty()); - if revertible { - cost.saturating_add(T::WeightInfo::access_list_rollback_amortization()) - } else { - cost - } + StorageAccessKind::Persistent(warmth) => { + warm_base::(&[warmth], CostPair { cold, hot }) }, - StorageAccessKind::Persistent(Warmth::Hot) => hot() - .saturating_add(Self::hot_storage_overlay_overhead::()) - .saturating_add(T::WeightInfo::access_list_touch_hot_full()) - .saturating_sub(T::WeightInfo::access_list_touch_hot_single_element()), StorageAccessKind::Transient => transient(), } } } +/// Bookkeeping weight of one access-list touch, plus the prepaid rollback +/// for a revertible cold insert. +pub(crate) fn access_list_overhead(warmth: Warmth) -> Weight { + let touch_cost = |bench: fn() -> Weight, base: fn() -> Weight| bench().saturating_sub(base()); + match warmth { + Warmth::Cold { revertible } => { + let cost = touch_cost( + T::WeightInfo::access_list_touch_cold_full, + T::WeightInfo::access_list_touch_cold_empty, + ); + if revertible { + cost.saturating_add(T::WeightInfo::access_list_rollback_amortization()) + } else { + cost + } + }, + Warmth::Hot => touch_cost( + T::WeightInfo::access_list_touch_hot_full, + T::WeightInfo::access_list_touch_hot_single_element, + ), + } +} + +/// Cold and hot benches of a warmth-priced base; named so call sites cannot swap them. +pub(crate) struct CostPair { + pub cold: Cold, + pub hot: Hot, +} + +/// Warmth-priced base of an opcode touching `items`: the hot bench applies +/// only when every item is hot (mixed warmth rounds up to the cold bench), +/// plus the per-item access-list overhead. +pub(crate) fn warm_base( + items: &[Warmth], + costs: CostPair Weight, impl FnOnce() -> Weight>, +) -> Weight { + let base = if items.iter().all(|warmth| warmth.is_hot()) { + // The hot benches run at an empty overlay; a single lookup is + // charged as an approximation. + (costs.hot)().saturating_add(RuntimeCosts::hot_storage_overlay_overhead::()) + } else { + (costs.cold)() + }; + items + .iter() + .fold(base, |base, warmth| base.saturating_add(access_list_overhead::(*warmth))) +} + impl Token for RuntimeCosts { fn influence_lowest_weight_limit(&self) -> bool { true @@ -338,8 +373,22 @@ impl Token for RuntimeCosts { || T::WeightInfo::take_storage_hot(len), || cost_storage!(write_transient, seal_take_transient_storage, len), ), - CallBase => T::WeightInfo::seal_call(0, 0, 0), - DelegateCallBase => T::WeightInfo::seal_delegate_call(), + CallBase(warmth) => match warmth { + StateAccessKind::Call { account, contract_info } => warm_base::( + &[account, contract_info], + CostPair { + cold: || T::WeightInfo::seal_call(0, 0, 0), + hot: T::WeightInfo::seal_call_hot, + }, + ), + StateAccessKind::DelegateCall { contract_info } => warm_base::( + &[contract_info], + CostPair { + cold: T::WeightInfo::seal_delegate_call, + hot: T::WeightInfo::seal_delegate_call_hot, + }, + ), + }, PrecompileBase => T::WeightInfo::seal_call_precompile(0, 0), PrecompileWithInfoBase => T::WeightInfo::seal_call_precompile(1, 0), PrecompileDecode(len) => cost_args!(seal_call_precompile, 0, len), @@ -391,7 +440,7 @@ mod tests { #[test] fn cold_hot_pricing_cold_is_strictly_more_expensive_than_hot() { let len = 64u32; - let cold = StorageAccessKind::Persistent(Warmth::Cold { revertible: false }); + let cold = StorageAccessKind::Persistent(Warmth::cold_nonrevertible()); let cold_revertible = StorageAccessKind::Persistent(Warmth::Cold { revertible: true }); let hot = StorageAccessKind::Persistent(Warmth::Hot); @@ -433,6 +482,56 @@ mod tests { } } + #[test] + fn call_base_cold_hot_pricing() { + let hot = Warmth::Hot; + let cold = Warmth::cold_nonrevertible(); + let cold_revertible = Warmth::Cold { revertible: true }; + let weight_of = |cost: RuntimeCosts| >::weight(&cost); + + let all_hot = weight_of(RuntimeCosts::CallBase(StateAccessKind::Call { + account: hot, + contract_info: hot, + })); + let all_cold = weight_of(RuntimeCosts::CallBase(StateAccessKind::Call { + account: cold, + contract_info: cold, + })); + let mixed = weight_of(RuntimeCosts::CallBase(StateAccessKind::Call { + account: cold, + contract_info: hot, + })); + + assert!( + all_cold.ref_time() >= all_hot.ref_time(), + "cold call must not be cheaper than hot: cold={all_cold:?} hot={all_hot:?}", + ); + assert_eq!(all_hot.proof_size(), 0, "hot call adds nothing to the proof: {all_hot:?}"); + assert!(all_cold.proof_size() > 0, "cold call pays proof size: {all_cold:?}"); + assert!(mixed.proof_size() > 0, "any cold item prices the full cold base: {mixed:?}",); + + let revertible = weight_of(RuntimeCosts::CallBase(StateAccessKind::Call { + account: cold_revertible, + contract_info: cold, + })); + assert!( + revertible.ref_time() > all_cold.ref_time(), + "a revertible cold touch prepays the rollback: rev={revertible:?} cold={all_cold:?}", + ); + + let delegate_hot = + weight_of(RuntimeCosts::CallBase(StateAccessKind::DelegateCall { contract_info: hot })); + let delegate_cold = weight_of(RuntimeCosts::CallBase(StateAccessKind::DelegateCall { + contract_info: cold, + })); + assert!( + delegate_cold.ref_time() >= delegate_hot.ref_time(), + "cold delegate call must not be cheaper than hot: cold={delegate_cold:?} hot={delegate_hot:?}", + ); + assert_eq!(delegate_hot.proof_size(), 0, "hot delegate call: {delegate_hot:?}"); + assert!(delegate_cold.proof_size() > 0, "cold delegate call: {delegate_cold:?}"); + } + #[test] fn hot_storage_overlay_overhead_is_not_zero() { let overhead = RuntimeCosts::hot_storage_overlay_overhead::(); diff --git a/substrate/frame/revive/src/weights.rs b/substrate/frame/revive/src/weights.rs index 7da6800db0c1..d64ec898b395 100644 --- a/substrate/frame/revive/src/weights.rs +++ b/substrate/frame/revive/src/weights.rs @@ -77,6 +77,8 @@ pub trait WeightInfo { fn deletion_queue_per_native_deposit_key(k: u32, ) -> Weight; fn call_with_pvm_code_per_byte(c: u32, ) -> Weight; fn call_with_evm_code_per_byte(c: u32, ) -> Weight; + fn call_with_pvm_code_per_byte_hot(c: u32, ) -> Weight; + fn call_with_evm_code_per_byte_hot(c: u32, ) -> Weight; fn basic_block_compilation(b: u32, ) -> Weight; fn instantiate_with_code(c: u32, i: u32, ) -> Weight; fn eth_instantiate_with_code(c: u32, i: u32, d: u32, ) -> Weight; @@ -158,6 +160,8 @@ pub trait WeightInfo { fn seal_contains_transient_storage(n: u32, ) -> Weight; fn seal_take_transient_storage(n: u32, ) -> Weight; fn seal_call(t: u32, d: u32, i: u32, ) -> Weight; + fn seal_call_hot() -> Weight; + fn seal_delegate_call_hot() -> Weight; fn seal_call_precompile(d: u32, i: u32, ) -> Weight; fn seal_delegate_call() -> Weight; fn seal_instantiate(t: u32, d: u32, i: u32, ) -> Weight; @@ -302,6 +306,22 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot load re-reads a blob already in the proof). + fn call_with_pvm_code_per_byte_hot(c: u32, ) -> Weight { + Weight::from_parts(148_471_832, 0) + .saturating_add(Weight::from_parts(1_601, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot load re-reads a blob already in the proof). + fn call_with_evm_code_per_byte_hot(c: u32, ) -> Weight { + Weight::from_parts(99_411_753, 0) + .saturating_add(Weight::from_parts(1_741, 0).saturating_mul(c.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:2 w:0) @@ -1324,6 +1344,19 @@ impl WeightInfo for SubstrateWeight { Weight::from_parts(30_587_000, 4214) .saturating_add(T::DbWeight::get().reads(3_u64)) } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot call re-reads state already in the proof). + fn seal_call_hot() -> Weight { + Weight::from_parts(70_070_774, 0) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot call re-reads state already in the proof). + fn seal_delegate_call_hot() -> Weight { + Weight::from_parts(30_587_000, 0) + .saturating_add(T::DbWeight::get().reads(3_u64)) + } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) @@ -1849,6 +1882,22 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot load re-reads a blob already in the proof). + fn call_with_pvm_code_per_byte_hot(c: u32, ) -> Weight { + Weight::from_parts(148_471_832, 0) + .saturating_add(Weight::from_parts(1_601, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot load re-reads a blob already in the proof). + fn call_with_evm_code_per_byte_hot(c: u32, ) -> Weight { + Weight::from_parts(99_411_753, 0) + .saturating_add(Weight::from_parts(1_741, 0).saturating_mul(c.into())) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:2 w:0) @@ -2871,6 +2920,19 @@ impl WeightInfo for () { Weight::from_parts(30_587_000, 4214) .saturating_add(RocksDbWeight::get().reads(3_u64)) } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot call re-reads state already in the proof). + fn seal_call_hot() -> Weight { + Weight::from_parts(70_070_774, 0) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time + // with the proof size zeroed (a hot call re-reads state already in the proof). + fn seal_delegate_call_hot() -> Weight { + Weight::from_parts(30_587_000, 0) + .saturating_add(RocksDbWeight::get().reads(3_u64)) + } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) From 80e55ece96f7dfa5e5f366d82d2a47dd38386340 Mon Sep 17 00:00:00 2001 From: Marian Radu Date: Thu, 16 Jul 2026 18:33:09 +0300 Subject: [PATCH 2/9] pallet-revive: account for code metadata warmth and overlay probes --- .../src/weights/pallet_revive.rs | 6 ++ substrate/frame/revive/src/access_list.rs | 44 +++++++++++-- substrate/frame/revive/src/benchmarking.rs | 53 +++++++++++++--- substrate/frame/revive/src/exec.rs | 49 ++++++--------- substrate/frame/revive/src/exec/tests.rs | 55 ++++++++++++++--- substrate/frame/revive/src/lib.rs | 2 +- substrate/frame/revive/src/vm/mod.rs | 61 ++++++++++++++----- .../frame/revive/src/vm/runtime_costs.rs | 14 +++-- substrate/frame/revive/src/weights.rs | 13 ++++ 9 files changed, 227 insertions(+), 70 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs index dc41e926a8c1..afcd8ac7599e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs @@ -1322,6 +1322,12 @@ impl pallet_revive::WeightInfo for WeightInfo { .saturating_add(Weight::from_parts(0, 4212)) .saturating_add(T::DbWeight::get().reads(3)) } + // Placeholder until `/cmd bench` runs the `code_load` benchmark: proof-only + // over-approximation reusing seal_delegate_call's {AccountInfoOf, CodeInfoOf, + // PristineCode} proof, which is a superset of the {CodeInfoOf, PristineCode} read. + fn code_load() -> Weight { + Weight::from_parts(0, Self::seal_delegate_call().proof_size()) + } // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time // with the proof size zeroed (a hot call re-reads state already in the proof). fn seal_call_hot() -> Weight { diff --git a/substrate/frame/revive/src/access_list.rs b/substrate/frame/revive/src/access_list.rs index 31d2db0de8b5..95ec2f2d0f13 100644 --- a/substrate/frame/revive/src/access_list.rs +++ b/substrate/frame/revive/src/access_list.rs @@ -133,6 +133,21 @@ impl Warmth { } } +/// Warmth of the two state items a code load reads. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct CodeWarmth { + /// The `CodeInfoOf` entry. + pub info: Warmth, + /// The `PristineCode` entry. + pub blob: Warmth, +} + +impl CodeWarmth { + pub fn cold_nonrevertible() -> Self { + Self { info: Warmth::cold_nonrevertible(), blob: Warmth::cold_nonrevertible() } + } +} + /// Classification of a storage access for pricing. #[cfg_attr(test, derive(PartialEq, Eq))] #[derive(Clone, Copy, Debug)] @@ -221,10 +236,11 @@ pub enum AccessEntry { Storage { slot: Slot, address: H160 }, /// Contract metadata of `address`. ContractInfo { address: H160 }, - /// Code blob and code metadata (`PristineCode` + `CodeInfoOf`). Keyed by - /// code hash, not address: code is deduplicated, so two contracts sharing - /// a blob genuinely share its load cost within a transaction. - Code { hash: H256 }, + /// Code metadata (`CodeInfoOf`). Keyed by code hash: code is + /// deduplicated, so contracts sharing a blob share its metadata warmth. + CodeInfo { hash: H256 }, + /// Code blob (`PristineCode`). Keyed by code hash for the same reason. + CodeBlob { hash: H256 }, } /// Per-transaction access list with per-frame rollback support. Layout @@ -350,6 +366,24 @@ impl AccessList { kind } + /// Touches each state item read by `access` and returns its warmth. + pub fn touch_access(&mut self, access: StateAccess) -> StateAccessKind { + access.expand(|entry| self.touch(entry)) + } + + /// Non-mutating sibling of [`touch_access`](Self::touch_access). + pub fn peek_access(&self, access: StateAccess) -> StateAccessKind { + access.expand(|entry| self.peek(&entry)) + } + + /// Registers the two state items a code load reads, returning their warmth. + pub fn touch_code(&mut self, hash: H256) -> CodeWarmth { + CodeWarmth { + info: self.touch(AccessEntry::CodeInfo { hash }), + blob: self.touch(AccessEntry::CodeBlob { hash }), + } + } + /// Per-transaction metrics snapshot. pub fn metrics(&self) -> AccessListMetrics { AccessListMetrics { size: self.accessed.len(), cold: self.cold_count, hot: self.hot_count } @@ -373,7 +407,7 @@ mod tests { AccessEntry::Storage { address: H160::zero(), slot: Slot::Fix([0xA; 32]) }, AccessEntry::Account { address: H160::zero() }, AccessEntry::ContractInfo { address: H160::zero() }, - AccessEntry::Code { hash: H256::repeat_byte(0xD) }, + AccessEntry::CodeBlob { hash: H256::repeat_byte(0xD) }, ); // Root frame: cold, but no checkpoint covers it, so it is not revertible. diff --git a/substrate/frame/revive/src/benchmarking.rs b/substrate/frame/revive/src/benchmarking.rs index e0e45f1405be..2429f467a199 100644 --- a/substrate/frame/revive/src/benchmarking.rs +++ b/substrate/frame/revive/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use crate::{ Pallet as Contracts, - access_list::{AccessEntry, AccessList, MAX_ACCESS_LIST_ENTRIES, StateAccess}, + access_list::{AccessEntry, AccessList, CodeWarmth, MAX_ACCESS_LIST_ENTRIES, StateAccess}, call_builder::{CallSetup, Contract, VmBinaryModule, caller_funding, default_deposit_limit}, evm::{ TransactionLegacyUnsigned, TransactionSigned, TransactionUnsigned, @@ -192,12 +192,8 @@ mod benchmarks { Ok(()) } - /// A hot call re-reads state already in the proof: exempt the callee's keys. - fn whitelist_callee_keys(callee: &Contract, code_hash: H256) { + fn whitelist_code(code_hash: H256) { for key in [ - frame_system::Account::::hashed_key_for(&callee.account_id), - OriginalAccount::::hashed_key_for(&callee.address), - AccountInfoOf::::hashed_key_for(&callee.address), CodeInfoOf::::hashed_key_for(&code_hash), PristineCode::::hashed_key_for(&code_hash), ] { @@ -205,6 +201,17 @@ mod benchmarks { } } + fn whitelist_contract_and_code(contract: &Contract, code_hash: H256) { + for key in [ + frame_system::Account::::hashed_key_for(&contract.account_id), + OriginalAccount::::hashed_key_for(&contract.address), + AccountInfoOf::::hashed_key_for(&contract.address), + ] { + frame_benchmarking::benchmarking::add_to_whitelist(key.into()); + } + whitelist_code::(code_hash); + } + /// Shared setup of the hot call benches: deploys `$module` as the callee, /// makes it hot (access list warmed, keys whitelisted), and binds /// `$do_call` to a zero-value call (or, with the `delegate` prefix, a @@ -244,7 +251,7 @@ mod benchmarks { let callee = callee_contract.account_id.clone(); let code_hash = callee_contract.info()?.code_hash; - whitelist_callee_keys::(&callee_contract, code_hash); + whitelist_contract_and_code::(&callee_contract, code_hash); let callee_bytes = callee.encode(); let $callee_len = callee_bytes.len() as u32; @@ -2467,8 +2474,12 @@ mod benchmarks { // i: size of the input data #[benchmark(pov_mode = Measured)] fn seal_call(t: Linear<0, 1>, d: Linear<0, 1>, i: Linear<0, { limits::code::BLOB_BYTES }>) { - let Contract { account_id: callee, address: callee_addr, .. } = + let callee_contract = Contract::::with_index(1, VmBinaryModule::dummy(), vec![]).unwrap(); + let Contract { account_id: callee, address: callee_addr, .. } = callee_contract.clone(); + + // The code read is priced by `code_load`, not this benchmark. + whitelist_code::(callee_contract.info().unwrap().code_hash); let callee_bytes = callee.encode(); let callee_len = callee_bytes.len() as u32; @@ -2597,8 +2608,12 @@ mod benchmarks { #[benchmark(pov_mode = Measured)] fn seal_delegate_call() -> Result<(), BenchmarkError> { - let Contract { account_id: address, .. } = + let callee_contract = Contract::::with_index(1, VmBinaryModule::dummy(), vec![]).unwrap(); + let Contract { account_id: address, .. } = callee_contract.clone(); + + // The code read is priced by `code_load`, not this benchmark. + whitelist_code::(callee_contract.info().unwrap().code_hash); let address_bytes = address.encode(); let address_len = address_bytes.len() as u32; @@ -2647,6 +2662,26 @@ mod benchmarks { Ok(()) } + #[benchmark(pov_mode = Measured)] + fn code_load() -> Result<(), BenchmarkError> { + let contract = Contract::::with_index(1, VmBinaryModule::dummy(), vec![])?; + let code_hash = contract.info()?.code_hash; + let mut meter = + TransactionMeter::::new_from_limits(Weight::MAX, BalanceOf::::max_value()) + .map_err(|_| BenchmarkError::Stop("could not create meter"))?; + let blob; + #[block] + { + blob = ContractBlob::::from_storage( + code_hash, + &mut meter, + CodeWarmth::cold_nonrevertible(), + ); + } + assert!(blob.is_ok(), "loading the code of an existing contract must succeed"); + Ok(()) + } + // t: with or without some value to transfer // d: with or without dust value to transfer // i: size of the input data diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index dc0ed2c1f7d1..031cdb014c70 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -20,7 +20,7 @@ use crate::{ CodeRemoved, Config, ContractInfo, Error, Event, ImmutableData, ImmutableDataOf, LOG_TARGET, Pallet as Contracts, RuntimeCosts, TrieId, access_list::{ - AccessEntry, AccessList, StateAccess, StateAccessKind, StorageAccessKind, Warmth, + AccessEntry, AccessList, CodeWarmth, StateAccess, StateAccessKind, StorageAccessKind, }, address::{self, AddressMapper}, deposit_payment::Deposit as _, @@ -556,8 +556,8 @@ pub trait PrecompileExt: sealing::Sealed { /// Non-mutating sibling of `touch_storage_access`. fn peek_storage_access(&self, transient: bool, key: &Key) -> StorageAccessKind; - /// Warmth of the state items `opcode` reads. - fn peek_access(&self, opcode: StateAccess) -> StateAccessKind; + /// Warmth of the state items `access` reads. + fn peek_access(&self, access: StateAccess) -> StateAccessKind; /// Charges `diff` from the meter. fn charge_storage(&mut self, diff: &Diff) -> DispatchResult; @@ -595,7 +595,7 @@ pub trait Executable: Sized { fn from_storage( code_hash: H256, meter: &mut ResourceMeter, - warmth: Warmth, + warmth: CodeWarmth, ) -> Result; /// Load the executable from EVM bytecode @@ -1064,15 +1064,6 @@ where Ok(Some((stack, executable))) } - /// Registers the state items `opcode` reads, so later accesses bill hot. - fn touch_access(access_list: &mut AccessList, opcode: StateAccess) { - // Precompile targets are priced without warmth: not registered. - if is_precompile::(&opcode.target()) { - return; - } - opcode.expand(|entry| access_list.touch(entry)); - } - /// Construct a new frame. /// /// This does not take `self` because when constructing the first frame `self` is @@ -1093,16 +1084,17 @@ where let address = T::AddressMapper::to_address(&dest); let precompile = >::get(address.as_fixed_bytes()); - // Placed after the depth and reentrancy gates, which abort - // before any state is read, and before the contract-info load - // below. That load reads storage even when it finds no contract - // (a plain account): the read is in the PoV, so warming the - // target is correct even when no frame is built. + // Denied calls (depth, reentrancy) abort before reaching this + // touch. The contract-info load below hits storage even for a + // plain account, so warming is correct when no frame is built. let access = match &delegated_call { None => StateAccess::Call { target: address }, Some(delegated) => StateAccess::DelegateCall { target: delegated.callee }, }; - Self::touch_access(access_list, access); + // Warmth does not apply to precompile calls. + if !is_precompile::(&access.target()) { + access_list.touch_access(access); + } // which contract info to load is unaffected by the fact if this // is a delegate call or not @@ -1146,8 +1138,7 @@ where else { return Ok(None); }; - let code_warmth = - access_list.touch(AccessEntry::Code { hash: info.code_hash }); + let code_warmth = access_list.touch_code(info.code_hash); let executable = E::from_storage(info.code_hash, meter, code_warmth)?; ExecutableOrPrecompile::Executable(executable) } @@ -1162,7 +1153,7 @@ where .as_contract() .expect("When not a precompile the contract was loaded above; qed") .code_hash; - let code_warmth = access_list.touch(AccessEntry::Code { hash: code_hash }); + let code_warmth = access_list.touch_code(code_hash); let executable = E::from_storage(code_hash, meter, code_warmth)?; ExecutableOrPrecompile::Executable(executable) } @@ -1934,11 +1925,11 @@ where self.block_number = block_number; } - /// Touches the access-list entries `opcode` reads, plus the code, as if the call already ran. + /// Touches the access-list entries `access` reads, plus the code, as if the call already ran. #[cfg(feature = "runtime-benchmarks")] - pub(crate) fn touch_call_target(&mut self, opcode: StateAccess, code_hash: H256) { - Self::touch_access(&mut self.access_list, opcode); - self.access_list.touch(AccessEntry::Code { hash: code_hash }); + pub(crate) fn touch_call_target(&mut self, access: StateAccess, code_hash: H256) { + self.access_list.touch_access(access); + self.access_list.touch_code(code_hash); } /// Per-transaction access list metrics (testing). @@ -2155,7 +2146,7 @@ where let executable = E::from_storage( *hash, self.frame_meter_mut(), - Warmth::cold_nonrevertible(), + CodeWarmth::cold_nonrevertible(), )?; ensure!(executable.code_info().is_pvm(), >::EvmConstructedFromHash); executable @@ -2679,8 +2670,8 @@ where ) } - fn peek_access(&self, opcode: StateAccess) -> StateAccessKind { - opcode.expand(|entry| self.access_list.peek(&entry)) + fn peek_access(&self, access: StateAccess) -> StateAccessKind { + self.access_list.peek_access(access) } fn charge_storage(&mut self, diff: &Diff) -> DispatchResult { diff --git a/substrate/frame/revive/src/exec/tests.rs b/substrate/frame/revive/src/exec/tests.rs index c864793d5bd8..957583ca72f3 100644 --- a/substrate/frame/revive/src/exec/tests.rs +++ b/substrate/frame/revive/src/exec/tests.rs @@ -24,7 +24,8 @@ use super::*; use crate::{ AddressMapper, Error, Pallet, ReentrancyProtection, access_list::{ - MAX_ACCESS_LIST_ENTRIES, MAX_INLINE_KEY_LEN, StateAccess, StateAccessKind, Warmth, + CodeWarmth, MAX_ACCESS_LIST_ENTRIES, MAX_INLINE_KEY_LEN, StateAccess, StateAccessKind, + Warmth, }, exec::ExportedFunction::*, metering::TransactionMeter, @@ -144,7 +145,7 @@ impl Executable for MockExecutable { fn from_storage( code_hash: H256, _meter: &mut ResourceMeter, - _warmth: Warmth, + _warmth: CodeWarmth, ) -> Result { Loader::mutate(|loader| { loader.map.get(&code_hash).cloned().ok_or(Error::::CodeNotFound.into()) @@ -208,7 +209,7 @@ fn from_storage_cold( code_hash: H256, meter: &mut crate::metering::ResourceMeter, ) -> Result { - MockExecutable::from_storage(code_hash, meter, Warmth::cold_nonrevertible()) + MockExecutable::from_storage(code_hash, meter, CodeWarmth::cold_nonrevertible()) } #[test] @@ -3334,14 +3335,14 @@ fn cold_hot_call_target_warms_across_calls() { let mid = ctx.ext.access_list_metrics(); assert_eq!( mid.cold - before.cold, - 3, - "first call: account + contract info + code touch cold", + 4, + "first call: account + contract info + code metadata + code blob touch cold", ); assert_eq!(mid.hot, before.hot, "first call adds no hot touches"); assert_matches!(run_child_call(ctx.ext, &BOB_ADDR, vec![]), Ok(_)); let after = ctx.ext.access_list_metrics(); - assert_eq!(after.hot - mid.hot, 3, "second call: account + contract info + code hot"); + assert_eq!(after.hot - mid.hot, 4, "second call: account + contract info + code hot"); assert_eq!(after.cold, mid.cold, "second call adds no cold touches"); exec_success() }); @@ -3364,7 +3365,11 @@ fn cold_hot_delegate_call_leaves_target_account_cold() { let before = ctx.ext.access_list_metrics(); assert_matches!(ctx.ext.delegate_call(&CallResources::NoLimits, BOB_ADDR, vec![]), Ok(_)); let after = ctx.ext.access_list_metrics(); - assert_eq!(after.cold - before.cold, 2, "delegate call: contract info + code touch cold"); + assert_eq!( + after.cold - before.cold, + 3, + "delegate call: contract info + code metadata + code blob touch cold", + ); assert_eq!(after.hot, before.hot, "delegate call adds no hot touches"); assert_matches!( ctx.ext.peek_access(StateAccess::DelegateCall { target: BOB_ADDR }), @@ -3468,7 +3473,7 @@ fn cold_hot_shared_code_hash_is_hot_across_addresses() { assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); let after = ctx.ext.access_list_metrics(); assert_eq!(after.cold - mid.cold, 2, "second address: account + contract info cold"); - assert_eq!(after.hot - mid.hot, 1, "second address: shared code blob hot"); + assert_eq!(after.hot - mid.hot, 2, "second address: shared code metadata + blob hot"); exec_success() }); @@ -3498,3 +3503,37 @@ fn cold_hot_first_frame_warms_entry_target() { run_root_call(BOB_ADDR, vec![]); }); } + +#[test] +fn cold_hot_code_loads_cold_after_target_warmed_as_plain_account() { + // Warm an address as a plain account (no code loaded), then place code there, + // so the next call sees account and contract info hot but the code cold. + let django_code_hash = MockLoader::insert(Call, |_, _| exec_success()); + + let root_code_hash = MockLoader::insert(Call, move |ctx, _| { + assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), + StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + "the plain-account call warmed account and contract info", + ); + + place_contract(&DJANGO, django_code_hash); + + let before = ctx.ext.access_list_metrics(); + assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); + let after = ctx.ext.access_list_metrics(); + assert_eq!(after.hot - before.hot, 2, "account + contract info are already hot"); + assert_eq!( + after.cold - before.cold, + 2, + "code metadata + blob load", + ); + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + place_contract(&CHARLIE, root_code_hash); + run_root_call(CHARLIE_ADDR, vec![]); + }); +} diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index 8026542925f9..f18ea149d860 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -1890,7 +1890,7 @@ impl Pallet { let executable = ContractBlob::from_storage( code_hash, &mut transaction_meter, - access_list::Warmth::cold_nonrevertible(), + access_list::CodeWarmth::cold_nonrevertible(), )?; ensure!(executable.code_info().is_pvm(), >::EvmConstructedFromHash); executable diff --git a/substrate/frame/revive/src/vm/mod.rs b/substrate/frame/revive/src/vm/mod.rs index 622a0a53e4d4..189e933b6362 100644 --- a/substrate/frame/revive/src/vm/mod.rs +++ b/substrate/frame/revive/src/vm/mod.rs @@ -27,7 +27,7 @@ pub use runtime_costs::RuntimeCosts; use crate::{ AccountIdOf, BalanceOf, CodeInfoOf, CodeRemoved, Config, Error, ExecConfig, ExecError, HoldReason, LOG_TARGET, Pallet, PristineCode, StorageDeposit, Weight, - access_list::Warmth, + access_list::CodeWarmth, deposit_payment, exec::{ExecResult, Executable, ExportedFunction, Ext}, frame_support::ensure, @@ -125,11 +125,11 @@ impl ExportedFunction { struct CodeLoadToken { code_len: u32, code_type: BytecodeType, - warmth: Warmth, + warmth: CodeWarmth, } impl CodeLoadToken { - fn from_code_info(code_info: &CodeInfo, warmth: Warmth) -> Self { + fn from_code_info(code_info: &CodeInfo, warmth: CodeWarmth) -> Self { Self { code_len: code_info.code_len, code_type: code_info.code_type, warmth } } } @@ -137,12 +137,19 @@ impl CodeLoadToken { impl Token for CodeLoadToken { fn weight(&self) -> Weight { let size_cost = |bench: fn(u32) -> Weight| bench(self.code_len).saturating_sub(bench(0)); + // Reading the code records adds proof only on a cold load; a hot load has + // them in the proof already. The read's time is part of the caller's base + // weight. + let read_proof = Weight::from_parts(0, T::WeightInfo::code_load().proof_size()); let base = runtime_costs::warm_base::( - &[self.warmth], + &[self.warmth.info, self.warmth.blob], + 2, // overlay probes: `CodeInfoOf` and `PristineCode` runtime_costs::CostPair { - cold: || match self.code_type { - BytecodeType::Pvm => size_cost(T::WeightInfo::call_with_pvm_code_per_byte), - BytecodeType::Evm => size_cost(T::WeightInfo::call_with_evm_code_per_byte), + cold: || { + read_proof.saturating_add(match self.code_type { + BytecodeType::Pvm => size_cost(T::WeightInfo::call_with_pvm_code_per_byte), + BytecodeType::Evm => size_cost(T::WeightInfo::call_with_evm_code_per_byte), + }) }, hot: || match self.code_type { BytecodeType::Pvm => size_cost(T::WeightInfo::call_with_pvm_code_per_byte_hot), @@ -169,7 +176,7 @@ pub fn code_load_weight(code_len: u32) -> Weight { Token::::weight(&CodeLoadToken { code_len, code_type: BytecodeType::Pvm, - warmth: Warmth::cold_nonrevertible(), + warmth: CodeWarmth::cold_nonrevertible(), }) } @@ -344,7 +351,7 @@ impl Executable for ContractBlob { fn from_storage( code_hash: H256, meter: &mut ResourceMeter, - warmth: Warmth, + warmth: CodeWarmth, ) -> Result { let code_info = >::get(code_hash).ok_or(Error::::CodeNotFound)?; meter.charge_weight_token(CodeLoadToken::from_code_info(&code_info, warmth))?; @@ -418,29 +425,55 @@ pub(crate) fn exec_error_into_return_code( #[cfg(test)] mod tests { use super::*; - use crate::tests::Test; + use crate::{access_list::Warmth, tests::Test}; #[test] fn code_load_cold_hot_pricing() { + let code_len = 1024_u32; let weight_of = |code_type, warmth| { - Token::::weight(&CodeLoadToken { code_len: 1024, code_type, warmth }) + Token::::weight(&CodeLoadToken { code_len, code_type, warmth }) }; for code_type in [BytecodeType::Pvm, BytecodeType::Evm] { - let cold = weight_of(code_type, Warmth::cold_nonrevertible()); - let hot = weight_of(code_type, Warmth::Hot); - let cold_revertible = weight_of(code_type, Warmth::Cold { revertible: true }); + let cold = weight_of(code_type, CodeWarmth::cold_nonrevertible()); + let hot = weight_of(code_type, CodeWarmth { info: Warmth::Hot, blob: Warmth::Hot }); + let cold_revertible = weight_of( + code_type, + CodeWarmth { + info: Warmth::Cold { revertible: true }, + blob: Warmth::Cold { revertible: true }, + }, + ); assert!( cold.ref_time() > hot.ref_time(), "expected cold > hot ref_time for {code_type:?}: cold={cold:?} hot={hot:?}", ); assert!(cold.proof_size() > 0, "cold proof_size {code_type:?}: {cold:?}"); assert_eq!(hot.proof_size(), 0, "hot proof_size {code_type:?}: {hot:?}"); + + let read_proof = ::WeightInfo::code_load().proof_size(); + assert!( + cold.proof_size() >= read_proof + u64::from(code_len), + "cold load must include the {read_proof}-byte code read proof plus \ + {code_len} per-byte proof: {cold:?}", + ); assert!( cold_revertible.ref_time() > cold.ref_time(), "expected revertible > non-revertible ref_time for {code_type:?}: \ rev={cold_revertible:?} non={cold:?}", ); + + // An `EXTCODESIZE`-style touch warms only the metadata; the blob + // load must still bill the full cold base. + let info_only = weight_of( + code_type, + CodeWarmth { info: Warmth::Hot, blob: Warmth::cold_nonrevertible() }, + ); + assert!( + info_only.proof_size() > hot.proof_size(), + "a cold blob prices the cold base even with hot metadata: \ + info_only={info_only:?} all_hot={hot:?}", + ); } } } diff --git a/substrate/frame/revive/src/vm/runtime_costs.rs b/substrate/frame/revive/src/vm/runtime_costs.rs index 71888105a60c..aa37e50ce9ee 100644 --- a/substrate/frame/revive/src/vm/runtime_costs.rs +++ b/substrate/frame/revive/src/vm/runtime_costs.rs @@ -231,7 +231,7 @@ impl RuntimeCosts { ) -> Weight { match kind { StorageAccessKind::Persistent(warmth) => { - warm_base::(&[warmth], CostPair { cold, hot }) + warm_base::(&[warmth], 1, CostPair { cold, hot }) // probe: the slot }, StorageAccessKind::Transient => transient(), } @@ -270,14 +270,18 @@ pub(crate) struct CostPair { /// Warmth-priced base of an opcode touching `items`: the hot bench applies /// only when every item is hot (mixed warmth rounds up to the cold bench), /// plus the per-item access-list overhead. +/// +/// `hot_probes` is the number of storage reads the hot path serves from the +/// overlay. pub(crate) fn warm_base( items: &[Warmth], + hot_probes: u64, costs: CostPair Weight, impl FnOnce() -> Weight>, ) -> Weight { let base = if items.iter().all(|warmth| warmth.is_hot()) { - // The hot benches run at an empty overlay; a single lookup is - // charged as an approximation. - (costs.hot)().saturating_add(RuntimeCosts::hot_storage_overlay_overhead::()) + (costs.hot)().saturating_add( + RuntimeCosts::hot_storage_overlay_overhead::().saturating_mul(hot_probes), + ) } else { (costs.cold)() }; @@ -376,6 +380,7 @@ impl Token for RuntimeCosts { CallBase(warmth) => match warmth { StateAccessKind::Call { account, contract_info } => warm_base::( &[account, contract_info], + 3, // probes: address mapping, system account, contract info CostPair { cold: || T::WeightInfo::seal_call(0, 0, 0), hot: T::WeightInfo::seal_call_hot, @@ -383,6 +388,7 @@ impl Token for RuntimeCosts { ), StateAccessKind::DelegateCall { contract_info } => warm_base::( &[contract_info], + 1, // probe: the callee's contract info CostPair { cold: T::WeightInfo::seal_delegate_call, hot: T::WeightInfo::seal_delegate_call_hot, diff --git a/substrate/frame/revive/src/weights.rs b/substrate/frame/revive/src/weights.rs index d64ec898b395..d9890bc1a9e9 100644 --- a/substrate/frame/revive/src/weights.rs +++ b/substrate/frame/revive/src/weights.rs @@ -164,6 +164,7 @@ pub trait WeightInfo { fn seal_delegate_call_hot() -> Weight; fn seal_call_precompile(d: u32, i: u32, ) -> Weight; fn seal_delegate_call() -> Weight; + fn code_load() -> Weight; fn seal_instantiate(t: u32, d: u32, i: u32, ) -> Weight; fn evm_instantiate(t: u32, d: u32, i: u32, ) -> Weight; fn sha2_256(n: u32, ) -> Weight; @@ -1344,6 +1345,12 @@ impl WeightInfo for SubstrateWeight { Weight::from_parts(30_587_000, 4214) .saturating_add(T::DbWeight::get().reads(3_u64)) } + // Placeholder until `/cmd bench` runs the `code_load` benchmark: proof-only + // over-approximation reusing seal_delegate_call's {AccountInfoOf, CodeInfoOf, + // PristineCode} proof, which is a superset of the {CodeInfoOf, PristineCode} read. + fn code_load() -> Weight { + Weight::from_parts(0, Self::seal_delegate_call().proof_size()) + } // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time // with the proof size zeroed (a hot call re-reads state already in the proof). fn seal_call_hot() -> Weight { @@ -2920,6 +2927,12 @@ impl WeightInfo for () { Weight::from_parts(30_587_000, 4214) .saturating_add(RocksDbWeight::get().reads(3_u64)) } + // Placeholder until `/cmd bench` runs the `code_load` benchmark: proof-only + // over-approximation reusing seal_delegate_call's {AccountInfoOf, CodeInfoOf, + // PristineCode} proof, which is a superset of the {CodeInfoOf, PristineCode} read. + fn code_load() -> Weight { + Weight::from_parts(0, Self::seal_delegate_call().proof_size()) + } // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time // with the proof size zeroed (a hot call re-reads state already in the proof). fn seal_call_hot() -> Weight { From c7bea76be0624129eeb3efbb1f3aca66662c3375 Mon Sep 17 00:00:00 2001 From: Marian Radu Date: Thu, 16 Jul 2026 19:01:09 +0300 Subject: [PATCH 3/9] pallet-revive: rename cold/hot weight helpers for clarity --- substrate/frame/revive/src/access_list.rs | 14 ++--- substrate/frame/revive/src/benchmarking.rs | 9 ++- substrate/frame/revive/src/exec.rs | 22 +++++--- substrate/frame/revive/src/exec/tests.rs | 12 ++-- substrate/frame/revive/src/lib.rs | 2 +- .../evm/instructions/contract/call_helpers.rs | 6 +- substrate/frame/revive/src/vm/mod.rs | 56 ++++++++++--------- substrate/frame/revive/src/vm/pvm.rs | 7 ++- .../frame/revive/src/vm/runtime_costs.rs | 34 ++++++----- 9 files changed, 84 insertions(+), 78 deletions(-) diff --git a/substrate/frame/revive/src/access_list.rs b/substrate/frame/revive/src/access_list.rs index 95ec2f2d0f13..3638eb353035 100644 --- a/substrate/frame/revive/src/access_list.rs +++ b/substrate/frame/revive/src/access_list.rs @@ -135,14 +135,14 @@ impl Warmth { /// Warmth of the two state items a code load reads. #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct CodeWarmth { +pub struct CodeLoadWarmth { /// The `CodeInfoOf` entry. pub info: Warmth, /// The `PristineCode` entry. pub blob: Warmth, } -impl CodeWarmth { +impl CodeLoadWarmth { pub fn cold_nonrevertible() -> Self { Self { info: Warmth::cold_nonrevertible(), blob: Warmth::cold_nonrevertible() } } @@ -177,7 +177,7 @@ pub enum StateAccess { impl StateAccess { /// The state access of a call or delegate call. - pub fn call(target: H160, delegate: bool) -> Self { + pub fn new(target: H160, delegate: bool) -> Self { if delegate { Self::DelegateCall { target } } else { Self::Call { target } } } @@ -188,8 +188,8 @@ impl StateAccess { } } - /// Expands into the state items the opcode reads; `warmth_of` supplies - /// each item's warmth. + /// Maps `warmth_of` over each state item this access reads and collects + /// the results into a [`StateAccessKind`]. pub fn expand(self, mut warmth_of: impl FnMut(AccessEntry) -> Warmth) -> StateAccessKind { match self { Self::Call { target } => StateAccessKind::Call { @@ -377,8 +377,8 @@ impl AccessList { } /// Registers the two state items a code load reads, returning their warmth. - pub fn touch_code(&mut self, hash: H256) -> CodeWarmth { - CodeWarmth { + pub fn touch_code(&mut self, hash: H256) -> CodeLoadWarmth { + CodeLoadWarmth { info: self.touch(AccessEntry::CodeInfo { hash }), blob: self.touch(AccessEntry::CodeBlob { hash }), } diff --git a/substrate/frame/revive/src/benchmarking.rs b/substrate/frame/revive/src/benchmarking.rs index 2429f467a199..4eda2be0c66c 100644 --- a/substrate/frame/revive/src/benchmarking.rs +++ b/substrate/frame/revive/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use crate::{ Pallet as Contracts, - access_list::{AccessEntry, AccessList, CodeWarmth, MAX_ACCESS_LIST_ENTRIES, StateAccess}, + access_list::{AccessEntry, AccessList, CodeLoadWarmth, MAX_ACCESS_LIST_ENTRIES, StateAccess}, call_builder::{CallSetup, Contract, VmBinaryModule, caller_funding, default_deposit_limit}, evm::{ TransactionLegacyUnsigned, TransactionSigned, TransactionUnsigned, @@ -267,7 +267,7 @@ mod benchmarks { setup.set_origin(ExecOrigin::from_account_id(setup.contract().account_id.clone())); let (mut ext, _) = setup.ext(); - ext.touch_call_target(StateAccess::call(callee_contract.address, $delegate), code_hash); + ext.touch_call_target(StateAccess::new(callee_contract.address, $delegate), code_hash); let mut $runtime = pvm::Runtime::<_, [u8]>::new(&mut ext, vec![]); let mut $memory = memory!(callee_bytes, deposit_bytes, value_bytes,); }; @@ -2646,8 +2646,7 @@ mod benchmarks { assert_eq!(result.unwrap(), ReturnErrorCode::Success); Ok(()) } - // Delegate-call a target whose contract metadata and code are hot, as if - // an identical delegate call already ran in the same transaction. + #[benchmark(pov_mode = Measured)] fn seal_delegate_call_hot() -> Result<(), BenchmarkError> { hot_call_setup!(delegate do_call, VmBinaryModule::dummy()); @@ -2675,7 +2674,7 @@ mod benchmarks { blob = ContractBlob::::from_storage( code_hash, &mut meter, - CodeWarmth::cold_nonrevertible(), + CodeLoadWarmth::cold_nonrevertible(), ); } assert!(blob.is_ok(), "loading the code of an existing contract must succeed"); diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 031cdb014c70..8d2af9705ca0 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -20,7 +20,7 @@ use crate::{ CodeRemoved, Config, ContractInfo, Error, Event, ImmutableData, ImmutableDataOf, LOG_TARGET, Pallet as Contracts, RuntimeCosts, TrieId, access_list::{ - AccessEntry, AccessList, CodeWarmth, StateAccess, StateAccessKind, StorageAccessKind, + AccessEntry, AccessList, CodeLoadWarmth, StateAccess, StateAccessKind, StorageAccessKind, }, address::{self, AddressMapper}, deposit_payment::Deposit as _, @@ -595,7 +595,7 @@ pub trait Executable: Sized { fn from_storage( code_hash: H256, meter: &mut ResourceMeter, - warmth: CodeWarmth, + warmth: CodeLoadWarmth, ) -> Result; /// Load the executable from EVM bytecode @@ -1087,12 +1087,18 @@ where // Denied calls (depth, reentrancy) abort before reaching this // touch. The contract-info load below hits storage even for a // plain account, so warming is correct when no frame is built. - let access = match &delegated_call { - None => StateAccess::Call { target: address }, - Some(delegated) => StateAccess::DelegateCall { target: delegated.callee }, + // + // Precompiles are not warmed. Reuse the `precompile` lookup for + // a plain call; a delegate call looks up its own callee. + let (access, target_is_precompile) = match &delegated_call { + None => + (StateAccess::Call { target: address }, precompile.is_some()), + Some(delegated) => ( + StateAccess::DelegateCall { target: delegated.callee }, + is_precompile::(&delegated.callee), + ), }; - // Warmth does not apply to precompile calls. - if !is_precompile::(&access.target()) { + if !target_is_precompile { access_list.touch_access(access); } @@ -2146,7 +2152,7 @@ where let executable = E::from_storage( *hash, self.frame_meter_mut(), - CodeWarmth::cold_nonrevertible(), + CodeLoadWarmth::cold_nonrevertible(), )?; ensure!(executable.code_info().is_pvm(), >::EvmConstructedFromHash); executable diff --git a/substrate/frame/revive/src/exec/tests.rs b/substrate/frame/revive/src/exec/tests.rs index 957583ca72f3..f896e6a4e7d8 100644 --- a/substrate/frame/revive/src/exec/tests.rs +++ b/substrate/frame/revive/src/exec/tests.rs @@ -24,7 +24,7 @@ use super::*; use crate::{ AddressMapper, Error, Pallet, ReentrancyProtection, access_list::{ - CodeWarmth, MAX_ACCESS_LIST_ENTRIES, MAX_INLINE_KEY_LEN, StateAccess, StateAccessKind, + CodeLoadWarmth, MAX_ACCESS_LIST_ENTRIES, MAX_INLINE_KEY_LEN, StateAccess, StateAccessKind, Warmth, }, exec::ExportedFunction::*, @@ -145,7 +145,7 @@ impl Executable for MockExecutable { fn from_storage( code_hash: H256, _meter: &mut ResourceMeter, - _warmth: CodeWarmth, + _warmth: CodeLoadWarmth, ) -> Result { Loader::mutate(|loader| { loader.map.get(&code_hash).cloned().ok_or(Error::::CodeNotFound.into()) @@ -209,7 +209,7 @@ fn from_storage_cold( code_hash: H256, meter: &mut crate::metering::ResourceMeter, ) -> Result { - MockExecutable::from_storage(code_hash, meter, CodeWarmth::cold_nonrevertible()) + MockExecutable::from_storage(code_hash, meter, CodeLoadWarmth::cold_nonrevertible()) } #[test] @@ -3524,11 +3524,7 @@ fn cold_hot_code_loads_cold_after_target_warmed_as_plain_account() { assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); let after = ctx.ext.access_list_metrics(); assert_eq!(after.hot - before.hot, 2, "account + contract info are already hot"); - assert_eq!( - after.cold - before.cold, - 2, - "code metadata + blob load", - ); + assert_eq!(after.cold - before.cold, 2, "code metadata + blob load",); exec_success() }); diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index f18ea149d860..ecbe20ae2cbc 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -1890,7 +1890,7 @@ impl Pallet { let executable = ContractBlob::from_storage( code_hash, &mut transaction_meter, - access_list::CodeWarmth::cold_nonrevertible(), + access_list::CodeLoadWarmth::cold_nonrevertible(), )?; ensure!(executable.code_info().is_pvm(), >::EvmConstructedFromHash); executable diff --git a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs index 05f92a34c7e0..67c1a724a3d9 100644 --- a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs +++ b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs @@ -86,9 +86,9 @@ pub fn charge_call_gas<'a, E: Ext>( None => { // Regular CALL / DELEGATECALL base cost / CALLCODE not supported. - // Charged from the current access-list state; the list is updated - // during frame execution. - let access = StateAccess::call(callee, scheme.is_delegate_call()); + // Peek the warmth to price the charge; the entries are touched when + // the frame is built, so peek and touch see the same state. + let access = StateAccess::new(callee, scheme.is_delegate_call()); let cost = RuntimeCosts::CallBase(interpreter.ext.peek_access(access)); interpreter.ext.charge_or_halt(cost)?; diff --git a/substrate/frame/revive/src/vm/mod.rs b/substrate/frame/revive/src/vm/mod.rs index 189e933b6362..4ecbea910e90 100644 --- a/substrate/frame/revive/src/vm/mod.rs +++ b/substrate/frame/revive/src/vm/mod.rs @@ -27,7 +27,7 @@ pub use runtime_costs::RuntimeCosts; use crate::{ AccountIdOf, BalanceOf, CodeInfoOf, CodeRemoved, Config, Error, ExecConfig, ExecError, HoldReason, LOG_TARGET, Pallet, PristineCode, StorageDeposit, Weight, - access_list::CodeWarmth, + access_list::CodeLoadWarmth, deposit_payment, exec::{ExecResult, Executable, ExportedFunction, Ext}, frame_support::ensure, @@ -125,35 +125,41 @@ impl ExportedFunction { struct CodeLoadToken { code_len: u32, code_type: BytecodeType, - warmth: CodeWarmth, + warmth: CodeLoadWarmth, } impl CodeLoadToken { - fn from_code_info(code_info: &CodeInfo, warmth: CodeWarmth) -> Self { + fn from_code_info(code_info: &CodeInfo, warmth: CodeLoadWarmth) -> Self { Self { code_len: code_info.code_len, code_type: code_info.code_type, warmth } } } impl Token for CodeLoadToken { fn weight(&self) -> Weight { - let size_cost = |bench: fn(u32) -> Weight| bench(self.code_len).saturating_sub(bench(0)); - // Reading the code records adds proof only on a cold load; a hot load has - // them in the proof already. The read's time is part of the caller's base - // weight. - let read_proof = Weight::from_parts(0, T::WeightInfo::code_load().proof_size()); - let base = runtime_costs::warm_base::( + let length_cost = |bench: fn(u32) -> Weight| bench(self.code_len).saturating_sub(bench(0)); + let base_weight = runtime_costs::cold_hot_base::( &[self.warmth.info, self.warmth.blob], 2, // overlay probes: `CodeInfoOf` and `PristineCode` runtime_costs::CostPair { cold: || { - read_proof.saturating_add(match self.code_type { - BytecodeType::Pvm => size_cost(T::WeightInfo::call_with_pvm_code_per_byte), - BytecodeType::Evm => size_cost(T::WeightInfo::call_with_evm_code_per_byte), + // The code_load ref_time is tracked by the base weight. + let code_load_proof = T::WeightInfo::code_load().set_ref_time(0); + code_load_proof.saturating_add(match self.code_type { + BytecodeType::Pvm => { + length_cost(T::WeightInfo::call_with_pvm_code_per_byte) + }, + BytecodeType::Evm => { + length_cost(T::WeightInfo::call_with_evm_code_per_byte) + }, }) }, hot: || match self.code_type { - BytecodeType::Pvm => size_cost(T::WeightInfo::call_with_pvm_code_per_byte_hot), - BytecodeType::Evm => size_cost(T::WeightInfo::call_with_evm_code_per_byte_hot), + BytecodeType::Pvm => { + length_cost(T::WeightInfo::call_with_pvm_code_per_byte_hot) + }, + BytecodeType::Evm => { + length_cost(T::WeightInfo::call_with_evm_code_per_byte_hot) + }, }, }, ); @@ -161,12 +167,12 @@ impl Token for CodeLoadToken { // the proof size impact is accounted for in the `call_with_pvm_code_per_byte` // strictly speaking we are double charging for the first BASIC_BLOCK_SIZE // instructions here. Let's consider this as a safety margin. - BytecodeType::Pvm => base.saturating_add( + BytecodeType::Pvm => base_weight.saturating_add( T::WeightInfo::basic_block_compilation(1) .saturating_sub(T::WeightInfo::basic_block_compilation(0)) .set_proof_size(0), ), - BytecodeType::Evm => base, + BytecodeType::Evm => base_weight, } } } @@ -176,7 +182,7 @@ pub fn code_load_weight(code_len: u32) -> Weight { Token::::weight(&CodeLoadToken { code_len, code_type: BytecodeType::Pvm, - warmth: CodeWarmth::cold_nonrevertible(), + warmth: CodeLoadWarmth::cold_nonrevertible(), }) } @@ -351,7 +357,7 @@ impl Executable for ContractBlob { fn from_storage( code_hash: H256, meter: &mut ResourceMeter, - warmth: CodeWarmth, + warmth: CodeLoadWarmth, ) -> Result { let code_info = >::get(code_hash).ok_or(Error::::CodeNotFound)?; meter.charge_weight_token(CodeLoadToken::from_code_info(&code_info, warmth))?; @@ -435,11 +441,11 @@ mod tests { }; for code_type in [BytecodeType::Pvm, BytecodeType::Evm] { - let cold = weight_of(code_type, CodeWarmth::cold_nonrevertible()); - let hot = weight_of(code_type, CodeWarmth { info: Warmth::Hot, blob: Warmth::Hot }); + let cold = weight_of(code_type, CodeLoadWarmth::cold_nonrevertible()); + let hot = weight_of(code_type, CodeLoadWarmth { info: Warmth::Hot, blob: Warmth::Hot }); let cold_revertible = weight_of( code_type, - CodeWarmth { + CodeLoadWarmth { info: Warmth::Cold { revertible: true }, blob: Warmth::Cold { revertible: true }, }, @@ -451,10 +457,10 @@ mod tests { assert!(cold.proof_size() > 0, "cold proof_size {code_type:?}: {cold:?}"); assert_eq!(hot.proof_size(), 0, "hot proof_size {code_type:?}: {hot:?}"); - let read_proof = ::WeightInfo::code_load().proof_size(); + let code_load_proof = ::WeightInfo::code_load().proof_size(); assert!( - cold.proof_size() >= read_proof + u64::from(code_len), - "cold load must include the {read_proof}-byte code read proof plus \ + cold.proof_size() >= code_load_proof + u64::from(code_len), + "cold load must include the {code_load_proof}-byte code read proof plus \ {code_len} per-byte proof: {cold:?}", ); assert!( @@ -467,7 +473,7 @@ mod tests { // load must still bill the full cold base. let info_only = weight_of( code_type, - CodeWarmth { info: Warmth::Hot, blob: Warmth::cold_nonrevertible() }, + CodeLoadWarmth { info: Warmth::Hot, blob: Warmth::cold_nonrevertible() }, ); assert!( info_only.proof_size() > hot.proof_size(), diff --git a/substrate/frame/revive/src/vm/pvm.rs b/substrate/frame/revive/src/vm/pvm.rs index 65979e24e0b7..9931e4954e32 100644 --- a/substrate/frame/revive/src/vm/pvm.rs +++ b/substrate/frame/revive/src/vm/pvm.rs @@ -279,10 +279,11 @@ enum CallType { } impl CallType { - /// Base cost of the call, charged from the current access-list state; - /// the list is updated during frame execution. + /// Base cost of the call. Peeks the warmth to price the charge; the + /// entries are touched when the frame is built, so peek and touch see the + /// same state. fn cost(&self, ext: &impl Ext, callee: &sp_core::H160) -> RuntimeCosts { - let access = StateAccess::call(*callee, matches!(self, CallType::DelegateCall)); + let access = StateAccess::new(*callee, matches!(self, CallType::DelegateCall)); RuntimeCosts::CallBase(ext.peek_access(access)) } } diff --git a/substrate/frame/revive/src/vm/runtime_costs.rs b/substrate/frame/revive/src/vm/runtime_costs.rs index aa37e50ce9ee..752acc6549bf 100644 --- a/substrate/frame/revive/src/vm/runtime_costs.rs +++ b/substrate/frame/revive/src/vm/runtime_costs.rs @@ -231,7 +231,7 @@ impl RuntimeCosts { ) -> Weight { match kind { StorageAccessKind::Persistent(warmth) => { - warm_base::(&[warmth], 1, CostPair { cold, hot }) // probe: the slot + cold_hot_base::(&[warmth], 1, CostPair { cold, hot }) // probe: the slot }, StorageAccessKind::Transient => transient(), } @@ -267,27 +267,25 @@ pub(crate) struct CostPair { pub hot: Hot, } -/// Warmth-priced base of an opcode touching `items`: the hot bench applies -/// only when every item is hot (mixed warmth rounds up to the cold bench), -/// plus the per-item access-list overhead. -/// -/// `hot_probes` is the number of storage reads the hot path serves from the -/// overlay. -pub(crate) fn warm_base( - items: &[Warmth], - hot_probes: u64, +/// Base weight for an opcode reading one state item per entry in +/// `item_warmths`, priced by each item's warmth. `overlay_probes` is the +/// count of overlay traversals the hot path performs in place of a trie read. +pub(crate) fn cold_hot_base( + item_warmths: &[Warmth], + overlay_probes: u64, costs: CostPair Weight, impl FnOnce() -> Weight>, ) -> Weight { - let base = if items.iter().all(|warmth| warmth.is_hot()) { + let opcode_weight = if item_warmths.iter().all(|warmth| warmth.is_hot()) { (costs.hot)().saturating_add( - RuntimeCosts::hot_storage_overlay_overhead::().saturating_mul(hot_probes), + RuntimeCosts::hot_storage_overlay_overhead::().saturating_mul(overlay_probes), ) } else { (costs.cold)() }; - items - .iter() - .fold(base, |base, warmth| base.saturating_add(access_list_overhead::(*warmth))) + // Add each touched item's access-list overhead on top of the opcode cost. + item_warmths.iter().fold(opcode_weight, |weight, warmth| { + weight.saturating_add(access_list_overhead::(*warmth)) + }) } impl Token for RuntimeCosts { @@ -377,8 +375,8 @@ impl Token for RuntimeCosts { || T::WeightInfo::take_storage_hot(len), || cost_storage!(write_transient, seal_take_transient_storage, len), ), - CallBase(warmth) => match warmth { - StateAccessKind::Call { account, contract_info } => warm_base::( + CallBase(access_kind) => match access_kind { + StateAccessKind::Call { account, contract_info } => cold_hot_base::( &[account, contract_info], 3, // probes: address mapping, system account, contract info CostPair { @@ -386,7 +384,7 @@ impl Token for RuntimeCosts { hot: T::WeightInfo::seal_call_hot, }, ), - StateAccessKind::DelegateCall { contract_info } => warm_base::( + StateAccessKind::DelegateCall { contract_info } => cold_hot_base::( &[contract_info], 1, // probe: the callee's contract info CostPair { From 4d0ab6c13e417e1dc58fb3ac1bdd7957c11041fb Mon Sep 17 00:00:00 2001 From: Marian Radu Date: Fri, 17 Jul 2026 14:28:12 +0300 Subject: [PATCH 4/9] pallet-revive: warm code-load entries only after charging --- substrate/frame/revive/src/access_list.rs | 54 +++++++++-- substrate/frame/revive/src/exec.rs | 48 +++++++--- substrate/frame/revive/src/exec/tests.rs | 91 +++++++++++++++++++ .../evm/instructions/contract/call_helpers.rs | 7 +- substrate/frame/revive/src/vm/pvm.rs | 8 +- .../frame/revive/src/vm/runtime_costs.rs | 16 ++-- 6 files changed, 184 insertions(+), 40 deletions(-) diff --git a/substrate/frame/revive/src/access_list.rs b/substrate/frame/revive/src/access_list.rs index 3638eb353035..e8d6c886857e 100644 --- a/substrate/frame/revive/src/access_list.rs +++ b/substrate/frame/revive/src/access_list.rs @@ -181,13 +181,6 @@ impl StateAccess { if delegate { Self::DelegateCall { target } } else { Self::Call { target } } } - /// The accessed address. - pub fn target(&self) -> H160 { - match self { - Self::Call { target } | Self::DelegateCall { target } => *target, - } - } - /// Maps `warmth_of` over each state item this access reads and collects /// the results into a [`StateAccessKind`]. pub fn expand(self, mut warmth_of: impl FnMut(AccessEntry) -> Warmth) -> StateAccessKind { @@ -384,6 +377,14 @@ impl AccessList { } } + /// Non-mutating sibling of [`touch_code`](Self::touch_code). + pub fn peek_code(&self, hash: H256) -> CodeLoadWarmth { + CodeLoadWarmth { + info: self.peek(&AccessEntry::CodeInfo { hash }), + blob: self.peek(&AccessEntry::CodeBlob { hash }), + } + } + /// Per-transaction metrics snapshot. pub fn metrics(&self) -> AccessListMetrics { AccessListMetrics { size: self.accessed.len(), cold: self.cold_count, hot: self.hot_count } @@ -482,6 +483,45 @@ mod tests { assert!(al.touch(existing).is_hot(), "existing entry still hot at cap"); } + #[test] + fn call_peek_and_touch_diverge_at_cap_boundary() { + let mut al = AccessList::new(); + // Fill to one below the cap. + for i in 0..(MAX_ACCESS_LIST_ENTRIES - 1) { + al.touch(AccessEntry::Storage { + address: H160::from_low_u64_be(i as u64), + slot: Slot::Fix([0; 32]), + }); + } + assert_eq!(al.metrics().size, MAX_ACCESS_LIST_ENTRIES - 1); + + let target = H160::from_low_u64_be(0xdead_beef); + // Nested frame, so a journaled cold touch would be revertible. + al.enter_frame(); + + // The set is below the cap, so peek prices both call entries revertible + // cold: it cannot see that touching the first entry fills the cap. + assert_eq!( + al.peek_access(StateAccess::Call { target }), + StateAccessKind::Call { + account: Warmth::Cold { revertible: true }, + contract_info: Warmth::Cold { revertible: true }, + }, + "peek sees the not-full set for both entries", + ); + + // The first touch fills the cap, so ContractInfo lands past it: non-revertible. + assert_eq!( + al.touch_access(StateAccess::Call { target }), + StateAccessKind::Call { + account: Warmth::Cold { revertible: true }, + contract_info: Warmth::cold_nonrevertible(), + }, + "touch journals only the first entry before the cap fills", + ); + al.commit_frame(); + } + #[test] fn peek_does_not_mutate() { let mut al = AccessList::new(); diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 8d2af9705ca0..bc6f0dcb318c 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -559,6 +559,12 @@ pub trait PrecompileExt: sealing::Sealed { /// Warmth of the state items `access` reads. fn peek_access(&self, access: StateAccess) -> StateAccessKind; + /// Base cost of a call opcode. Peeks the warmth; the entries are touched + /// when the frame is built, so peek and touch see the same state. + fn call_base_cost(&self, callee: H160, delegate: bool) -> RuntimeCosts { + RuntimeCosts::CallBase(self.peek_access(StateAccess::new(callee, delegate))) + } + /// Charges `diff` from the meter. fn charge_storage(&mut self, diff: &Diff) -> DispatchResult; } @@ -1084,18 +1090,22 @@ where let address = T::AddressMapper::to_address(&dest); let precompile = >::get(address.as_fixed_bytes()); + let originally_delegated = delegated_call.is_some(); + let delegate_precompile = delegated_call + .as_ref() + .and_then(|d| >::get(d.callee.as_fixed_bytes())); + // Denied calls (depth, reentrancy) abort before reaching this // touch. The contract-info load below hits storage even for a // plain account, so warming is correct when no frame is built. // // Precompiles are not warmed. Reuse the `precompile` lookup for - // a plain call; a delegate call looks up its own callee. + // a plain call; a delegate call reuses its own. let (access, target_is_precompile) = match &delegated_call { - None => - (StateAccess::Call { target: address }, precompile.is_some()), + None => (StateAccess::Call { target: address }, precompile.is_some()), Some(delegated) => ( StateAccess::DelegateCall { target: delegated.callee }, - is_precompile::(&delegated.callee), + delegate_precompile.is_some(), ), }; if !target_is_precompile { @@ -1132,9 +1142,14 @@ where }); // in case of delegate the executable is not the one at `address` let executable = if let Some(delegated_call) = &delegated_call { - if let Some(precompile) = + // Reuse the lookup from above for a real delegate; a + // mock-injected callee is resolved fresh. + let callee_precompile = if originally_delegated { + delegate_precompile + } else { >::get(delegated_call.callee.as_fixed_bytes()) - { + }; + if let Some(precompile) = callee_precompile { ExecutableOrPrecompile::Precompile { instance: precompile, _phantom: Default::default(), @@ -1144,8 +1159,11 @@ where else { return Ok(None); }; - let code_warmth = access_list.touch_code(info.code_hash); + // Touch only after the charge succeeds, so a failed load + // leaves nothing warm. + let code_warmth = access_list.peek_code(info.code_hash); let executable = E::from_storage(info.code_hash, meter, code_warmth)?; + access_list.touch_code(info.code_hash); ExecutableOrPrecompile::Executable(executable) } } else { @@ -1159,8 +1177,11 @@ where .as_contract() .expect("When not a precompile the contract was loaded above; qed") .code_hash; - let code_warmth = access_list.touch_code(code_hash); + // Touch only after the charge succeeds, so a failed load + // leaves nothing warm. + let code_warmth = access_list.peek_code(code_hash); let executable = E::from_storage(code_hash, meter, code_warmth)?; + access_list.touch_code(code_hash); ExecutableOrPrecompile::Executable(executable) } }; @@ -2148,12 +2169,11 @@ where E::from_evm_init_code(initcode, sender.clone())? }, Code::Existing(hash) => { - // The code load of an instantiation is always billed cold. - let executable = E::from_storage( - *hash, - self.frame_meter_mut(), - CodeLoadWarmth::cold_nonrevertible(), - )?; + // Touch only after the charge succeeds, so a failed load + // leaves nothing warm. + let code_warmth = self.access_list.peek_code(*hash); + let executable = E::from_storage(*hash, self.frame_meter_mut(), code_warmth)?; + self.access_list.touch_code(*hash); ensure!(executable.code_info().is_pvm(), >::EvmConstructedFromHash); executable }, diff --git a/substrate/frame/revive/src/exec/tests.rs b/substrate/frame/revive/src/exec/tests.rs index f896e6a4e7d8..cb6dbdd7148a 100644 --- a/substrate/frame/revive/src/exec/tests.rs +++ b/substrate/frame/revive/src/exec/tests.rs @@ -3354,6 +3354,97 @@ fn cold_hot_call_target_warms_across_calls() { }); } +#[test] +fn cold_hot_depth_denied_call_leaves_target_cold() { + // A call denied by the depth limit never builds a frame, so it never warms + // the target: a retry still prices it cold. This diverges from EIP-2929 + // (which warms the address even on a failed call) in the overcharge-safe + // direction, and is the intended behavior. + parameter_types! { + static ReachedBottom: bool = false; + } + let target_ch = MockLoader::insert(Call, |_, _| exec_success()); + let recurse_ch = MockLoader::insert(Call, |ctx, _| { + // Recurse into self until the depth limit denies the call. + let r = ctx.ext.call( + &Default::default(), + &BOB_ADDR, + U256::zero(), + vec![], + ReentrancyProtection::AllowReentry, + false, + ); + + ReachedBottom::mutate(|reached_bottom| { + if *reached_bottom { + // Unwinding the stack: the self-call succeeds here. + assert_matches!(r, Ok(_)); + return; + } + // First time at the bottom: the self-call hit the depth limit. + assert_eq!(r, Err(Error::::MaxCallDepthReached.into())); + *reached_bottom = true; + + let before = ctx.ext.access_list_metrics(); + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), + StateAccessKind::Call { + account: Warmth::Cold { .. }, + contract_info: Warmth::Cold { .. } + }, + "a fresh target starts cold", + ); + + // Calling a fresh target at max depth is denied before a frame is built. + assert_eq!( + ctx.ext.call( + &Default::default(), + &DJANGO_ADDR, + U256::zero(), + vec![], + ReentrancyProtection::AllowReentry, + false, + ), + Err(Error::::MaxCallDepthReached.into()), + "call at max depth is denied", + ); + + assert_eq!( + ctx.ext.access_list_metrics().size, + before.size, + "the denied call warms nothing", + ); + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), + StateAccessKind::Call { + account: Warmth::Cold { .. }, + contract_info: Warmth::Cold { .. } + }, + "the denied call leaves the target cold", + ); + }); + + exec_success() + }); + + ExtBuilder::default().build().execute_with(|| { + set_balance(&BOB, 1); + place_contract(&BOB, recurse_ch); + place_contract(&DJANGO, target_ch); + let origin = Origin::from_account_id(ALICE); + let mut meter = TransactionMeter::::new_from_limits(WEIGHT_LIMIT, 0).unwrap(); + let result = MockStack::run_call( + origin, + BOB_ADDR, + &mut meter, + 0.into(), + vec![], + &ExecConfig::new_substrate_tx(), + ); + assert_matches!(result, Ok(_)); + }); +} + #[test] fn cold_hot_delegate_call_leaves_target_account_cold() { // A delegate call reads only the target's contract metadata and code, so diff --git a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs index 67c1a724a3d9..b00cc44faf27 100644 --- a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs +++ b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs @@ -17,7 +17,6 @@ use crate::{ Pallet, RuntimeCosts, - access_list::StateAccess, precompiles::{All as AllPrecompiles, Precompiles}, vm::{ Ext, @@ -85,11 +84,7 @@ pub fn charge_call_gas<'a, E: Ext>( }, None => { // Regular CALL / DELEGATECALL base cost / CALLCODE not supported. - - // Peek the warmth to price the charge; the entries are touched when - // the frame is built, so peek and touch see the same state. - let access = StateAccess::new(callee, scheme.is_delegate_call()); - let cost = RuntimeCosts::CallBase(interpreter.ext.peek_access(access)); + let cost = interpreter.ext.call_base_cost(callee, scheme.is_delegate_call()); interpreter.ext.charge_or_halt(cost)?; interpreter diff --git a/substrate/frame/revive/src/vm/pvm.rs b/substrate/frame/revive/src/vm/pvm.rs index 9931e4954e32..3b57a998150f 100644 --- a/substrate/frame/revive/src/vm/pvm.rs +++ b/substrate/frame/revive/src/vm/pvm.rs @@ -21,7 +21,6 @@ pub mod env; use crate::{ Code, Config, Error, LOG_TARGET, Pallet, ReentrancyProtection, RuntimeCosts, SENTINEL, - access_list::StateAccess, exec::{CallResources, ExecError, ExecResult, Ext, Key}, limits, metering::ChargedAmount, @@ -279,12 +278,9 @@ enum CallType { } impl CallType { - /// Base cost of the call. Peeks the warmth to price the charge; the - /// entries are touched when the frame is built, so peek and touch see the - /// same state. + /// Base cost of the call. fn cost(&self, ext: &impl Ext, callee: &sp_core::H160) -> RuntimeCosts { - let access = StateAccess::new(*callee, matches!(self, CallType::DelegateCall)); - RuntimeCosts::CallBase(ext.peek_access(access)) + ext.call_base_cost(*callee, matches!(self, CallType::DelegateCall)) } } diff --git a/substrate/frame/revive/src/vm/runtime_costs.rs b/substrate/frame/revive/src/vm/runtime_costs.rs index 752acc6549bf..36b944e12303 100644 --- a/substrate/frame/revive/src/vm/runtime_costs.rs +++ b/substrate/frame/revive/src/vm/runtime_costs.rs @@ -275,13 +275,15 @@ pub(crate) fn cold_hot_base( overlay_probes: u64, costs: CostPair Weight, impl FnOnce() -> Weight>, ) -> Weight { - let opcode_weight = if item_warmths.iter().all(|warmth| warmth.is_hot()) { - (costs.hot)().saturating_add( - RuntimeCosts::hot_storage_overlay_overhead::().saturating_mul(overlay_probes), - ) - } else { - (costs.cold)() - }; + // An empty slice prices cold. + let opcode_weight = + if !item_warmths.is_empty() && item_warmths.iter().all(|warmth| warmth.is_hot()) { + (costs.hot)().saturating_add( + RuntimeCosts::hot_storage_overlay_overhead::().saturating_mul(overlay_probes), + ) + } else { + (costs.cold)() + }; // Add each touched item's access-list overhead on top of the opcode cost. item_warmths.iter().fold(opcode_weight, |weight, warmth| { weight.saturating_add(access_list_overhead::(*warmth)) From 53a8b6d96f9dc2742f02d70d81757210936d7cbc Mon Sep 17 00:00:00 2001 From: "cmd[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 17 Jul 2026 14:20:08 +0000 Subject: [PATCH 5/9] Update from github-actions[bot] running command 'bench --runtime asset-hub-westend dev --pallet pallet_revive --clean' --- .../src/weights/pallet_revive.rs | 860 ++++----- substrate/frame/revive/src/weights.rs | 1666 +++++++++-------- 2 files changed, 1270 insertions(+), 1256 deletions(-) diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs index afcd8ac7599e..e998778673b7 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_revive.rs @@ -16,9 +16,9 @@ //! Autogenerated weights for `pallet_revive` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2026-07-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-07-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `2da6e5f06f98`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `09fa8e0f052a`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 // Executed Command: @@ -56,8 +56,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `279` // Estimated: `1764` - // Minimum execution time: 3_300_000 picoseconds. - Weight::from_parts(3_700_000, 0) + // Minimum execution time: 3_269_000 picoseconds. + Weight::from_parts(3_690_000, 0) .saturating_add(Weight::from_parts(0, 1764)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -71,8 +71,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `605` // Estimated: `4070` - // Minimum execution time: 22_421_000 picoseconds. - Weight::from_parts(24_117_000, 0) + // Minimum execution time: 23_110_000 picoseconds. + Weight::from_parts(25_034_000, 0) .saturating_add(Weight::from_parts(0, 4070)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -84,11 +84,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `738 + k * (69 ±0)` // Estimated: `728 + k * (70 ±0)` - // Minimum execution time: 23_038_000 picoseconds. - Weight::from_parts(5_827_534, 0) + // Minimum execution time: 23_490_000 picoseconds. + Weight::from_parts(13_219_373, 0) .saturating_add(Weight::from_parts(0, 728)) - // Standard Error: 1_075 - .saturating_add(Weight::from_parts(1_313_555, 0).saturating_mul(k.into())) + // Standard Error: 931 + .saturating_add(Weight::from_parts(1_338_810, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(3)) @@ -100,13 +100,13 @@ impl pallet_revive::WeightInfo for WeightInfo { /// The range of component `k` is `[0, 1024]`. fn deletion_queue_per_native_deposit_key(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `630 + k * (52 ±0)` - // Estimated: `645 + k * (53 ±0)` - // Minimum execution time: 23_212_000 picoseconds. - Weight::from_parts(24_436_000, 0) - .saturating_add(Weight::from_parts(0, 645)) - // Standard Error: 1_029 - .saturating_add(Weight::from_parts(1_309_576, 0).saturating_mul(k.into())) + // Measured: `629 + k * (52 ±0)` + // Estimated: `644 + k * (53 ±0)` + // Minimum execution time: 23_255_000 picoseconds. + Weight::from_parts(4_982_054, 0) + .saturating_add(Weight::from_parts(0, 644)) + // Standard Error: 1_087 + .saturating_add(Weight::from_parts(1_335_139, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(3)) @@ -130,22 +130,25 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `4965 + c * (1 ±0)` // Estimated: `10854 + c * (1 ±0)` - // Minimum execution time: 129_739_000 picoseconds. - Weight::from_parts(179_867_634, 0) + // Minimum execution time: 131_561_000 picoseconds. + Weight::from_parts(182_341_252, 0) .saturating_add(Weight::from_parts(0, 10854)) // Standard Error: 13 - .saturating_add(Weight::from_parts(1_579, 0).saturating_mul(c.into())) + .saturating_add(Weight::from_parts(1_744, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot load re-reads a blob already in the proof). + /// The range of component `c` is `[0, 102400]`. fn call_with_pvm_code_per_byte_hot(c: u32, ) -> Weight { - Weight::from_parts(179_867_634, 0) - .saturating_add(Weight::from_parts(1_579, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(2)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 31_482_000 picoseconds. + Weight::from_parts(77_161_991, 0) + .saturating_add(Weight::from_parts(0, 0)) + // Standard Error: 11 + .saturating_add(Weight::from_parts(1_433, 0).saturating_mul(c.into())) } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -164,22 +167,25 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `4940 + c * (1 ±0)` // Estimated: `10782 + c * (1 ±0)` - // Minimum execution time: 118_860_000 picoseconds. - Weight::from_parts(127_674_465, 0) + // Minimum execution time: 122_567_000 picoseconds. + Weight::from_parts(130_694_139, 0) .saturating_add(Weight::from_parts(0, 10782)) - // Standard Error: 13 - .saturating_add(Weight::from_parts(1_780, 0).saturating_mul(c.into())) + // Standard Error: 14 + .saturating_add(Weight::from_parts(1_999, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(2)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot load re-reads a blob already in the proof). + /// The range of component `c` is `[1, 10240]`. fn call_with_evm_code_per_byte_hot(c: u32, ) -> Weight { - Weight::from_parts(127_674_465, 0) - .saturating_add(Weight::from_parts(1_780, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(8)) - .saturating_add(T::DbWeight::get().writes(2)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 26_296_000 picoseconds. + Weight::from_parts(28_093_387, 0) + .saturating_add(Weight::from_parts(0, 0)) + // Standard Error: 5 + .saturating_add(Weight::from_parts(1_847, 0).saturating_mul(c.into())) } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -198,8 +204,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `8297` // Estimated: `14237` - // Minimum execution time: 176_982_000 picoseconds. - Weight::from_parts(185_777_685, 0) + // Minimum execution time: 178_626_000 picoseconds. + Weight::from_parts(187_656_573, 0) .saturating_add(Weight::from_parts(0, 14237)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(2)) @@ -234,13 +240,13 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `6535` // Estimated: `15032` - // Minimum execution time: 876_469_000 picoseconds. - Weight::from_parts(150_028_888, 0) + // Minimum execution time: 918_637_000 picoseconds. + Weight::from_parts(245_812_432, 0) .saturating_add(Weight::from_parts(0, 15032)) - // Standard Error: 44 - .saturating_add(Weight::from_parts(21_256, 0).saturating_mul(c.into())) - // Standard Error: 34 - .saturating_add(Weight::from_parts(5_153, 0).saturating_mul(i.into())) + // Standard Error: 76 + .saturating_add(Weight::from_parts(20_530, 0).saturating_mul(c.into())) + // Standard Error: 60 + .saturating_add(Weight::from_parts(4_741, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(16)) .saturating_add(T::DbWeight::get().writes(12)) } @@ -275,19 +281,17 @@ impl pallet_revive::WeightInfo for WeightInfo { /// The range of component `c` is `[0, 102400]`. /// The range of component `i` is `[0, 131072]`. /// The range of component `d` is `[0, 1]`. - fn eth_instantiate_with_code(c: u32, i: u32, d: u32, ) -> Weight { + fn eth_instantiate_with_code(c: u32, i: u32, _d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `8522` // Estimated: `16937` - // Minimum execution time: 539_346_000 picoseconds. - Weight::from_parts(405_855_058, 0) + // Minimum execution time: 560_697_000 picoseconds. + Weight::from_parts(406_230_554, 0) .saturating_add(Weight::from_parts(0, 16937)) - // Standard Error: 54 - .saturating_add(Weight::from_parts(17_060, 0).saturating_mul(c.into())) - // Standard Error: 42 - .saturating_add(Weight::from_parts(729, 0).saturating_mul(i.into())) - // Standard Error: 3_544_125 - .saturating_add(Weight::from_parts(15_257_366, 0).saturating_mul(d.into())) + // Standard Error: 60 + .saturating_add(Weight::from_parts(17_317, 0).saturating_mul(c.into())) + // Standard Error: 47 + .saturating_add(Weight::from_parts(1_093, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(19)) .saturating_add(T::DbWeight::get().writes(17)) } @@ -295,8 +299,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_112_000 picoseconds. - Weight::from_parts(3_511_000, 0) + // Minimum execution time: 3_287_000 picoseconds. + Weight::from_parts(3_700_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) @@ -326,13 +330,13 @@ impl pallet_revive::WeightInfo for WeightInfo { /// The range of component `i` is `[0, 131072]`. fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6186` - // Estimated: `12115` - // Minimum execution time: 263_897_000 picoseconds. - Weight::from_parts(275_426_529, 0) - .saturating_add(Weight::from_parts(0, 12115)) - // Standard Error: 6 - .saturating_add(Weight::from_parts(4_190, 0).saturating_mul(i.into())) + // Measured: `6146` + // Estimated: `12097` + // Minimum execution time: 257_828_000 picoseconds. + Weight::from_parts(271_668_613, 0) + .saturating_add(Weight::from_parts(0, 12097)) + // Standard Error: 5 + .saturating_add(Weight::from_parts(4_236, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(15)) .saturating_add(T::DbWeight::get().writes(9)) } @@ -350,11 +354,11 @@ impl pallet_revive::WeightInfo for WeightInfo { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `5584` - // Estimated: `11524` - // Minimum execution time: 127_086_000 picoseconds. - Weight::from_parts(135_026_000, 0) - .saturating_add(Weight::from_parts(0, 11524)) + // Measured: `4918` + // Estimated: `10858` + // Minimum execution time: 127_608_000 picoseconds. + Weight::from_parts(134_263_000, 0) + .saturating_add(Weight::from_parts(0, 10858)) .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -377,13 +381,13 @@ impl pallet_revive::WeightInfo for WeightInfo { /// The range of component `d` is `[0, 1]`. fn eth_call(d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `6995` - // Estimated: `12935` - // Minimum execution time: 237_582_000 picoseconds. - Weight::from_parts(250_250_149, 0) - .saturating_add(Weight::from_parts(0, 12935)) - // Standard Error: 385_596 - .saturating_add(Weight::from_parts(4_577_564, 0).saturating_mul(d.into())) + // Measured: `6329` + // Estimated: `12269` + // Minimum execution time: 235_575_000 picoseconds. + Weight::from_parts(247_797_910, 0) + .saturating_add(Weight::from_parts(0, 12269)) + // Standard Error: 391_316 + .saturating_add(Weight::from_parts(3_423_260, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(6)) } @@ -398,11 +402,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `302` // Estimated: `3767` - // Minimum execution time: 27_631_000 picoseconds. - Weight::from_parts(24_434_177, 0) + // Minimum execution time: 28_590_000 picoseconds. + Weight::from_parts(25_680_701, 0) .saturating_add(Weight::from_parts(0, 3767)) - // Standard Error: 4 - .saturating_add(Weight::from_parts(6_323, 0).saturating_mul(c.into())) + // Standard Error: 3 + .saturating_add(Weight::from_parts(6_543, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) } @@ -425,11 +429,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `2305` // Estimated: `5770` - // Minimum execution time: 81_818_000 picoseconds. - Weight::from_parts(69_904_089, 0) + // Minimum execution time: 81_884_000 picoseconds. + Weight::from_parts(85_154_992, 0) .saturating_add(Weight::from_parts(0, 5770)) - // Standard Error: 24 - .saturating_add(Weight::from_parts(14_976, 0).saturating_mul(c.into())) + // Standard Error: 26 + .saturating_add(Weight::from_parts(15_320, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } @@ -445,8 +449,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `2223` // Estimated: `5688` - // Minimum execution time: 63_240_000 picoseconds. - Weight::from_parts(67_467_000, 0) + // Minimum execution time: 63_284_000 picoseconds. + Weight::from_parts(67_841_000, 0) .saturating_add(Weight::from_parts(0, 5688)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(4)) @@ -467,8 +471,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `3304` // Estimated: `9244` - // Minimum execution time: 87_734_000 picoseconds. - Weight::from_parts(92_383_000, 0) + // Minimum execution time: 88_300_000 picoseconds. + Weight::from_parts(93_407_000, 0) .saturating_add(Weight::from_parts(0, 9244)) .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(7)) @@ -483,8 +487,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `3914` // Estimated: `7379` - // Minimum execution time: 73_667_000 picoseconds. - Weight::from_parts(78_280_000, 0) + // Minimum execution time: 74_710_000 picoseconds. + Weight::from_parts(79_785_000, 0) .saturating_add(Weight::from_parts(0, 7379)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(2)) @@ -497,8 +501,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `1793` // Estimated: `5258` - // Minimum execution time: 34_985_000 picoseconds. - Weight::from_parts(37_552_000, 0) + // Minimum execution time: 35_695_000 picoseconds. + Weight::from_parts(38_453_000, 0) .saturating_add(Weight::from_parts(0, 5258)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(2)) @@ -516,11 +520,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `238922 + a * (861 ±0)` // Estimated: `189927 + a * (3400 ±23)` - // Minimum execution time: 11_682_000 picoseconds. - Weight::from_parts(12_003_000, 0) + // Minimum execution time: 11_670_000 picoseconds. + Weight::from_parts(11_971_000, 0) .saturating_add(Weight::from_parts(0, 189927)) - // Standard Error: 54_667 - .saturating_add(Weight::from_parts(65_965_473, 0).saturating_mul(a.into())) + // Standard Error: 65_420 + .saturating_add(Weight::from_parts(66_775_653, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(a.into()))) @@ -532,8 +536,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `302` // Estimated: `3767` - // Minimum execution time: 14_035_000 picoseconds. - Weight::from_parts(15_197_000, 0) + // Minimum execution time: 14_011_000 picoseconds. + Weight::from_parts(15_316_000, 0) .saturating_add(Weight::from_parts(0, 3767)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -542,26 +546,26 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 11_977_000 picoseconds. - Weight::from_parts(13_554_232, 0) + // Minimum execution time: 12_050_000 picoseconds. + Weight::from_parts(13_774_398, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 67 - .saturating_add(Weight::from_parts(140_764, 0).saturating_mul(r.into())) + // Standard Error: 69 + .saturating_add(Weight::from_parts(140_414, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 397_000 picoseconds. - Weight::from_parts(553_000, 0) + // Minimum execution time: 459_000 picoseconds. + Weight::from_parts(621_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn seal_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 424_000 picoseconds. - Weight::from_parts(564_000, 0) + // Minimum execution time: 383_000 picoseconds. + Weight::from_parts(571_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) @@ -570,8 +574,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `1871` // Estimated: `5336` - // Minimum execution time: 14_490_000 picoseconds. - Weight::from_parts(15_700_000, 0) + // Minimum execution time: 14_827_000 picoseconds. + Weight::from_parts(15_962_000, 0) .saturating_add(Weight::from_parts(0, 5336)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -581,8 +585,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `124` // Estimated: `3589` - // Minimum execution time: 5_372_000 picoseconds. - Weight::from_parts(6_044_000, 0) + // Minimum execution time: 5_369_000 picoseconds. + Weight::from_parts(6_119_000, 0) .saturating_add(Weight::from_parts(0, 3589)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -590,8 +594,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_024_000 picoseconds. - Weight::from_parts(4_828_000, 0) + // Minimum execution time: 4_369_000 picoseconds. + Weight::from_parts(5_017_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) @@ -602,8 +606,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `194` // Estimated: `3659` - // Minimum execution time: 11_074_000 picoseconds. - Weight::from_parts(12_062_000, 0) + // Minimum execution time: 11_223_000 picoseconds. + Weight::from_parts(12_185_000, 0) .saturating_add(Weight::from_parts(0, 3659)) .saturating_add(T::DbWeight::get().reads(2)) } @@ -611,48 +615,48 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_673_000 picoseconds. - Weight::from_parts(1_996_000, 0) + // Minimum execution time: 1_813_000 picoseconds. + Weight::from_parts(2_200_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_576_000 picoseconds. - Weight::from_parts(1_904_000, 0) + // Minimum execution time: 1_794_000 picoseconds. + Weight::from_parts(2_117_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 404_000 picoseconds. - Weight::from_parts(536_000, 0) + // Minimum execution time: 371_000 picoseconds. + Weight::from_parts(546_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_685_000 picoseconds. - Weight::from_parts(1_969_000, 0) + // Minimum execution time: 1_772_000 picoseconds. + Weight::from_parts(2_117_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn seal_ref_time_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_797_000 picoseconds. - Weight::from_parts(3_185_000, 0) + // Minimum execution time: 2_708_000 picoseconds. + Weight::from_parts(3_070_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn seal_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_840_000 picoseconds. - Weight::from_parts(5_400_000, 0) + // Minimum execution time: 4_716_000 picoseconds. + Weight::from_parts(5_377_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) @@ -665,8 +669,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `3112` // Estimated: `6577` - // Minimum execution time: 26_682_000 picoseconds. - Weight::from_parts(28_449_000, 0) + // Minimum execution time: 26_819_000 picoseconds. + Weight::from_parts(28_973_000, 0) .saturating_add(Weight::from_parts(0, 6577)) .saturating_add(T::DbWeight::get().reads(3)) } @@ -677,11 +681,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `13 + n * (1 ±0)` // Estimated: `3478 + n * (1 ±0)` - // Minimum execution time: 4_837_000 picoseconds. - Weight::from_parts(5_428_882, 0) + // Minimum execution time: 4_656_000 picoseconds. + Weight::from_parts(5_265_296, 0) .saturating_add(Weight::from_parts(0, 3478)) // Standard Error: 1 - .saturating_add(Weight::from_parts(545, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(805, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -692,75 +696,75 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_414_000 picoseconds. - Weight::from_parts(2_851_505, 0) + // Minimum execution time: 2_402_000 picoseconds. + Weight::from_parts(2_835_374, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 1 - .saturating_add(Weight::from_parts(506, 0).saturating_mul(n.into())) + // Standard Error: 0 + .saturating_add(Weight::from_parts(766, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().writes(1)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 365_000 picoseconds. - Weight::from_parts(491_000, 0) + // Minimum execution time: 362_000 picoseconds. + Weight::from_parts(495_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_912_000 picoseconds. - Weight::from_parts(2_276_000, 0) + // Minimum execution time: 1_993_000 picoseconds. + Weight::from_parts(2_387_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn seal_return_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 346_000 picoseconds. - Weight::from_parts(482_000, 0) + // Minimum execution time: 321_000 picoseconds. + Weight::from_parts(483_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn seal_call_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 343_000 picoseconds. - Weight::from_parts(501_000, 0) + // Minimum execution time: 324_000 picoseconds. + Weight::from_parts(458_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn seal_gas_limit() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 374_000 picoseconds. - Weight::from_parts(498_000, 0) + // Minimum execution time: 340_000 picoseconds. + Weight::from_parts(497_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn seal_gas_price() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_314_000 picoseconds. - Weight::from_parts(1_569_000, 0) + // Minimum execution time: 1_189_000 picoseconds. + Weight::from_parts(1_487_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn seal_base_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_326_000 picoseconds. - Weight::from_parts(1_588_000, 0) + // Minimum execution time: 1_233_000 picoseconds. + Weight::from_parts(1_502_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 381_000 picoseconds. - Weight::from_parts(488_000, 0) + // Minimum execution time: 346_000 picoseconds. + Weight::from_parts(466_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// Storage: `Aura::Authorities` (r:1 w:0) @@ -771,8 +775,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `442` // Estimated: `1927` - // Minimum execution time: 25_484_000 picoseconds. - Weight::from_parts(26_866_000, 0) + // Minimum execution time: 26_009_000 picoseconds. + Weight::from_parts(27_454_000, 0) .saturating_add(Weight::from_parts(0, 1927)) .saturating_add(T::DbWeight::get().reads(2)) } @@ -782,8 +786,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `22` // Estimated: `3487` - // Minimum execution time: 3_721_000 picoseconds. - Weight::from_parts(4_144_000, 0) + // Minimum execution time: 3_684_000 picoseconds. + Weight::from_parts(4_193_000, 0) .saturating_add(Weight::from_parts(0, 3487)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -791,8 +795,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 340_000 picoseconds. - Weight::from_parts(484_000, 0) + // Minimum execution time: 354_000 picoseconds. + Weight::from_parts(480_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `n` is `[0, 1048572]`. @@ -800,18 +804,18 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 581_000 picoseconds. - Weight::from_parts(649_000, 0) + // Minimum execution time: 553_000 picoseconds. + Weight::from_parts(643_000, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(207, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(243, 0).saturating_mul(n.into())) } fn seal_call_data_load() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 380_000 picoseconds. - Weight::from_parts(520_000, 0) + // Minimum execution time: 327_000 picoseconds. + Weight::from_parts(483_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `n` is `[0, 1048576]`. @@ -819,33 +823,35 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 440_000 picoseconds. - Weight::from_parts(70_171, 0) + // Minimum execution time: 375_000 picoseconds. + Weight::from_parts(464_000, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(117, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(152, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 131072]`. fn seal_return(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 399_000 picoseconds. - Weight::from_parts(655_375, 0) + // Minimum execution time: 398_000 picoseconds. + Weight::from_parts(675_453, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(202, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(237, 0).saturating_mul(n.into())) } /// Storage: `Revive::OriginalAccount` (r:2 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) /// The range of component `r` is `[0, 1]`. - fn seal_terminate(_r: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2814` - // Estimated: `8754` - // Minimum execution time: 24_240_000 picoseconds. - Weight::from_parts(26_083_766, 0) - .saturating_add(Weight::from_parts(0, 8754)) + fn seal_terminate(r: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2763` + // Estimated: `8703` + // Minimum execution time: 24_047_000 picoseconds. + Weight::from_parts(26_103_300, 0) + .saturating_add(Weight::from_parts(0, 8703)) + // Standard Error: 27_168 + .saturating_add(Weight::from_parts(99_699, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: `Balances::Holds` (r:2 w:2) @@ -880,11 +886,11 @@ impl pallet_revive::WeightInfo for WeightInfo { /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) fn seal_terminate_logic() -> Weight { // Proof Size summary in bytes: - // Measured: `9527` - // Estimated: `17942` - // Minimum execution time: 380_950_000 picoseconds. - Weight::from_parts(400_857_000, 0) - .saturating_add(Weight::from_parts(0, 17942)) + // Measured: `9574` + // Estimated: `17989` + // Minimum execution time: 382_552_000 picoseconds. + Weight::from_parts(404_512_000, 0) + .saturating_add(Weight::from_parts(0, 17989)) .saturating_add(T::DbWeight::get().reads(16)) .saturating_add(T::DbWeight::get().writes(17)) } @@ -894,11 +900,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_214_000 picoseconds. - Weight::from_parts(6_546_000, 0) + // Minimum execution time: 6_568_000 picoseconds. + Weight::from_parts(6_884_000, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_337, 0).saturating_mul(n.into())) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_504, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -906,8 +912,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `653` // Estimated: `653` - // Minimum execution time: 8_569_000 picoseconds. - Weight::from_parts(9_518_000, 0) + // Minimum execution time: 9_151_000 picoseconds. + Weight::from_parts(10_025_000, 0) .saturating_add(Weight::from_parts(0, 653)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -917,8 +923,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `10663` // Estimated: `10663` - // Minimum execution time: 39_737_000 picoseconds. - Weight::from_parts(41_767_000, 0) + // Minimum execution time: 40_322_000 picoseconds. + Weight::from_parts(42_413_000, 0) .saturating_add(Weight::from_parts(0, 10663)) .saturating_add(T::DbWeight::get().reads(1)) } @@ -928,8 +934,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `653` // Estimated: `653` - // Minimum execution time: 10_043_000 picoseconds. - Weight::from_parts(11_102_000, 0) + // Minimum execution time: 10_295_000 picoseconds. + Weight::from_parts(11_432_000, 0) .saturating_add(Weight::from_parts(0, 653)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -940,8 +946,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `10663` // Estimated: `10663` - // Minimum execution time: 43_093_000 picoseconds. - Weight::from_parts(45_467_000, 0) + // Minimum execution time: 42_780_000 picoseconds. + Weight::from_parts(45_216_000, 0) .saturating_add(Weight::from_parts(0, 10663)) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) @@ -953,11 +959,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 922_287_000 picoseconds. - Weight::from_parts(976_846_980, 0) + // Minimum execution time: 913_475_000 picoseconds. + Weight::from_parts(995_782_197, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 1_447 - .saturating_add(Weight::from_parts(1_041_180, 0).saturating_mul(n.into())) + // Standard Error: 1_787 + .saturating_add(Weight::from_parts(1_088_523, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().writes(2048)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -967,11 +973,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 788_000 picoseconds. - Weight::from_parts(12_579_656, 0) + // Minimum execution time: 755_000 picoseconds. + Weight::from_parts(14_241_497, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 740 - .saturating_add(Weight::from_parts(864_924, 0).saturating_mul(n.into())) + // Standard Error: 991 + .saturating_add(Weight::from_parts(949_141, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -981,13 +987,13 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `253 + o * (1 ±0)` // Estimated: `252 + o * (1 ±0)` - // Minimum execution time: 12_389_000 picoseconds. - Weight::from_parts(13_391_905, 0) + // Minimum execution time: 12_628_000 picoseconds. + Weight::from_parts(14_006_064, 0) .saturating_add(Weight::from_parts(0, 252)) - // Standard Error: 22 - .saturating_add(Weight::from_parts(580, 0).saturating_mul(n.into())) - // Standard Error: 22 - .saturating_add(Weight::from_parts(838, 0).saturating_mul(o.into())) + // Standard Error: 28 + .saturating_add(Weight::from_parts(466, 0).saturating_mul(n.into())) + // Standard Error: 28 + .saturating_add(Weight::from_parts(963, 0).saturating_mul(o.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) @@ -996,17 +1002,15 @@ impl pallet_revive::WeightInfo for WeightInfo { /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 416]`. /// The range of component `o` is `[0, 416]`. - fn seal_set_storage_hot(n: u32, o: u32, ) -> Weight { + fn seal_set_storage_hot(n: u32, _o: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_357_000 picoseconds. - Weight::from_parts(5_912_617, 0) + // Minimum execution time: 5_368_000 picoseconds. + Weight::from_parts(6_147_897, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 11 - .saturating_add(Weight::from_parts(372, 0).saturating_mul(n.into())) - // Standard Error: 11 - .saturating_add(Weight::from_parts(39, 0).saturating_mul(o.into())) + // Standard Error: 13 + .saturating_add(Weight::from_parts(255, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1015,11 +1019,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `253 + n * (1 ±0)` // Estimated: `252 + n * (1 ±0)` - // Minimum execution time: 14_505_000 picoseconds. - Weight::from_parts(15_969_348, 0) + // Minimum execution time: 14_688_000 picoseconds. + Weight::from_parts(16_522_471, 0) .saturating_add(Weight::from_parts(0, 252)) - // Standard Error: 25 - .saturating_add(Weight::from_parts(776, 0).saturating_mul(n.into())) + // Standard Error: 27 + .saturating_add(Weight::from_parts(826, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1027,15 +1031,13 @@ impl pallet_revive::WeightInfo for WeightInfo { /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) /// The range of component `n` is `[0, 416]`. - fn clear_storage_hot(n: u32, ) -> Weight { + fn clear_storage_hot(_n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_474_000 picoseconds. - Weight::from_parts(8_326_822, 0) + // Minimum execution time: 7_503_000 picoseconds. + Weight::from_parts(8_473_763, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 14 - .saturating_add(Weight::from_parts(118, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1044,11 +1046,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `253 + n * (1 ±0)` // Estimated: `252 + n * (1 ±0)` - // Minimum execution time: 11_410_000 picoseconds. - Weight::from_parts(12_666_284, 0) + // Minimum execution time: 11_555_000 picoseconds. + Weight::from_parts(13_202_661, 0) .saturating_add(Weight::from_parts(0, 252)) - // Standard Error: 21 - .saturating_add(Weight::from_parts(1_594, 0).saturating_mul(n.into())) + // Standard Error: 23 + .saturating_add(Weight::from_parts(1_692, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1059,11 +1061,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_044_000 picoseconds. - Weight::from_parts(4_560_300, 0) + // Minimum execution time: 4_008_000 picoseconds. + Weight::from_parts(4_551_728, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 8 - .saturating_add(Weight::from_parts(606, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(794, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1072,11 +1074,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `253 + n * (1 ±0)` // Estimated: `252 + n * (1 ±0)` - // Minimum execution time: 12_955_000 picoseconds. - Weight::from_parts(14_223_683, 0) + // Minimum execution time: 13_020_000 picoseconds. + Weight::from_parts(14_761_316, 0) .saturating_add(Weight::from_parts(0, 252)) - // Standard Error: 21 - .saturating_add(Weight::from_parts(910, 0).saturating_mul(n.into())) + // Standard Error: 25 + .saturating_add(Weight::from_parts(1_048, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1087,11 +1089,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_905_000 picoseconds. - Weight::from_parts(6_666_250, 0) + // Minimum execution time: 6_004_000 picoseconds. + Weight::from_parts(6_676_139, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 10 - .saturating_add(Weight::from_parts(121, 0).saturating_mul(n.into())) + // Standard Error: 9 + .saturating_add(Weight::from_parts(62, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1100,11 +1102,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `253 + n * (1 ±0)` // Estimated: `252 + n * (1 ±0)` - // Minimum execution time: 15_025_000 picoseconds. - Weight::from_parts(16_706_623, 0) + // Minimum execution time: 15_118_000 picoseconds. + Weight::from_parts(17_148_427, 0) .saturating_add(Weight::from_parts(0, 252)) - // Standard Error: 27 - .saturating_add(Weight::from_parts(1_416, 0).saturating_mul(n.into())) + // Standard Error: 31 + .saturating_add(Weight::from_parts(1_742, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1116,90 +1118,90 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_347_000 picoseconds. - Weight::from_parts(8_402_336, 0) + // Minimum execution time: 7_344_000 picoseconds. + Weight::from_parts(8_419_353, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 14 - .saturating_add(Weight::from_parts(723, 0).saturating_mul(n.into())) + // Standard Error: 16 + .saturating_add(Weight::from_parts(774, 0).saturating_mul(n.into())) } fn access_list_touch_cold_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_183_000 picoseconds. - Weight::from_parts(4_319_000, 0) + // Minimum execution time: 3_784_000 picoseconds. + Weight::from_parts(4_451_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn access_list_touch_hot_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_035_000 picoseconds. - Weight::from_parts(1_177_000, 0) + // Minimum execution time: 1_058_000 picoseconds. + Weight::from_parts(1_227_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn access_list_touch_cold_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 471_000 picoseconds. - Weight::from_parts(556_000, 0) + // Minimum execution time: 464_000 picoseconds. + Weight::from_parts(586_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn access_list_touch_hot_single_element() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 573_000 picoseconds. - Weight::from_parts(670_000, 0) + // Minimum execution time: 544_000 picoseconds. + Weight::from_parts(663_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn access_list_rollback_amortization() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_061_000 picoseconds. - Weight::from_parts(4_656_000, 0) + // Minimum execution time: 4_506_000 picoseconds. + Weight::from_parts(5_368_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn set_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_835_000 picoseconds. - Weight::from_parts(2_150_000, 0) + // Minimum execution time: 1_768_000 picoseconds. + Weight::from_parts(2_065_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_188_000 picoseconds. - Weight::from_parts(2_496_000, 0) + // Minimum execution time: 2_164_000 picoseconds. + Weight::from_parts(2_555_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_617_000 picoseconds. - Weight::from_parts(1_863_000, 0) + // Minimum execution time: 1_629_000 picoseconds. + Weight::from_parts(1_912_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_774_000 picoseconds. - Weight::from_parts(2_041_000, 0) + // Minimum execution time: 1_834_000 picoseconds. + Weight::from_parts(2_126_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_419_000 picoseconds. - Weight::from_parts(1_749_000, 0) + // Minimum execution time: 1_438_000 picoseconds. + Weight::from_parts(1_700_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `n` is `[0, 416]`. @@ -1208,64 +1210,62 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_838_000 picoseconds. - Weight::from_parts(3_224_333, 0) + // Minimum execution time: 2_820_000 picoseconds. + Weight::from_parts(3_231_411, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 6 - .saturating_add(Weight::from_parts(277, 0).saturating_mul(n.into())) - // Standard Error: 6 - .saturating_add(Weight::from_parts(350, 0).saturating_mul(o.into())) + // Standard Error: 7 + .saturating_add(Weight::from_parts(255, 0).saturating_mul(n.into())) + // Standard Error: 7 + .saturating_add(Weight::from_parts(379, 0).saturating_mul(o.into())) } /// The range of component `n` is `[0, 416]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_952_000 picoseconds. - Weight::from_parts(5_684_087, 0) + // Minimum execution time: 4_974_000 picoseconds. + Weight::from_parts(5_548_303, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 8 - .saturating_add(Weight::from_parts(315, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(437, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_356_000 picoseconds. - Weight::from_parts(2_783_311, 0) + // Minimum execution time: 2_345_000 picoseconds. + Weight::from_parts(2_740_107, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 5 - .saturating_add(Weight::from_parts(378, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(390, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_300_000 picoseconds. - Weight::from_parts(4_839_980, 0) + // Minimum execution time: 4_386_000 picoseconds. + Weight::from_parts(4_896_229, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 7 - .saturating_add(Weight::from_parts(192, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(195, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. - fn seal_take_transient_storage(_n: u32, ) -> Weight { + fn seal_take_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_335_000 picoseconds. - Weight::from_parts(6_012_885, 0) + // Minimum execution time: 5_363_000 picoseconds. + Weight::from_parts(5_923_484, 0) .saturating_add(Weight::from_parts(0, 0)) + // Standard Error: 7 + .saturating_add(Weight::from_parts(9, 0).saturating_mul(n.into())) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) /// Storage: `Revive::AccountInfoOf` (r:1 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) - /// Storage: `Revive::CodeInfoOf` (r:1 w:0) - /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) - /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `t` is `[0, 1]`. @@ -1273,19 +1273,27 @@ impl pallet_revive::WeightInfo for WeightInfo { /// The range of component `i` is `[0, 1048576]`. fn seal_call(t: u32, d: u32, _i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `3701` - // Estimated: `7166` - // Minimum execution time: 110_810_000 picoseconds. - Weight::from_parts(94_926_944, 0) - .saturating_add(Weight::from_parts(0, 7166)) - // Standard Error: 85_388 - .saturating_add(Weight::from_parts(19_759_589, 0).saturating_mul(t.into())) - // Standard Error: 85_388 - .saturating_add(Weight::from_parts(25_695_778, 0).saturating_mul(d.into())) - .saturating_add(T::DbWeight::get().reads(5)) + // Measured: `2862` + // Estimated: `6327` + // Minimum execution time: 104_124_000 picoseconds. + Weight::from_parts(89_639_071, 0) + .saturating_add(Weight::from_parts(0, 6327)) + // Standard Error: 86_970 + .saturating_add(Weight::from_parts(18_431_604, 0).saturating_mul(t.into())) + // Standard Error: 86_970 + .saturating_add(Weight::from_parts(24_269_109, 0).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(t.into()))) } + fn seal_call_hot() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 30_809_000 picoseconds. + Weight::from_parts(32_717_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } /// Storage: `Revive::AccountInfoOf` (r:1 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) @@ -1296,50 +1304,48 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0 + d * (1380 ±0)` // Estimated: `2423 + d * (2423 ±0)` - // Minimum execution time: 26_682_000 picoseconds. - Weight::from_parts(11_482_200, 0) + // Minimum execution time: 27_000_000 picoseconds. + Weight::from_parts(12_235_433, 0) .saturating_add(Weight::from_parts(0, 2423)) - // Standard Error: 29_584 - .saturating_add(Weight::from_parts(17_339_300, 0).saturating_mul(d.into())) + // Standard Error: 17_071 + .saturating_add(Weight::from_parts(17_455_430, 0).saturating_mul(d.into())) // Standard Error: 0 - .saturating_add(Weight::from_parts(337, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(406, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(d.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(d.into()))) .saturating_add(Weight::from_parts(0, 2423).saturating_mul(d.into())) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) + fn seal_delegate_call() -> Weight { + // Proof Size summary in bytes: + // Measured: `124` + // Estimated: `3589` + // Minimum execution time: 31_047_000 picoseconds. + Weight::from_parts(33_716_000, 0) + .saturating_add(Weight::from_parts(0, 3589)) + .saturating_add(T::DbWeight::get().reads(1)) + } + fn seal_delegate_call_hot() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 29_216_000 picoseconds. + Weight::from_parts(31_200_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn seal_delegate_call() -> Weight { - // Proof Size summary in bytes: - // Measured: `747` - // Estimated: `4212` - // Minimum execution time: 37_041_000 picoseconds. - Weight::from_parts(39_798_000, 0) - .saturating_add(Weight::from_parts(0, 4212)) - .saturating_add(T::DbWeight::get().reads(3)) - } - // Placeholder until `/cmd bench` runs the `code_load` benchmark: proof-only - // over-approximation reusing seal_delegate_call's {AccountInfoOf, CodeInfoOf, - // PristineCode} proof, which is a superset of the {CodeInfoOf, PristineCode} read. fn code_load() -> Weight { - Weight::from_parts(0, Self::seal_delegate_call().proof_size()) - } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot call re-reads state already in the proof). - fn seal_call_hot() -> Weight { - Weight::from_parts(94_926_944, 0) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(1)) - } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot call re-reads state already in the proof). - fn seal_delegate_call_hot() -> Weight { - Weight::from_parts(39_798_000, 0) - .saturating_add(T::DbWeight::get().reads(3)) + // Proof Size summary in bytes: + // Measured: `980` + // Estimated: `4445` + // Minimum execution time: 12_518_000 picoseconds. + Weight::from_parts(13_594_000, 0) + .saturating_add(Weight::from_parts(0, 4445)) + .saturating_add(T::DbWeight::get().reads(2)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) @@ -1364,17 +1370,17 @@ impl pallet_revive::WeightInfo for WeightInfo { /// The range of component `i` is `[0, 131072]`. fn seal_instantiate(t: u32, d: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2593` - // Estimated: `6162` - // Minimum execution time: 212_200_000 picoseconds. - Weight::from_parts(162_535_729, 0) - .saturating_add(Weight::from_parts(0, 6162)) - // Standard Error: 428_311 - .saturating_add(Weight::from_parts(26_462_145, 0).saturating_mul(t.into())) - // Standard Error: 428_311 - .saturating_add(Weight::from_parts(32_222_317, 0).saturating_mul(d.into())) - // Standard Error: 5 - .saturating_add(Weight::from_parts(4_056, 0).saturating_mul(i.into())) + // Measured: `2518` + // Estimated: `6049` + // Minimum execution time: 219_373_000 picoseconds. + Weight::from_parts(172_456_952, 0) + .saturating_add(Weight::from_parts(0, 6049)) + // Standard Error: 415_417 + .saturating_add(Weight::from_parts(23_751_795, 0).saturating_mul(t.into())) + // Standard Error: 415_417 + .saturating_add(Weight::from_parts(32_913_312, 0).saturating_mul(d.into())) + // Standard Error: 4 + .saturating_add(Weight::from_parts(4_091, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(7)) } @@ -1407,15 +1413,15 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `4102` // Estimated: `9574 + d * (405 ±35) + t * (405 ±35)` - // Minimum execution time: 451_084_000 picoseconds. - Weight::from_parts(313_299_110, 0) + // Minimum execution time: 465_706_000 picoseconds. + Weight::from_parts(343_589_049, 0) .saturating_add(Weight::from_parts(0, 9574)) - // Standard Error: 675_975 - .saturating_add(Weight::from_parts(21_084_348, 0).saturating_mul(t.into())) - // Standard Error: 675_975 - .saturating_add(Weight::from_parts(31_426_615, 0).saturating_mul(d.into())) - // Standard Error: 26 - .saturating_add(Weight::from_parts(8_179, 0).saturating_mul(i.into())) + // Standard Error: 587_529 + .saturating_add(Weight::from_parts(16_910_247, 0).saturating_mul(t.into())) + // Standard Error: 587_529 + .saturating_add(Weight::from_parts(26_058_386, 0).saturating_mul(d.into())) + // Standard Error: 23 + .saturating_add(Weight::from_parts(8_023, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(14)) .saturating_add(T::DbWeight::get().writes(11)) .saturating_add(Weight::from_parts(0, 405).saturating_mul(d.into())) @@ -1426,108 +1432,108 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_023_000 picoseconds. - Weight::from_parts(18_062_080, 0) + // Minimum execution time: 2_005_000 picoseconds. + Weight::from_parts(14_170_008, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_269, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_309, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn identity(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_215_000 picoseconds. - Weight::from_parts(1_353_378, 0) + // Minimum execution time: 1_288_000 picoseconds. + Weight::from_parts(1_118_732, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(115, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(150, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn ripemd_160(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_014_000 picoseconds. - Weight::from_parts(6_940_594, 0) + // Minimum execution time: 2_032_000 picoseconds. + Weight::from_parts(5_358_279, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(3_724, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_764, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_366_000 picoseconds. - Weight::from_parts(20_296_999, 0) + // Minimum execution time: 1_523_000 picoseconds. + Weight::from_parts(16_470_585, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(3_563, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_602, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_722_000 picoseconds. - Weight::from_parts(20_345_224, 0) + // Minimum execution time: 2_863_000 picoseconds. + Weight::from_parts(14_729_946, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_424, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_455, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_735_000 picoseconds. - Weight::from_parts(21_724_877, 0) + // Minimum execution time: 2_718_000 picoseconds. + Weight::from_parts(15_232_617, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_421, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_458, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048321]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 44_308_000 picoseconds. - Weight::from_parts(96_254_067, 0) + // Minimum execution time: 44_587_000 picoseconds. + Weight::from_parts(96_007_722, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 4 - .saturating_add(Weight::from_parts(4_922, 0).saturating_mul(n.into())) + // Standard Error: 3 + .saturating_add(Weight::from_parts(4_867, 0).saturating_mul(n.into())) } fn ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 48_800_000 picoseconds. - Weight::from_parts(50_121_000, 0) + // Minimum execution time: 49_432_000 picoseconds. + Weight::from_parts(50_956_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn p256_verify() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_804_492_000 picoseconds. - Weight::from_parts(1_820_436_000, 0) + // Minimum execution time: 1_807_316_000 picoseconds. + Weight::from_parts(1_820_852_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn bn128_add() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 16_812_000 picoseconds. - Weight::from_parts(18_195_000, 0) + // Minimum execution time: 16_794_000 picoseconds. + Weight::from_parts(18_212_000, 0) .saturating_add(Weight::from_parts(0, 0)) } fn bn128_mul() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 985_095_000 picoseconds. - Weight::from_parts(1_000_202_000, 0) + // Minimum execution time: 978_342_000 picoseconds. + Weight::from_parts(992_630_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `n` is `[0, 20]`. @@ -1535,29 +1541,29 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_494_000 picoseconds. - Weight::from_parts(4_968_864_584, 0) + // Minimum execution time: 1_408_000 picoseconds. + Weight::from_parts(4_895_549_289, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 10_525_515 - .saturating_add(Weight::from_parts(6_023_077_711, 0).saturating_mul(n.into())) + // Standard Error: 11_461_815 + .saturating_add(Weight::from_parts(6_005_733_645, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1200]`. fn blake2f(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_472_000 picoseconds. - Weight::from_parts(1_854_056, 0) + // Minimum execution time: 1_441_000 picoseconds. + Weight::from_parts(1_843_559, 0) .saturating_add(Weight::from_parts(0, 0)) // Standard Error: 2 - .saturating_add(Weight::from_parts(29_525, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(29_387, 0).saturating_mul(n.into())) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 13_357_000 picoseconds. - Weight::from_parts(13_724_000, 0) + // Minimum execution time: 15_068_000 picoseconds. + Weight::from_parts(15_484_000, 0) .saturating_add(Weight::from_parts(0, 0)) } /// The range of component `r` is `[0, 10000]`. @@ -1565,33 +1571,33 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 758_000 picoseconds. - Weight::from_parts(1_250_305, 0) + // Minimum execution time: 783_000 picoseconds. + Weight::from_parts(1_084_692, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 2 - .saturating_add(Weight::from_parts(7_741, 0).saturating_mul(r.into())) + // Standard Error: 3 + .saturating_add(Weight::from_parts(7_761, 0).saturating_mul(r.into())) } /// The range of component `r` is `[0, 10000]`. fn instr(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 14_139_000 picoseconds. - Weight::from_parts(79_060_450, 0) + // Minimum execution time: 12_971_000 picoseconds. + Weight::from_parts(57_272_887, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 776 - .saturating_add(Weight::from_parts(85_264, 0).saturating_mul(r.into())) + // Standard Error: 511 + .saturating_add(Weight::from_parts(71_752, 0).saturating_mul(r.into())) } /// The range of component `r` is `[0, 10000]`. fn instr_empty_loop(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_541_000 picoseconds. - Weight::from_parts(5_671_025, 0) + // Minimum execution time: 5_115_000 picoseconds. + Weight::from_parts(5_571_134, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 23 - .saturating_add(Weight::from_parts(40_324, 0).saturating_mul(r.into())) + // Standard Error: 13 + .saturating_add(Weight::from_parts(39_115, 0).saturating_mul(r.into())) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -1602,13 +1608,13 @@ impl pallet_revive::WeightInfo for WeightInfo { /// The range of component `n` is `[1000, 102400]`. fn extcodecopy(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `365 + n * (1 ±0)` + // Measured: `366 + n * (1 ±0)` // Estimated: `3829 + n * (1 ±0)` - // Minimum execution time: 22_521_000 picoseconds. - Weight::from_parts(19_656_443, 0) + // Minimum execution time: 23_391_000 picoseconds. + Weight::from_parts(20_613_853, 0) .saturating_add(Weight::from_parts(0, 3829)) - // Standard Error: 5 - .saturating_add(Weight::from_parts(1_139, 0).saturating_mul(n.into())) + // Standard Error: 7 + .saturating_add(Weight::from_parts(1_404, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1620,8 +1626,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `448` // Estimated: `6388` - // Minimum execution time: 12_804_000 picoseconds. - Weight::from_parts(13_877_000, 0) + // Minimum execution time: 12_502_000 picoseconds. + Weight::from_parts(13_507_000, 0) .saturating_add(Weight::from_parts(0, 6388)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(2)) @@ -1636,8 +1642,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `3620` // Estimated: `6722` - // Minimum execution time: 78_079_000 picoseconds. - Weight::from_parts(82_981_000, 0) + // Minimum execution time: 78_769_000 picoseconds. + Weight::from_parts(82_904_000, 0) .saturating_add(Weight::from_parts(0, 6722)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) @@ -1652,8 +1658,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `3804` // Estimated: `6196` - // Minimum execution time: 112_981_000 picoseconds. - Weight::from_parts(120_659_000, 0) + // Minimum execution time: 110_749_000 picoseconds. + Weight::from_parts(116_434_000, 0) .saturating_add(Weight::from_parts(0, 6196)) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(3)) @@ -1666,8 +1672,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `564` // Estimated: `6134` - // Minimum execution time: 18_248_000 picoseconds. - Weight::from_parts(19_762_000, 0) + // Minimum execution time: 17_932_000 picoseconds. + Weight::from_parts(19_447_000, 0) .saturating_add(Weight::from_parts(0, 6134)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -1696,8 +1702,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `6302` // Estimated: `6434` - // Minimum execution time: 180_373_000 picoseconds. - Weight::from_parts(189_401_000, 0) + // Minimum execution time: 179_076_000 picoseconds. + Weight::from_parts(188_206_000, 0) .saturating_add(Weight::from_parts(0, 6434)) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(8)) @@ -1708,8 +1714,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `379` // Estimated: `6288` - // Minimum execution time: 11_073_000 picoseconds. - Weight::from_parts(12_001_000, 0) + // Minimum execution time: 10_795_000 picoseconds. + Weight::from_parts(11_712_000, 0) .saturating_add(Weight::from_parts(0, 6288)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -1730,12 +1736,12 @@ impl pallet_revive::WeightInfo for WeightInfo { fn on_finalize_per_transaction(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `3004 + n * (97 ±0)` - // Estimated: `6296 + n * (104 ±2)` - // Minimum execution time: 28_301_000 picoseconds. - Weight::from_parts(57_552_911, 0) + // Estimated: `6296 + n * (104 ±1)` + // Minimum execution time: 28_015_000 picoseconds. + Weight::from_parts(57_446_889, 0) .saturating_add(Weight::from_parts(0, 6296)) - // Standard Error: 4_705 - .saturating_add(Weight::from_parts(547_036, 0).saturating_mul(n.into())) + // Standard Error: 4_798 + .saturating_add(Weight::from_parts(553_717, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(5)) .saturating_add(Weight::from_parts(0, 104).saturating_mul(n.into())) @@ -1757,11 +1763,11 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `3570 + d * (3 ±0)` // Estimated: `7029 + d * (3 ±0)` - // Minimum execution time: 60_585_000 picoseconds. - Weight::from_parts(63_429_395, 0) + // Minimum execution time: 61_178_000 picoseconds. + Weight::from_parts(63_661_413, 0) .saturating_add(Weight::from_parts(0, 7029)) // Standard Error: 74 - .saturating_add(Weight::from_parts(11_228, 0).saturating_mul(d.into())) + .saturating_add(Weight::from_parts(12_690, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(5)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(d.into())) @@ -1785,8 +1791,8 @@ impl pallet_revive::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `2215` // Estimated: `5680` - // Minimum execution time: 49_687_000 picoseconds. - Weight::from_parts(52_204_928, 0) + // Minimum execution time: 50_826_000 picoseconds. + Weight::from_parts(53_613_227, 0) .saturating_add(Weight::from_parts(0, 5680)) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) @@ -1806,13 +1812,15 @@ impl pallet_revive::WeightInfo for WeightInfo { /// Storage: `Revive::ReceiptInfoData` (r:0 w:1) /// Proof: `Revive::ReceiptInfoData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `d` is `[0, 16384]`. - fn on_finalize_per_event_data(_d: u32, ) -> Weight { + fn on_finalize_per_event_data(d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `2215` // Estimated: `5680` - // Minimum execution time: 49_681_000 picoseconds. - Weight::from_parts(52_347_879, 0) + // Minimum execution time: 51_080_000 picoseconds. + Weight::from_parts(53_624_504, 0) .saturating_add(Weight::from_parts(0, 5680)) + // Standard Error: 1 + .saturating_add(Weight::from_parts(9, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(5)) } diff --git a/substrate/frame/revive/src/weights.rs b/substrate/frame/revive/src/weights.rs index d9890bc1a9e9..148d4637a972 100644 --- a/substrate/frame/revive/src/weights.rs +++ b/substrate/frame/revive/src/weights.rs @@ -35,9 +35,9 @@ //! Autogenerated weights for `pallet_revive` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2026-07-08, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-07-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `2da6e5f06f98`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `09fa8e0f052a`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: `1024` // Executed Command: @@ -76,8 +76,8 @@ pub trait WeightInfo { fn deletion_queue_per_trie_key(k: u32, ) -> Weight; fn deletion_queue_per_native_deposit_key(k: u32, ) -> Weight; fn call_with_pvm_code_per_byte(c: u32, ) -> Weight; - fn call_with_evm_code_per_byte(c: u32, ) -> Weight; fn call_with_pvm_code_per_byte_hot(c: u32, ) -> Weight; + fn call_with_evm_code_per_byte(c: u32, ) -> Weight; fn call_with_evm_code_per_byte_hot(c: u32, ) -> Weight; fn basic_block_compilation(b: u32, ) -> Weight; fn instantiate_with_code(c: u32, i: u32, ) -> Weight; @@ -161,9 +161,9 @@ pub trait WeightInfo { fn seal_take_transient_storage(n: u32, ) -> Weight; fn seal_call(t: u32, d: u32, i: u32, ) -> Weight; fn seal_call_hot() -> Weight; - fn seal_delegate_call_hot() -> Weight; fn seal_call_precompile(d: u32, i: u32, ) -> Weight; fn seal_delegate_call() -> Weight; + fn seal_delegate_call_hot() -> Weight; fn code_load() -> Weight; fn seal_instantiate(t: u32, d: u32, i: u32, ) -> Weight; fn evm_instantiate(t: u32, d: u32, i: u32, ) -> Weight; @@ -206,8 +206,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `213` // Estimated: `1698` - // Minimum execution time: 3_078_000 picoseconds. - Weight::from_parts(3_415_000, 1698) + // Minimum execution time: 2_962_000 picoseconds. + Weight::from_parts(3_287_000, 1698) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Revive::DeletionQueueCounter` (r:1 w:1) @@ -218,8 +218,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `390` // Estimated: `3855` - // Minimum execution time: 17_557_000 picoseconds. - Weight::from_parts(18_994_000, 3855) + // Minimum execution time: 17_627_000 picoseconds. + Weight::from_parts(19_156_000, 3855) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -230,10 +230,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `524 + k * (69 ±0)` // Estimated: `514 + k * (70 ±0)` - // Minimum execution time: 18_131_000 picoseconds. - Weight::from_parts(18_672_000, 514) - // Standard Error: 881 - .saturating_add(Weight::from_parts(1_200_222, 0).saturating_mul(k.into())) + // Minimum execution time: 18_343_000 picoseconds. + Weight::from_parts(4_012_746, 514) + // Standard Error: 932 + .saturating_add(Weight::from_parts(1_228_883, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -247,10 +247,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `469 + k * (52 ±0)` // Estimated: `479 + k * (53 ±0)` - // Minimum execution time: 18_129_000 picoseconds. - Weight::from_parts(18_629_000, 479) - // Standard Error: 967 - .saturating_add(Weight::from_parts(1_207_151, 0).saturating_mul(k.into())) + // Minimum execution time: 18_434_000 picoseconds. + Weight::from_parts(18_767_000, 479) + // Standard Error: 841 + .saturating_add(Weight::from_parts(1_214_573, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes(2_u64)) @@ -274,14 +274,24 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1267 + c * (1 ±0)` // Estimated: `7204 + c * (1 ±0)` - // Minimum execution time: 100_740_000 picoseconds. - Weight::from_parts(148_471_832, 7204) - // Standard Error: 14 - .saturating_add(Weight::from_parts(1_601, 0).saturating_mul(c.into())) + // Minimum execution time: 100_825_000 picoseconds. + Weight::from_parts(151_084_583, 7204) + // Standard Error: 13 + .saturating_add(Weight::from_parts(1_519, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } + /// The range of component `c` is `[0, 102400]`. + fn call_with_pvm_code_per_byte_hot(c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 24_520_000 picoseconds. + Weight::from_parts(71_168_932, 0) + // Standard Error: 11 + .saturating_add(Weight::from_parts(1_199, 0).saturating_mul(c.into())) + } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:2 w:0) @@ -299,29 +309,23 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1208 + c * (1 ±0)` // Estimated: `7145 + c * (1 ±0)` - // Minimum execution time: 94_505_000 picoseconds. - Weight::from_parts(99_411_753, 7145) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_741, 0).saturating_mul(c.into())) + // Minimum execution time: 95_703_000 picoseconds. + Weight::from_parts(101_330_448, 7145) + // Standard Error: 8 + .saturating_add(Weight::from_parts(1_593, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot load re-reads a blob already in the proof). - fn call_with_pvm_code_per_byte_hot(c: u32, ) -> Weight { - Weight::from_parts(148_471_832, 0) - .saturating_add(Weight::from_parts(1_601, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot load re-reads a blob already in the proof). + /// The range of component `c` is `[1, 10240]`. fn call_with_evm_code_per_byte_hot(c: u32, ) -> Weight { - Weight::from_parts(99_411_753, 0) - .saturating_add(Weight::from_parts(1_741, 0).saturating_mul(c.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 20_583_000 picoseconds. + Weight::from_parts(22_195_758, 0) + // Standard Error: 6 + .saturating_add(Weight::from_parts(1_610, 0).saturating_mul(c.into())) } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -336,14 +340,12 @@ impl WeightInfo for SubstrateWeight { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `b` is `[0, 1]`. - fn basic_block_compilation(b: u32, ) -> Weight { + fn basic_block_compilation(_b: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `4609` // Estimated: `10549` - // Minimum execution time: 150_640_000 picoseconds. - Weight::from_parts(158_446_397, 10549) - // Standard Error: 256_147 - .saturating_add(Weight::from_parts(108_702, 0).saturating_mul(b.into())) + // Minimum execution time: 152_556_000 picoseconds. + Weight::from_parts(159_383_691, 10549) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -369,12 +371,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `880` // Estimated: `6826` - // Minimum execution time: 785_146_000 picoseconds. - Weight::from_parts(96_655_352, 6826) - // Standard Error: 35 - .saturating_add(Weight::from_parts(20_829, 0).saturating_mul(c.into())) + // Minimum execution time: 783_983_000 picoseconds. + Weight::from_parts(102_741_454, 6826) + // Standard Error: 34 + .saturating_add(Weight::from_parts(19_934, 0).saturating_mul(c.into())) // Standard Error: 27 - .saturating_add(Weight::from_parts(4_955, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(4_947, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -401,18 +403,16 @@ impl WeightInfo for SubstrateWeight { /// The range of component `c` is `[0, 102400]`. /// The range of component `i` is `[0, 131072]`. /// The range of component `d` is `[0, 1]`. - fn eth_instantiate_with_code(c: u32, i: u32, d: u32, ) -> Weight { + fn eth_instantiate_with_code(c: u32, i: u32, _d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `981` // Estimated: `6921` - // Minimum execution time: 420_604_000 picoseconds. - Weight::from_parts(287_137_358, 6921) - // Standard Error: 44 - .saturating_add(Weight::from_parts(16_341, 0).saturating_mul(c.into())) - // Standard Error: 34 - .saturating_add(Weight::from_parts(912, 0).saturating_mul(i.into())) - // Standard Error: 2_886_713 - .saturating_add(Weight::from_parts(10_317_725, 0).saturating_mul(d.into())) + // Minimum execution time: 421_825_000 picoseconds. + Weight::from_parts(357_225_914, 6921) + // Standard Error: 58 + .saturating_add(Weight::from_parts(15_912, 0).saturating_mul(c.into())) + // Standard Error: 45 + .saturating_add(Weight::from_parts(328, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(11_u64)) .saturating_add(T::DbWeight::get().writes(10_u64)) } @@ -420,8 +420,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_845_000 picoseconds. - Weight::from_parts(3_155_000, 0) + // Minimum execution time: 2_953_000 picoseconds. + Weight::from_parts(3_322_000, 0) } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -443,11 +443,11 @@ impl WeightInfo for SubstrateWeight { fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1510` - // Estimated: `7447` - // Minimum execution time: 176_916_000 picoseconds. - Weight::from_parts(184_330_194, 7447) - // Standard Error: 5 - .saturating_add(Weight::from_parts(4_389, 0).saturating_mul(i.into())) + // Estimated: `7443` + // Minimum execution time: 176_953_000 picoseconds. + Weight::from_parts(182_761_060, 7443) + // Standard Error: 4 + .saturating_add(Weight::from_parts(4_336, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -465,10 +465,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `1698` - // Estimated: `7638` - // Minimum execution time: 98_637_000 picoseconds. - Weight::from_parts(103_497_000, 7638) + // Measured: `1746` + // Estimated: `7686` + // Minimum execution time: 100_324_000 picoseconds. + Weight::from_parts(105_719_000, 7686) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -491,12 +491,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `d` is `[0, 1]`. fn eth_call(d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1698` - // Estimated: `7638` - // Minimum execution time: 181_834_000 picoseconds. - Weight::from_parts(190_697_274, 7638) - // Standard Error: 220_888 - .saturating_add(Weight::from_parts(3_908_244, 0).saturating_mul(d.into())) + // Measured: `1746` + // Estimated: `7686` + // Minimum execution time: 183_381_000 picoseconds. + Weight::from_parts(193_758_233, 7686) + // Standard Error: 245_086 + .saturating_add(Weight::from_parts(3_765_029, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(9_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -515,10 +515,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `381` // Estimated: `3846` - // Minimum execution time: 31_364_000 picoseconds. - Weight::from_parts(27_032_161, 3846) - // Standard Error: 4 - .saturating_add(Weight::from_parts(6_475, 0).saturating_mul(c.into())) + // Minimum execution time: 31_508_000 picoseconds. + Weight::from_parts(27_466_638, 3846) + // Standard Error: 3 + .saturating_add(Weight::from_parts(6_387, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -535,10 +535,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `291` // Estimated: `3756` - // Minimum execution time: 61_026_000 picoseconds. - Weight::from_parts(47_131_680, 3756) - // Standard Error: 21 - .saturating_add(Weight::from_parts(14_816, 0).saturating_mul(c.into())) + // Minimum execution time: 60_597_000 picoseconds. + Weight::from_parts(53_153_595, 3756) + // Standard Error: 22 + .saturating_add(Weight::from_parts(15_011, 0).saturating_mul(c.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -552,8 +552,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `423` // Estimated: `3888` - // Minimum execution time: 51_061_000 picoseconds. - Weight::from_parts(54_352_000, 3888) + // Minimum execution time: 51_171_000 picoseconds. + Weight::from_parts(54_079_000, 3888) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -571,8 +571,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `867` // Estimated: `6807` - // Minimum execution time: 67_577_000 picoseconds. - Weight::from_parts(71_341_000, 6807) + // Minimum execution time: 66_569_000 picoseconds. + Weight::from_parts(70_668_000, 6807) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) } @@ -586,8 +586,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `623` // Estimated: `4088` - // Minimum execution time: 59_787_000 picoseconds. - Weight::from_parts(63_418_000, 4088) + // Minimum execution time: 59_319_000 picoseconds. + Weight::from_parts(62_813_000, 4088) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -599,8 +599,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `93` // Estimated: `3558` - // Minimum execution time: 39_659_000 picoseconds. - Weight::from_parts(42_554_000, 3558) + // Minimum execution time: 39_038_000 picoseconds. + Weight::from_parts(41_550_000, 3558) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -617,10 +617,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `563 + a * (209 ±0)` // Estimated: `4008 + a * (2684 ±0)` - // Minimum execution time: 10_918_000 picoseconds. - Weight::from_parts(11_238_000, 4008) - // Standard Error: 73_798 - .saturating_add(Weight::from_parts(49_660_410, 0).saturating_mul(a.into())) + // Minimum execution time: 10_858_000 picoseconds. + Weight::from_parts(10_969_000, 4008) + // Standard Error: 62_375 + .saturating_add(Weight::from_parts(48_487_766, 0).saturating_mul(a.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(a.into()))) @@ -636,8 +636,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `381` // Estimated: `3846` - // Minimum execution time: 18_295_000 picoseconds. - Weight::from_parts(19_704_000, 3846) + // Minimum execution time: 18_397_000 picoseconds. + Weight::from_parts(19_831_000, 3846) .saturating_add(T::DbWeight::get().reads(3_u64)) } /// The range of component `r` is `[0, 1600]`. @@ -645,24 +645,24 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_002_000 picoseconds. - Weight::from_parts(10_808_148, 0) - // Standard Error: 46 - .saturating_add(Weight::from_parts(141_532, 0).saturating_mul(r.into())) + // Minimum execution time: 9_006_000 picoseconds. + Weight::from_parts(11_074_481, 0) + // Standard Error: 59 + .saturating_add(Weight::from_parts(138_548, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 357_000 picoseconds. - Weight::from_parts(463_000, 0) + // Minimum execution time: 315_000 picoseconds. + Weight::from_parts(425_000, 0) } fn seal_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 339_000 picoseconds. - Weight::from_parts(445_000, 0) + // Minimum execution time: 306_000 picoseconds. + Weight::from_parts(380_000, 0) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) @@ -670,8 +670,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `365` // Estimated: `3830` - // Minimum execution time: 7_429_000 picoseconds. - Weight::from_parts(8_340_000, 3830) + // Minimum execution time: 7_354_000 picoseconds. + Weight::from_parts(8_190_000, 3830) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) @@ -680,16 +680,16 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `124` // Estimated: `3589` - // Minimum execution time: 4_260_000 picoseconds. - Weight::from_parts(4_794_000, 3589) + // Minimum execution time: 4_103_000 picoseconds. + Weight::from_parts(4_610_000, 3589) .saturating_add(T::DbWeight::get().reads(1_u64)) } fn own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_417_000 picoseconds. - Weight::from_parts(3_937_000, 0) + // Minimum execution time: 3_280_000 picoseconds. + Weight::from_parts(3_738_000, 0) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -699,51 +699,51 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `196` // Estimated: `3661` - // Minimum execution time: 7_788_000 picoseconds. - Weight::from_parts(8_510_000, 3661) + // Minimum execution time: 7_343_000 picoseconds. + Weight::from_parts(8_144_000, 3661) .saturating_add(T::DbWeight::get().reads(2_u64)) } fn caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_265_000 picoseconds. - Weight::from_parts(1_552_000, 0) + // Minimum execution time: 1_199_000 picoseconds. + Weight::from_parts(1_446_000, 0) } fn caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_182_000 picoseconds. - Weight::from_parts(1_472_000, 0) + // Minimum execution time: 1_160_000 picoseconds. + Weight::from_parts(1_417_000, 0) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 334_000 picoseconds. - Weight::from_parts(445_000, 0) + // Minimum execution time: 314_000 picoseconds. + Weight::from_parts(392_000, 0) } fn weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_235_000 picoseconds. - Weight::from_parts(1_528_000, 0) + // Minimum execution time: 1_174_000 picoseconds. + Weight::from_parts(1_413_000, 0) } fn seal_ref_time_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_004_000 picoseconds. - Weight::from_parts(2_280_000, 0) + // Minimum execution time: 1_948_000 picoseconds. + Weight::from_parts(2_222_000, 0) } fn seal_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_428_000 picoseconds. - Weight::from_parts(4_898_000, 0) + // Minimum execution time: 4_377_000 picoseconds. + Weight::from_parts(4_811_000, 0) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) @@ -755,8 +755,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `539` // Estimated: `4004` - // Minimum execution time: 13_965_000 picoseconds. - Weight::from_parts(14_997_000, 4004) + // Minimum execution time: 13_714_000 picoseconds. + Weight::from_parts(14_810_000, 4004) .saturating_add(T::DbWeight::get().reads(3_u64)) } /// Storage: `Revive::ImmutableDataOf` (r:1 w:0) @@ -766,10 +766,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `13 + n * (1 ±0)` // Estimated: `3478 + n * (1 ±0)` - // Minimum execution time: 4_103_000 picoseconds. - Weight::from_parts(4_732_656, 3478) + // Minimum execution time: 4_086_000 picoseconds. + Weight::from_parts(4_703_771, 3478) // Standard Error: 0 - .saturating_add(Weight::from_parts(537, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(531, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -780,67 +780,67 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_037_000 picoseconds. - Weight::from_parts(2_373_000, 0) + // Minimum execution time: 2_020_000 picoseconds. + Weight::from_parts(2_367_213, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(549, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(545, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().writes(1_u64)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 297_000 picoseconds. - Weight::from_parts(396_000, 0) + // Minimum execution time: 268_000 picoseconds. + Weight::from_parts(356_000, 0) } fn minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_414_000 picoseconds. - Weight::from_parts(1_731_000, 0) + // Minimum execution time: 1_351_000 picoseconds. + Weight::from_parts(1_654_000, 0) } fn seal_return_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 289_000 picoseconds. - Weight::from_parts(389_000, 0) + // Minimum execution time: 261_000 picoseconds. + Weight::from_parts(335_000, 0) } fn seal_call_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 288_000 picoseconds. - Weight::from_parts(381_000, 0) + // Minimum execution time: 262_000 picoseconds. + Weight::from_parts(334_000, 0) } fn seal_gas_limit() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 304_000 picoseconds. - Weight::from_parts(398_000, 0) + // Minimum execution time: 263_000 picoseconds. + Weight::from_parts(356_000, 0) } fn seal_gas_price() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_062_000 picoseconds. - Weight::from_parts(1_278_000, 0) + // Minimum execution time: 1_001_000 picoseconds. + Weight::from_parts(1_217_000, 0) } fn seal_base_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_044_000 picoseconds. - Weight::from_parts(1_249_000, 0) + // Minimum execution time: 978_000 picoseconds. + Weight::from_parts(1_181_000, 0) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 295_000 picoseconds. - Weight::from_parts(396_000, 0) + // Minimum execution time: 269_000 picoseconds. + Weight::from_parts(360_000, 0) } /// Storage: `Session::Validators` (r:1 w:0) /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -848,8 +848,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 19_240_000 picoseconds. - Weight::from_parts(20_538_000, 1627) + // Minimum execution time: 18_545_000 picoseconds. + Weight::from_parts(19_722_000, 1627) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Revive::BlockHash` (r:1 w:0) @@ -858,41 +858,41 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `22` // Estimated: `3487` - // Minimum execution time: 3_223_000 picoseconds. - Weight::from_parts(3_608_000, 3487) + // Minimum execution time: 3_145_000 picoseconds. + Weight::from_parts(3_518_000, 3487) .saturating_add(T::DbWeight::get().reads(1_u64)) } fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 291_000 picoseconds. - Weight::from_parts(388_000, 0) + // Minimum execution time: 259_000 picoseconds. + Weight::from_parts(346_000, 0) } /// The range of component `n` is `[0, 1048572]`. fn seal_copy_to_contract(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 503_000 picoseconds. - Weight::from_parts(558_000, 0) + // Minimum execution time: 481_000 picoseconds. + Weight::from_parts(530_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(239, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(240, 0).saturating_mul(n.into())) } fn seal_call_data_load() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 306_000 picoseconds. - Weight::from_parts(399_000, 0) + // Minimum execution time: 257_000 picoseconds. + Weight::from_parts(341_000, 0) } /// The range of component `n` is `[0, 1048576]`. fn seal_call_data_copy(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 331_000 picoseconds. - Weight::from_parts(383_000, 0) + // Minimum execution time: 277_000 picoseconds. + Weight::from_parts(334_000, 0) // Standard Error: 0 .saturating_add(Weight::from_parts(150, 0).saturating_mul(n.into())) } @@ -901,22 +901,22 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 340_000 picoseconds. - Weight::from_parts(576_244, 0) + // Minimum execution time: 290_000 picoseconds. + Weight::from_parts(500_344, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(235, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(237, 0).saturating_mul(n.into())) } /// Storage: `Revive::OriginalAccount` (r:2 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) /// The range of component `r` is `[0, 1]`. fn seal_terminate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `348` - // Estimated: `6288` - // Minimum execution time: 11_753_000 picoseconds. - Weight::from_parts(12_850_878, 6288) - // Standard Error: 11_382 - .saturating_add(Weight::from_parts(60_445, 0).saturating_mul(r.into())) + // Measured: `332` + // Estimated: `6272` + // Minimum execution time: 11_707_000 picoseconds. + Weight::from_parts(12_712_227, 6272) + // Standard Error: 10_422 + .saturating_add(Weight::from_parts(36_027, 0).saturating_mul(r.into())) .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `Balances::Holds` (r:2 w:2) @@ -937,10 +937,10 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) fn seal_terminate_logic() -> Weight { // Proof Size summary in bytes: - // Measured: `789` - // Estimated: `6729` - // Minimum execution time: 214_858_000 picoseconds. - Weight::from_parts(231_492_000, 6729) + // Measured: `773` + // Estimated: `6713` + // Minimum execution time: 211_802_000 picoseconds. + Weight::from_parts(220_522_000, 6713) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(9_u64)) } @@ -950,10 +950,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_129_000 picoseconds. - Weight::from_parts(5_426_000, 0) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_421, 0).saturating_mul(n.into())) + // Minimum execution time: 5_178_000 picoseconds. + Weight::from_parts(5_415_000, 0) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_317, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -961,8 +961,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `648` // Estimated: `648` - // Minimum execution time: 8_711_000 picoseconds. - Weight::from_parts(9_515_000, 648) + // Minimum execution time: 8_844_000 picoseconds. + Weight::from_parts(9_678_000, 648) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -971,8 +971,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `10658` // Estimated: `10658` - // Minimum execution time: 38_638_000 picoseconds. - Weight::from_parts(40_350_000, 10658) + // Minimum execution time: 38_874_000 picoseconds. + Weight::from_parts(40_600_000, 10658) .saturating_add(T::DbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -981,8 +981,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `648` // Estimated: `648` - // Minimum execution time: 9_821_000 picoseconds. - Weight::from_parts(10_671_000, 648) + // Minimum execution time: 9_897_000 picoseconds. + Weight::from_parts(10_866_000, 648) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -992,8 +992,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `10658` // Estimated: `10658` - // Minimum execution time: 40_396_000 picoseconds. - Weight::from_parts(42_183_000, 10658) + // Minimum execution time: 40_501_000 picoseconds. + Weight::from_parts(42_311_000, 10658) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -1004,10 +1004,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 879_806_000 picoseconds. - Weight::from_parts(938_663_968, 0) - // Standard Error: 1_256 - .saturating_add(Weight::from_parts(1_067_429, 0).saturating_mul(n.into())) + // Minimum execution time: 859_695_000 picoseconds. + Weight::from_parts(907_196_094, 0) + // Standard Error: 2_707 + .saturating_add(Weight::from_parts(1_089_439, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().writes(2048_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -1017,10 +1017,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 748_000 picoseconds. - Weight::from_parts(12_316_473, 0) - // Standard Error: 758 - .saturating_add(Weight::from_parts(890_662, 0).saturating_mul(n.into())) + // Minimum execution time: 726_000 picoseconds. + Weight::from_parts(19_170_522, 0) + // Standard Error: 1_136 + .saturating_add(Weight::from_parts(877_369, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1030,12 +1030,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + o * (1 ±0)` // Estimated: `247 + o * (1 ±0)` - // Minimum execution time: 9_900_000 picoseconds. - Weight::from_parts(10_662_472, 247) - // Standard Error: 15 - .saturating_add(Weight::from_parts(451, 0).saturating_mul(n.into())) - // Standard Error: 15 - .saturating_add(Weight::from_parts(528, 0).saturating_mul(o.into())) + // Minimum execution time: 9_744_000 picoseconds. + Weight::from_parts(10_716_480, 247) + // Standard Error: 17 + .saturating_add(Weight::from_parts(500, 0).saturating_mul(n.into())) + // Standard Error: 17 + .saturating_add(Weight::from_parts(632, 0).saturating_mul(o.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) @@ -1048,12 +1048,12 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_411_000 picoseconds. - Weight::from_parts(4_905_650, 0) - // Standard Error: 7 - .saturating_add(Weight::from_parts(398, 0).saturating_mul(n.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(94, 0).saturating_mul(o.into())) + // Minimum execution time: 4_370_000 picoseconds. + Weight::from_parts(4_886_632, 0) + // Standard Error: 9 + .saturating_add(Weight::from_parts(400, 0).saturating_mul(n.into())) + // Standard Error: 9 + .saturating_add(Weight::from_parts(59, 0).saturating_mul(o.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1062,10 +1062,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 10_942_000 picoseconds. - Weight::from_parts(12_422_926, 247) - // Standard Error: 17 - .saturating_add(Weight::from_parts(674, 0).saturating_mul(n.into())) + // Minimum execution time: 11_447_000 picoseconds. + Weight::from_parts(12_648_167, 247) + // Standard Error: 18 + .saturating_add(Weight::from_parts(748, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1077,10 +1077,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_897_000 picoseconds. - Weight::from_parts(6_628_641, 0) + // Minimum execution time: 5_939_000 picoseconds. + Weight::from_parts(6_666_812, 0) // Standard Error: 10 - .saturating_add(Weight::from_parts(188, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(154, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1089,10 +1089,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_692_000 picoseconds. - Weight::from_parts(10_072_874, 247) + // Minimum execution time: 9_023_000 picoseconds. + Weight::from_parts(10_208_007, 247) // Standard Error: 15 - .saturating_add(Weight::from_parts(1_260, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_375, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1103,10 +1103,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_413_000 picoseconds. - Weight::from_parts(3_875_397, 0) + // Minimum execution time: 3_462_000 picoseconds. + Weight::from_parts(3_905_870, 0) // Standard Error: 6 - .saturating_add(Weight::from_parts(659, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(655, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1115,10 +1115,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 10_181_000 picoseconds. - Weight::from_parts(11_375_558, 247) - // Standard Error: 15 - .saturating_add(Weight::from_parts(679, 0).saturating_mul(n.into())) + // Minimum execution time: 10_188_000 picoseconds. + Weight::from_parts(11_468_250, 247) + // Standard Error: 16 + .saturating_add(Weight::from_parts(756, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1129,10 +1129,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_052_000 picoseconds. - Weight::from_parts(5_595_259, 0) - // Standard Error: 8 - .saturating_add(Weight::from_parts(53, 0).saturating_mul(n.into())) + // Minimum execution time: 4_958_000 picoseconds. + Weight::from_parts(5_570_149, 0) + // Standard Error: 7 + .saturating_add(Weight::from_parts(119, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -1141,10 +1141,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 11_488_000 picoseconds. - Weight::from_parts(13_213_620, 247) + // Minimum execution time: 11_454_000 picoseconds. + Weight::from_parts(13_207_272, 247) // Standard Error: 22 - .saturating_add(Weight::from_parts(1_350, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_473, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -1156,80 +1156,80 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_054_000 picoseconds. - Weight::from_parts(7_026_838, 0) + // Minimum execution time: 5_911_000 picoseconds. + Weight::from_parts(6_933_854, 0) // Standard Error: 12 - .saturating_add(Weight::from_parts(841, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(790, 0).saturating_mul(n.into())) } fn access_list_touch_cold_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_683_000 picoseconds. - Weight::from_parts(4_294_000, 0) + // Minimum execution time: 4_251_000 picoseconds. + Weight::from_parts(4_382_000, 0) } fn access_list_touch_hot_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_051_000 picoseconds. - Weight::from_parts(1_193_000, 0) + // Minimum execution time: 1_035_000 picoseconds. + Weight::from_parts(1_176_000, 0) } fn access_list_touch_cold_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` // Minimum execution time: 458_000 picoseconds. - Weight::from_parts(584_000, 0) + Weight::from_parts(570_000, 0) } fn access_list_touch_hot_single_element() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 593_000 picoseconds. - Weight::from_parts(697_000, 0) + // Minimum execution time: 565_000 picoseconds. + Weight::from_parts(673_000, 0) } fn access_list_rollback_amortization() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_903_000 picoseconds. - Weight::from_parts(4_679_000, 0) + // Minimum execution time: 4_423_000 picoseconds. + Weight::from_parts(4_850_000, 0) } fn set_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_594_000 picoseconds. - Weight::from_parts(1_819_000, 0) + // Minimum execution time: 1_553_000 picoseconds. + Weight::from_parts(1_788_000, 0) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_896_000 picoseconds. - Weight::from_parts(2_170_000, 0) + // Minimum execution time: 1_903_000 picoseconds. + Weight::from_parts(2_163_000, 0) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_539_000 picoseconds. - Weight::from_parts(1_724_000, 0) + // Minimum execution time: 1_495_000 picoseconds. + Weight::from_parts(1_700_000, 0) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_678_000 picoseconds. + // Minimum execution time: 1_634_000 picoseconds. Weight::from_parts(1_889_000, 0) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_127_000 picoseconds. - Weight::from_parts(1_327_000, 0) + // Minimum execution time: 1_229_000 picoseconds. + Weight::from_parts(1_429_000, 0) } /// The range of component `n` is `[0, 416]`. /// The range of component `o` is `[0, 416]`. @@ -1237,59 +1237,57 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_432_000 picoseconds. - Weight::from_parts(2_825_609, 0) - // Standard Error: 5 - .saturating_add(Weight::from_parts(279, 0).saturating_mul(n.into())) - // Standard Error: 5 - .saturating_add(Weight::from_parts(374, 0).saturating_mul(o.into())) + // Minimum execution time: 2_391_000 picoseconds. + Weight::from_parts(2_685_206, 0) + // Standard Error: 4 + .saturating_add(Weight::from_parts(306, 0).saturating_mul(n.into())) + // Standard Error: 4 + .saturating_add(Weight::from_parts(383, 0).saturating_mul(o.into())) } /// The range of component `n` is `[0, 416]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_811_000 picoseconds. - Weight::from_parts(4_462_331, 0) + // Minimum execution time: 3_892_000 picoseconds. + Weight::from_parts(4_482_704, 0) // Standard Error: 7 - .saturating_add(Weight::from_parts(345, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(400, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_019_000 picoseconds. - Weight::from_parts(2_428_719, 0) + // Minimum execution time: 1_952_000 picoseconds. + Weight::from_parts(2_347_346, 0) // Standard Error: 3 - .saturating_add(Weight::from_parts(375, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(354, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_375_000 picoseconds. - Weight::from_parts(3_962_070, 0) + // Minimum execution time: 3_469_000 picoseconds. + Weight::from_parts(3_940_543, 0) // Standard Error: 6 - .saturating_add(Weight::from_parts(143, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(215, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. - fn seal_take_transient_storage(_n: u32, ) -> Weight { + fn seal_take_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_269_000 picoseconds. - Weight::from_parts(4_837_696, 0) + // Minimum execution time: 4_305_000 picoseconds. + Weight::from_parts(4_846_729, 0) + // Standard Error: 6 + .saturating_add(Weight::from_parts(9, 0).saturating_mul(n.into())) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) /// Storage: `Revive::AccountInfoOf` (r:1 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) - /// Storage: `Revive::CodeInfoOf` (r:1 w:0) - /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) - /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `t` is `[0, 1]`. @@ -1297,20 +1295,27 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 1048576]`. fn seal_call(t: u32, d: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1236` - // Estimated: `4701` - // Minimum execution time: 89_979_000 picoseconds. - Weight::from_parts(70_070_774, 4701) - // Standard Error: 74_621 - .saturating_add(Weight::from_parts(19_752_547, 0).saturating_mul(t.into())) - // Standard Error: 74_621 - .saturating_add(Weight::from_parts(25_306_220, 0).saturating_mul(d.into())) + // Measured: `572` + // Estimated: `4037` + // Minimum execution time: 83_690_000 picoseconds. + Weight::from_parts(64_824_903, 4037) + // Standard Error: 59_255 + .saturating_add(Weight::from_parts(19_587_216, 0).saturating_mul(t.into())) + // Standard Error: 59_255 + .saturating_add(Weight::from_parts(24_915_648, 0).saturating_mul(d.into())) // Standard Error: 0 .saturating_add(Weight::from_parts(3, 0).saturating_mul(i.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(t.into()))) } + fn seal_call_hot() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 23_202_000 picoseconds. + Weight::from_parts(25_313_000, 0) + } /// Storage: `Revive::AccountInfoOf` (r:1 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) @@ -1321,48 +1326,44 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0 + d * (174 ±0)` // Estimated: `1819 + d * (1820 ±0)` - // Minimum execution time: 19_472_000 picoseconds. - Weight::from_parts(9_662_203, 1819) - // Standard Error: 13_916 - .saturating_add(Weight::from_parts(11_153_483, 0).saturating_mul(d.into())) + // Minimum execution time: 19_247_000 picoseconds. + Weight::from_parts(9_327_844, 1819) + // Standard Error: 14_465 + .saturating_add(Weight::from_parts(11_260_656, 0).saturating_mul(d.into())) // Standard Error: 0 - .saturating_add(Weight::from_parts(397, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(401, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(d.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(d.into()))) .saturating_add(Weight::from_parts(0, 1820).saturating_mul(d.into())) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) + fn seal_delegate_call() -> Weight { + // Proof Size summary in bytes: + // Measured: `124` + // Estimated: `3589` + // Minimum execution time: 23_991_000 picoseconds. + Weight::from_parts(26_163_000, 3589) + .saturating_add(T::DbWeight::get().reads(1_u64)) + } + fn seal_delegate_call_hot() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 21_831_000 picoseconds. + Weight::from_parts(23_947_000, 0) + } /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn seal_delegate_call() -> Weight { - // Proof Size summary in bytes: - // Measured: `749` - // Estimated: `4214` - // Minimum execution time: 28_151_000 picoseconds. - Weight::from_parts(30_587_000, 4214) - .saturating_add(T::DbWeight::get().reads(3_u64)) - } - // Placeholder until `/cmd bench` runs the `code_load` benchmark: proof-only - // over-approximation reusing seal_delegate_call's {AccountInfoOf, CodeInfoOf, - // PristineCode} proof, which is a superset of the {CodeInfoOf, PristineCode} read. fn code_load() -> Weight { - Weight::from_parts(0, Self::seal_delegate_call().proof_size()) - } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot call re-reads state already in the proof). - fn seal_call_hot() -> Weight { - Weight::from_parts(70_070_774, 0) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot call re-reads state already in the proof). - fn seal_delegate_call_hot() -> Weight { - Weight::from_parts(30_587_000, 0) - .saturating_add(T::DbWeight::get().reads(3_u64)) + // Proof Size summary in bytes: + // Measured: `883` + // Estimated: `4348` + // Minimum execution time: 12_492_000 picoseconds. + Weight::from_parts(13_486_000, 4348) + .saturating_add(T::DbWeight::get().reads(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) @@ -1379,18 +1380,20 @@ impl WeightInfo for SubstrateWeight { /// The range of component `i` is `[0, 131072]`. fn seal_instantiate(t: u32, d: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `699` - // Estimated: `4192` - // Minimum execution time: 134_215_000 picoseconds. - Weight::from_parts(83_528_095, 4192) - // Standard Error: 438_417 - .saturating_add(Weight::from_parts(21_862_241, 0).saturating_mul(t.into())) - // Standard Error: 438_417 - .saturating_add(Weight::from_parts(34_393_022, 0).saturating_mul(d.into())) - // Standard Error: 5 - .saturating_add(Weight::from_parts(4_144, 0).saturating_mul(i.into())) + // Measured: `647` + // Estimated: `4088 + d * (25 ±5) + t * (25 ±5)` + // Minimum execution time: 134_639_000 picoseconds. + Weight::from_parts(85_480_716, 4088) + // Standard Error: 396_463 + .saturating_add(Weight::from_parts(24_452_682, 0).saturating_mul(t.into())) + // Standard Error: 396_463 + .saturating_add(Weight::from_parts(31_069_410, 0).saturating_mul(d.into())) + // Standard Error: 4 + .saturating_add(Weight::from_parts(4_074, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(Weight::from_parts(0, 25).saturating_mul(d.into())) + .saturating_add(Weight::from_parts(0, 25).saturating_mul(t.into())) } /// Storage: `Revive::AccountInfoOf` (r:1 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -1411,14 +1414,14 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `302` // Estimated: `6210 + d * (22 ±3) + t * (22 ±3)` - // Minimum execution time: 348_954_000 picoseconds. - Weight::from_parts(225_616_923, 6210) - // Standard Error: 519_988 - .saturating_add(Weight::from_parts(17_118_694, 0).saturating_mul(t.into())) - // Standard Error: 519_988 - .saturating_add(Weight::from_parts(23_827_011, 0).saturating_mul(d.into())) - // Standard Error: 20 - .saturating_add(Weight::from_parts(8_065, 0).saturating_mul(i.into())) + // Minimum execution time: 341_911_000 picoseconds. + Weight::from_parts(221_200_992, 6210) + // Standard Error: 581_753 + .saturating_add(Weight::from_parts(25_664_453, 0).saturating_mul(t.into())) + // Standard Error: 581_753 + .saturating_add(Weight::from_parts(28_107_850, 0).saturating_mul(d.into())) + // Standard Error: 23 + .saturating_add(Weight::from_parts(7_723, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(6_u64)) .saturating_add(Weight::from_parts(0, 22).saturating_mul(d.into())) @@ -1429,18 +1432,18 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_462_000 picoseconds. - Weight::from_parts(17_265_292, 0) + // Minimum execution time: 1_440_000 picoseconds. + Weight::from_parts(11_966_571, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_310, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_301, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn identity(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 925_000 picoseconds. - Weight::from_parts(844_673, 0) + // Minimum execution time: 933_000 picoseconds. + Weight::from_parts(726_785, 0) // Standard Error: 0 .saturating_add(Weight::from_parts(149, 0).saturating_mul(n.into())) } @@ -1449,135 +1452,135 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_487_000 picoseconds. - Weight::from_parts(5_175_760, 0) + // Minimum execution time: 1_465_000 picoseconds. + Weight::from_parts(5_607_347, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(3_772, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_777, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_225_000 picoseconds. - Weight::from_parts(16_636_672, 0) + // Minimum execution time: 1_142_000 picoseconds. + Weight::from_parts(13_605_194, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(3_585, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_596, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_016_000 picoseconds. - Weight::from_parts(18_049_453, 0) + // Minimum execution time: 1_960_000 picoseconds. + Weight::from_parts(13_496_010, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_451, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_454, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_093_000 picoseconds. - Weight::from_parts(18_587_920, 0) + // Minimum execution time: 1_975_000 picoseconds. + Weight::from_parts(13_788_816, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_446, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_452, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048321]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 45_366_000 picoseconds. - Weight::from_parts(87_519_654, 0) + // Minimum execution time: 45_734_000 picoseconds. + Weight::from_parts(92_269_416, 0) // Standard Error: 3 - .saturating_add(Weight::from_parts(4_966, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(4_861, 0).saturating_mul(n.into())) } fn ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 46_127_000 picoseconds. - Weight::from_parts(47_562_000, 0) + // Minimum execution time: 46_483_000 picoseconds. + Weight::from_parts(47_728_000, 0) } fn p256_verify() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_786_952_000 picoseconds. - Weight::from_parts(1_802_203_000, 0) + // Minimum execution time: 1_782_736_000 picoseconds. + Weight::from_parts(1_801_110_000, 0) } fn bn128_add() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 14_768_000 picoseconds. - Weight::from_parts(16_550_000, 0) + // Minimum execution time: 14_745_000 picoseconds. + Weight::from_parts(16_419_000, 0) } fn bn128_mul() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 970_342_000 picoseconds. - Weight::from_parts(985_972_000, 0) + // Minimum execution time: 976_251_000 picoseconds. + Weight::from_parts(991_172_000, 0) } /// The range of component `n` is `[0, 20]`. fn bn128_pairing(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_038_000 picoseconds. - Weight::from_parts(4_872_284_272, 0) - // Standard Error: 10_450_049 - .saturating_add(Weight::from_parts(5_922_447_843, 0).saturating_mul(n.into())) + // Minimum execution time: 980_000 picoseconds. + Weight::from_parts(4_980_929_261, 0) + // Standard Error: 10_760_224 + .saturating_add(Weight::from_parts(5_933_016_201, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1200]`. fn blake2f(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_206_000 picoseconds. - Weight::from_parts(1_549_126, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(29_703, 0).saturating_mul(n.into())) + // Minimum execution time: 1_130_000 picoseconds. + Weight::from_parts(1_489_126, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(30_587, 0).saturating_mul(n.into())) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_894_000 picoseconds. - Weight::from_parts(13_172_000, 0) + // Minimum execution time: 12_936_000 picoseconds. + Weight::from_parts(13_228_000, 0) } /// The range of component `r` is `[0, 10000]`. fn evm_opcode(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 689_000 picoseconds. - Weight::from_parts(923_228, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(7_743, 0).saturating_mul(r.into())) + // Minimum execution time: 643_000 picoseconds. + Weight::from_parts(902_066, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(7_690, 0).saturating_mul(r.into())) } /// The range of component `r` is `[0, 10000]`. fn instr(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 14_123_000 picoseconds. - Weight::from_parts(82_116_844, 0) - // Standard Error: 624 - .saturating_add(Weight::from_parts(86_822, 0).saturating_mul(r.into())) + // Minimum execution time: 12_953_000 picoseconds. + Weight::from_parts(38_184_235, 0) + // Standard Error: 857 + .saturating_add(Weight::from_parts(83_522, 0).saturating_mul(r.into())) } /// The range of component `r` is `[0, 10000]`. fn instr_empty_loop(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_519_000 picoseconds. - Weight::from_parts(3_433_593, 0) + // Minimum execution time: 3_404_000 picoseconds. + Weight::from_parts(3_339_267, 0) // Standard Error: 7 - .saturating_add(Weight::from_parts(38_940, 0).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(38_879, 0).saturating_mul(r.into())) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -1588,12 +1591,12 @@ impl WeightInfo for SubstrateWeight { /// The range of component `n` is `[1000, 102400]`. fn extcodecopy(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `368 + n * (1 ±0)` - // Estimated: `3831 + n * (1 ±0)` - // Minimum execution time: 18_574_000 picoseconds. - Weight::from_parts(14_934_289, 3831) + // Measured: `369 + n * (1 ±0)` + // Estimated: `3832 + n * (1 ±0)` + // Minimum execution time: 17_962_000 picoseconds. + Weight::from_parts(14_565_992, 3832) // Standard Error: 5 - .saturating_add(Weight::from_parts(1_219, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_168, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -1605,8 +1608,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `382` // Estimated: `6322` - // Minimum execution time: 11_355_000 picoseconds. - Weight::from_parts(12_308_000, 6322) + // Minimum execution time: 11_492_000 picoseconds. + Weight::from_parts(12_362_000, 6322) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -1620,8 +1623,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `505` // Estimated: `7010` - // Minimum execution time: 63_135_000 picoseconds. - Weight::from_parts(67_045_000, 7010) + // Minimum execution time: 62_402_000 picoseconds. + Weight::from_parts(65_929_000, 7010) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -1635,8 +1638,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `629` // Estimated: `6196` - // Minimum execution time: 38_935_000 picoseconds. - Weight::from_parts(41_585_000, 6196) + // Minimum execution time: 38_273_000 picoseconds. + Weight::from_parts(41_047_000, 6196) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -1648,8 +1651,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6134` - // Minimum execution time: 16_267_000 picoseconds. - Weight::from_parts(17_667_000, 6134) + // Minimum execution time: 16_108_000 picoseconds. + Weight::from_parts(17_373_000, 6134) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -1663,8 +1666,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `909` // Estimated: `6434` - // Minimum execution time: 22_918_000 picoseconds. - Weight::from_parts(24_540_000, 6434) + // Minimum execution time: 22_658_000 picoseconds. + Weight::from_parts(24_312_000, 6434) .saturating_add(T::DbWeight::get().reads(4_u64)) } /// Storage: `Revive::DeletionQueue` (r:2 w:1) @@ -1673,8 +1676,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `313` // Estimated: `6288` - // Minimum execution time: 9_770_000 picoseconds. - Weight::from_parts(10_686_000, 6288) + // Minimum execution time: 9_481_000 picoseconds. + Weight::from_parts(10_484_000, 6288) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -1695,10 +1698,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3012 + n * (97 ±0)` // Estimated: `6303 + n * (104 ±1)` - // Minimum execution time: 27_570_000 picoseconds. - Weight::from_parts(55_661_437, 6303) - // Standard Error: 4_837 - .saturating_add(Weight::from_parts(546_107, 0).saturating_mul(n.into())) + // Minimum execution time: 27_048_000 picoseconds. + Weight::from_parts(53_620_386, 6303) + // Standard Error: 5_729 + .saturating_add(Weight::from_parts(533_429, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) .saturating_add(Weight::from_parts(0, 104).saturating_mul(n.into())) @@ -1720,10 +1723,10 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `3577 + d * (3 ±0)` // Estimated: `7036 + d * (3 ±0)` - // Minimum execution time: 58_934_000 picoseconds. - Weight::from_parts(61_521_292, 7036) - // Standard Error: 88 - .saturating_add(Weight::from_parts(11_606, 0).saturating_mul(d.into())) + // Minimum execution time: 58_325_000 picoseconds. + Weight::from_parts(60_895_382, 7036) + // Standard Error: 85 + .saturating_add(Weight::from_parts(11_402, 0).saturating_mul(d.into())) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(d.into())) @@ -1743,12 +1746,14 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Revive::ReceiptInfoData` (r:0 w:1) /// Proof: `Revive::ReceiptInfoData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `e` is `[0, 100]`. - fn on_finalize_per_event(_e: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1546` - // Estimated: `5011` - // Minimum execution time: 43_178_000 picoseconds. - Weight::from_parts(45_603_687, 5011) + fn on_finalize_per_event(e: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1547` + // Estimated: `5012` + // Minimum execution time: 43_382_000 picoseconds. + Weight::from_parts(45_448_933, 5012) + // Standard Error: 197 + .saturating_add(Weight::from_parts(417, 0).saturating_mul(e.into())) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -1767,14 +1772,12 @@ impl WeightInfo for SubstrateWeight { /// Storage: `Revive::ReceiptInfoData` (r:0 w:1) /// Proof: `Revive::ReceiptInfoData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `d` is `[0, 16384]`. - fn on_finalize_per_event_data(d: u32, ) -> Weight { + fn on_finalize_per_event_data(_d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1546` - // Estimated: `5011` - // Minimum execution time: 43_363_000 picoseconds. - Weight::from_parts(45_583_724, 5011) - // Standard Error: 1 - .saturating_add(Weight::from_parts(13, 0).saturating_mul(d.into())) + // Measured: `1547` + // Estimated: `5012` + // Minimum execution time: 43_346_000 picoseconds. + Weight::from_parts(45_781_402, 5012) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -1788,8 +1791,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `213` // Estimated: `1698` - // Minimum execution time: 3_078_000 picoseconds. - Weight::from_parts(3_415_000, 1698) + // Minimum execution time: 2_962_000 picoseconds. + Weight::from_parts(3_287_000, 1698) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Revive::DeletionQueueCounter` (r:1 w:1) @@ -1800,8 +1803,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `390` // Estimated: `3855` - // Minimum execution time: 17_557_000 picoseconds. - Weight::from_parts(18_994_000, 3855) + // Minimum execution time: 17_627_000 picoseconds. + Weight::from_parts(19_156_000, 3855) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1812,10 +1815,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `524 + k * (69 ±0)` // Estimated: `514 + k * (70 ±0)` - // Minimum execution time: 18_131_000 picoseconds. - Weight::from_parts(18_672_000, 514) - // Standard Error: 881 - .saturating_add(Weight::from_parts(1_200_222, 0).saturating_mul(k.into())) + // Minimum execution time: 18_343_000 picoseconds. + Weight::from_parts(4_012_746, 514) + // Standard Error: 932 + .saturating_add(Weight::from_parts(1_228_883, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1829,10 +1832,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `469 + k * (52 ±0)` // Estimated: `479 + k * (53 ±0)` - // Minimum execution time: 18_129_000 picoseconds. - Weight::from_parts(18_629_000, 479) - // Standard Error: 967 - .saturating_add(Weight::from_parts(1_207_151, 0).saturating_mul(k.into())) + // Minimum execution time: 18_434_000 picoseconds. + Weight::from_parts(18_767_000, 479) + // Standard Error: 841 + .saturating_add(Weight::from_parts(1_214_573, 0).saturating_mul(k.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(RocksDbWeight::get().writes(2_u64)) @@ -1856,14 +1859,24 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1267 + c * (1 ±0)` // Estimated: `7204 + c * (1 ±0)` - // Minimum execution time: 100_740_000 picoseconds. - Weight::from_parts(148_471_832, 7204) - // Standard Error: 14 - .saturating_add(Weight::from_parts(1_601, 0).saturating_mul(c.into())) + // Minimum execution time: 100_825_000 picoseconds. + Weight::from_parts(151_084_583, 7204) + // Standard Error: 13 + .saturating_add(Weight::from_parts(1_519, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } + /// The range of component `c` is `[0, 102400]`. + fn call_with_pvm_code_per_byte_hot(c: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 24_520_000 picoseconds. + Weight::from_parts(71_168_932, 0) + // Standard Error: 11 + .saturating_add(Weight::from_parts(1_199, 0).saturating_mul(c.into())) + } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `Revive::OriginalAccount` (r:2 w:0) @@ -1881,29 +1894,23 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1208 + c * (1 ±0)` // Estimated: `7145 + c * (1 ±0)` - // Minimum execution time: 94_505_000 picoseconds. - Weight::from_parts(99_411_753, 7145) - // Standard Error: 7 - .saturating_add(Weight::from_parts(1_741, 0).saturating_mul(c.into())) + // Minimum execution time: 95_703_000 picoseconds. + Weight::from_parts(101_330_448, 7145) + // Standard Error: 8 + .saturating_add(Weight::from_parts(1_593, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(c.into())) } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot load re-reads a blob already in the proof). - fn call_with_pvm_code_per_byte_hot(c: u32, ) -> Weight { - Weight::from_parts(148_471_832, 0) - .saturating_add(Weight::from_parts(1_601, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot load re-reads a blob already in the proof). + /// The range of component `c` is `[1, 10240]`. fn call_with_evm_code_per_byte_hot(c: u32, ) -> Weight { - Weight::from_parts(99_411_753, 0) - .saturating_add(Weight::from_parts(1_741, 0).saturating_mul(c.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 20_583_000 picoseconds. + Weight::from_parts(22_195_758, 0) + // Standard Error: 6 + .saturating_add(Weight::from_parts(1_610, 0).saturating_mul(c.into())) } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -1918,14 +1925,12 @@ impl WeightInfo for () { /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `b` is `[0, 1]`. - fn basic_block_compilation(b: u32, ) -> Weight { + fn basic_block_compilation(_b: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `4609` // Estimated: `10549` - // Minimum execution time: 150_640_000 picoseconds. - Weight::from_parts(158_446_397, 10549) - // Standard Error: 256_147 - .saturating_add(Weight::from_parts(108_702, 0).saturating_mul(b.into())) + // Minimum execution time: 152_556_000 picoseconds. + Weight::from_parts(159_383_691, 10549) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -1951,12 +1956,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `880` // Estimated: `6826` - // Minimum execution time: 785_146_000 picoseconds. - Weight::from_parts(96_655_352, 6826) - // Standard Error: 35 - .saturating_add(Weight::from_parts(20_829, 0).saturating_mul(c.into())) + // Minimum execution time: 783_983_000 picoseconds. + Weight::from_parts(102_741_454, 6826) + // Standard Error: 34 + .saturating_add(Weight::from_parts(19_934, 0).saturating_mul(c.into())) // Standard Error: 27 - .saturating_add(Weight::from_parts(4_955, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(4_947, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -1983,18 +1988,16 @@ impl WeightInfo for () { /// The range of component `c` is `[0, 102400]`. /// The range of component `i` is `[0, 131072]`. /// The range of component `d` is `[0, 1]`. - fn eth_instantiate_with_code(c: u32, i: u32, d: u32, ) -> Weight { + fn eth_instantiate_with_code(c: u32, i: u32, _d: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `981` // Estimated: `6921` - // Minimum execution time: 420_604_000 picoseconds. - Weight::from_parts(287_137_358, 6921) - // Standard Error: 44 - .saturating_add(Weight::from_parts(16_341, 0).saturating_mul(c.into())) - // Standard Error: 34 - .saturating_add(Weight::from_parts(912, 0).saturating_mul(i.into())) - // Standard Error: 2_886_713 - .saturating_add(Weight::from_parts(10_317_725, 0).saturating_mul(d.into())) + // Minimum execution time: 421_825_000 picoseconds. + Weight::from_parts(357_225_914, 6921) + // Standard Error: 58 + .saturating_add(Weight::from_parts(15_912, 0).saturating_mul(c.into())) + // Standard Error: 45 + .saturating_add(Weight::from_parts(328, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(11_u64)) .saturating_add(RocksDbWeight::get().writes(10_u64)) } @@ -2002,8 +2005,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_845_000 picoseconds. - Weight::from_parts(3_155_000, 0) + // Minimum execution time: 2_953_000 picoseconds. + Weight::from_parts(3_322_000, 0) } /// Storage: `Revive::AccountInfoOf` (r:2 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -2025,11 +2028,11 @@ impl WeightInfo for () { fn instantiate(i: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `1510` - // Estimated: `7447` - // Minimum execution time: 176_916_000 picoseconds. - Weight::from_parts(184_330_194, 7447) - // Standard Error: 5 - .saturating_add(Weight::from_parts(4_389, 0).saturating_mul(i.into())) + // Estimated: `7443` + // Minimum execution time: 176_953_000 picoseconds. + Weight::from_parts(182_761_060, 7443) + // Standard Error: 4 + .saturating_add(Weight::from_parts(4_336, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -2047,10 +2050,10 @@ impl WeightInfo for () { /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) fn call() -> Weight { // Proof Size summary in bytes: - // Measured: `1698` - // Estimated: `7638` - // Minimum execution time: 98_637_000 picoseconds. - Weight::from_parts(103_497_000, 7638) + // Measured: `1746` + // Estimated: `7686` + // Minimum execution time: 100_324_000 picoseconds. + Weight::from_parts(105_719_000, 7686) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2073,12 +2076,12 @@ impl WeightInfo for () { /// The range of component `d` is `[0, 1]`. fn eth_call(d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1698` - // Estimated: `7638` - // Minimum execution time: 181_834_000 picoseconds. - Weight::from_parts(190_697_274, 7638) - // Standard Error: 220_888 - .saturating_add(Weight::from_parts(3_908_244, 0).saturating_mul(d.into())) + // Measured: `1746` + // Estimated: `7686` + // Minimum execution time: 183_381_000 picoseconds. + Weight::from_parts(193_758_233, 7686) + // Standard Error: 245_086 + .saturating_add(Weight::from_parts(3_765_029, 0).saturating_mul(d.into())) .saturating_add(RocksDbWeight::get().reads(9_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -2097,10 +2100,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `381` // Estimated: `3846` - // Minimum execution time: 31_364_000 picoseconds. - Weight::from_parts(27_032_161, 3846) - // Standard Error: 4 - .saturating_add(Weight::from_parts(6_475, 0).saturating_mul(c.into())) + // Minimum execution time: 31_508_000 picoseconds. + Weight::from_parts(27_466_638, 3846) + // Standard Error: 3 + .saturating_add(Weight::from_parts(6_387, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2117,10 +2120,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `291` // Estimated: `3756` - // Minimum execution time: 61_026_000 picoseconds. - Weight::from_parts(47_131_680, 3756) - // Standard Error: 21 - .saturating_add(Weight::from_parts(14_816, 0).saturating_mul(c.into())) + // Minimum execution time: 60_597_000 picoseconds. + Weight::from_parts(53_153_595, 3756) + // Standard Error: 22 + .saturating_add(Weight::from_parts(15_011, 0).saturating_mul(c.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -2134,8 +2137,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `423` // Estimated: `3888` - // Minimum execution time: 51_061_000 picoseconds. - Weight::from_parts(54_352_000, 3888) + // Minimum execution time: 51_171_000 picoseconds. + Weight::from_parts(54_079_000, 3888) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -2153,8 +2156,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `867` // Estimated: `6807` - // Minimum execution time: 67_577_000 picoseconds. - Weight::from_parts(71_341_000, 6807) + // Minimum execution time: 66_569_000 picoseconds. + Weight::from_parts(70_668_000, 6807) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) } @@ -2168,8 +2171,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `623` // Estimated: `4088` - // Minimum execution time: 59_787_000 picoseconds. - Weight::from_parts(63_418_000, 4088) + // Minimum execution time: 59_319_000 picoseconds. + Weight::from_parts(62_813_000, 4088) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2181,8 +2184,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `93` // Estimated: `3558` - // Minimum execution time: 39_659_000 picoseconds. - Weight::from_parts(42_554_000, 3558) + // Minimum execution time: 39_038_000 picoseconds. + Weight::from_parts(41_550_000, 3558) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -2199,10 +2202,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `563 + a * (209 ±0)` // Estimated: `4008 + a * (2684 ±0)` - // Minimum execution time: 10_918_000 picoseconds. - Weight::from_parts(11_238_000, 4008) - // Standard Error: 73_798 - .saturating_add(Weight::from_parts(49_660_410, 0).saturating_mul(a.into())) + // Minimum execution time: 10_858_000 picoseconds. + Weight::from_parts(10_969_000, 4008) + // Standard Error: 62_375 + .saturating_add(Weight::from_parts(48_487_766, 0).saturating_mul(a.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(a.into()))) .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(a.into()))) @@ -2218,8 +2221,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `381` // Estimated: `3846` - // Minimum execution time: 18_295_000 picoseconds. - Weight::from_parts(19_704_000, 3846) + // Minimum execution time: 18_397_000 picoseconds. + Weight::from_parts(19_831_000, 3846) .saturating_add(RocksDbWeight::get().reads(3_u64)) } /// The range of component `r` is `[0, 1600]`. @@ -2227,24 +2230,24 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 9_002_000 picoseconds. - Weight::from_parts(10_808_148, 0) - // Standard Error: 46 - .saturating_add(Weight::from_parts(141_532, 0).saturating_mul(r.into())) + // Minimum execution time: 9_006_000 picoseconds. + Weight::from_parts(11_074_481, 0) + // Standard Error: 59 + .saturating_add(Weight::from_parts(138_548, 0).saturating_mul(r.into())) } fn seal_caller() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 357_000 picoseconds. - Weight::from_parts(463_000, 0) + // Minimum execution time: 315_000 picoseconds. + Weight::from_parts(425_000, 0) } fn seal_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 339_000 picoseconds. - Weight::from_parts(445_000, 0) + // Minimum execution time: 306_000 picoseconds. + Weight::from_parts(380_000, 0) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) @@ -2252,8 +2255,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `365` // Estimated: `3830` - // Minimum execution time: 7_429_000 picoseconds. - Weight::from_parts(8_340_000, 3830) + // Minimum execution time: 7_354_000 picoseconds. + Weight::from_parts(8_190_000, 3830) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) @@ -2262,16 +2265,16 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `124` // Estimated: `3589` - // Minimum execution time: 4_260_000 picoseconds. - Weight::from_parts(4_794_000, 3589) + // Minimum execution time: 4_103_000 picoseconds. + Weight::from_parts(4_610_000, 3589) .saturating_add(RocksDbWeight::get().reads(1_u64)) } fn own_code_hash() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_417_000 picoseconds. - Weight::from_parts(3_937_000, 0) + // Minimum execution time: 3_280_000 picoseconds. + Weight::from_parts(3_738_000, 0) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -2281,51 +2284,51 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `196` // Estimated: `3661` - // Minimum execution time: 7_788_000 picoseconds. - Weight::from_parts(8_510_000, 3661) + // Minimum execution time: 7_343_000 picoseconds. + Weight::from_parts(8_144_000, 3661) .saturating_add(RocksDbWeight::get().reads(2_u64)) } fn caller_is_origin() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_265_000 picoseconds. - Weight::from_parts(1_552_000, 0) + // Minimum execution time: 1_199_000 picoseconds. + Weight::from_parts(1_446_000, 0) } fn caller_is_root() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_182_000 picoseconds. - Weight::from_parts(1_472_000, 0) + // Minimum execution time: 1_160_000 picoseconds. + Weight::from_parts(1_417_000, 0) } fn seal_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 334_000 picoseconds. - Weight::from_parts(445_000, 0) + // Minimum execution time: 314_000 picoseconds. + Weight::from_parts(392_000, 0) } fn weight_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_235_000 picoseconds. - Weight::from_parts(1_528_000, 0) + // Minimum execution time: 1_174_000 picoseconds. + Weight::from_parts(1_413_000, 0) } fn seal_ref_time_left() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_004_000 picoseconds. - Weight::from_parts(2_280_000, 0) + // Minimum execution time: 1_948_000 picoseconds. + Weight::from_parts(2_222_000, 0) } fn seal_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_428_000 picoseconds. - Weight::from_parts(4_898_000, 0) + // Minimum execution time: 4_377_000 picoseconds. + Weight::from_parts(4_811_000, 0) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) @@ -2337,8 +2340,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `539` // Estimated: `4004` - // Minimum execution time: 13_965_000 picoseconds. - Weight::from_parts(14_997_000, 4004) + // Minimum execution time: 13_714_000 picoseconds. + Weight::from_parts(14_810_000, 4004) .saturating_add(RocksDbWeight::get().reads(3_u64)) } /// Storage: `Revive::ImmutableDataOf` (r:1 w:0) @@ -2348,10 +2351,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `13 + n * (1 ±0)` // Estimated: `3478 + n * (1 ±0)` - // Minimum execution time: 4_103_000 picoseconds. - Weight::from_parts(4_732_656, 3478) + // Minimum execution time: 4_086_000 picoseconds. + Weight::from_parts(4_703_771, 3478) // Standard Error: 0 - .saturating_add(Weight::from_parts(537, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(531, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -2362,67 +2365,67 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_037_000 picoseconds. - Weight::from_parts(2_373_000, 0) + // Minimum execution time: 2_020_000 picoseconds. + Weight::from_parts(2_367_213, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(549, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(545, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().writes(1_u64)) } fn seal_value_transferred() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 297_000 picoseconds. - Weight::from_parts(396_000, 0) + // Minimum execution time: 268_000 picoseconds. + Weight::from_parts(356_000, 0) } fn minimum_balance() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_414_000 picoseconds. - Weight::from_parts(1_731_000, 0) + // Minimum execution time: 1_351_000 picoseconds. + Weight::from_parts(1_654_000, 0) } fn seal_return_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 289_000 picoseconds. - Weight::from_parts(389_000, 0) + // Minimum execution time: 261_000 picoseconds. + Weight::from_parts(335_000, 0) } fn seal_call_data_size() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 288_000 picoseconds. - Weight::from_parts(381_000, 0) + // Minimum execution time: 262_000 picoseconds. + Weight::from_parts(334_000, 0) } fn seal_gas_limit() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 304_000 picoseconds. - Weight::from_parts(398_000, 0) + // Minimum execution time: 263_000 picoseconds. + Weight::from_parts(356_000, 0) } fn seal_gas_price() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_062_000 picoseconds. - Weight::from_parts(1_278_000, 0) + // Minimum execution time: 1_001_000 picoseconds. + Weight::from_parts(1_217_000, 0) } fn seal_base_fee() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_044_000 picoseconds. - Weight::from_parts(1_249_000, 0) + // Minimum execution time: 978_000 picoseconds. + Weight::from_parts(1_181_000, 0) } fn seal_block_number() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 295_000 picoseconds. - Weight::from_parts(396_000, 0) + // Minimum execution time: 269_000 picoseconds. + Weight::from_parts(360_000, 0) } /// Storage: `Session::Validators` (r:1 w:0) /// Proof: `Session::Validators` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) @@ -2430,8 +2433,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `142` // Estimated: `1627` - // Minimum execution time: 19_240_000 picoseconds. - Weight::from_parts(20_538_000, 1627) + // Minimum execution time: 18_545_000 picoseconds. + Weight::from_parts(19_722_000, 1627) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Revive::BlockHash` (r:1 w:0) @@ -2440,41 +2443,41 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `22` // Estimated: `3487` - // Minimum execution time: 3_223_000 picoseconds. - Weight::from_parts(3_608_000, 3487) + // Minimum execution time: 3_145_000 picoseconds. + Weight::from_parts(3_518_000, 3487) .saturating_add(RocksDbWeight::get().reads(1_u64)) } fn seal_now() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 291_000 picoseconds. - Weight::from_parts(388_000, 0) + // Minimum execution time: 259_000 picoseconds. + Weight::from_parts(346_000, 0) } /// The range of component `n` is `[0, 1048572]`. fn seal_copy_to_contract(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 503_000 picoseconds. - Weight::from_parts(558_000, 0) + // Minimum execution time: 481_000 picoseconds. + Weight::from_parts(530_000, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(239, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(240, 0).saturating_mul(n.into())) } fn seal_call_data_load() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 306_000 picoseconds. - Weight::from_parts(399_000, 0) + // Minimum execution time: 257_000 picoseconds. + Weight::from_parts(341_000, 0) } /// The range of component `n` is `[0, 1048576]`. fn seal_call_data_copy(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 331_000 picoseconds. - Weight::from_parts(383_000, 0) + // Minimum execution time: 277_000 picoseconds. + Weight::from_parts(334_000, 0) // Standard Error: 0 .saturating_add(Weight::from_parts(150, 0).saturating_mul(n.into())) } @@ -2483,22 +2486,22 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 340_000 picoseconds. - Weight::from_parts(576_244, 0) + // Minimum execution time: 290_000 picoseconds. + Weight::from_parts(500_344, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(235, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(237, 0).saturating_mul(n.into())) } /// Storage: `Revive::OriginalAccount` (r:2 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) /// The range of component `r` is `[0, 1]`. fn seal_terminate(r: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `348` - // Estimated: `6288` - // Minimum execution time: 11_753_000 picoseconds. - Weight::from_parts(12_850_878, 6288) - // Standard Error: 11_382 - .saturating_add(Weight::from_parts(60_445, 0).saturating_mul(r.into())) + // Measured: `332` + // Estimated: `6272` + // Minimum execution time: 11_707_000 picoseconds. + Weight::from_parts(12_712_227, 6272) + // Standard Error: 10_422 + .saturating_add(Weight::from_parts(36_027, 0).saturating_mul(r.into())) .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `Balances::Holds` (r:2 w:2) @@ -2519,10 +2522,10 @@ impl WeightInfo for () { /// Proof: `Revive::ImmutableDataOf` (`max_values`: None, `max_size`: Some(4118), added: 6593, mode: `Measured`) fn seal_terminate_logic() -> Weight { // Proof Size summary in bytes: - // Measured: `789` - // Estimated: `6729` - // Minimum execution time: 214_858_000 picoseconds. - Weight::from_parts(231_492_000, 6729) + // Measured: `773` + // Estimated: `6713` + // Minimum execution time: 211_802_000 picoseconds. + Weight::from_parts(220_522_000, 6713) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(9_u64)) } @@ -2532,10 +2535,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_129_000 picoseconds. - Weight::from_parts(5_426_000, 0) - // Standard Error: 2 - .saturating_add(Weight::from_parts(1_421, 0).saturating_mul(n.into())) + // Minimum execution time: 5_178_000 picoseconds. + Weight::from_parts(5_415_000, 0) + // Standard Error: 1 + .saturating_add(Weight::from_parts(1_317, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -2543,8 +2546,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `648` // Estimated: `648` - // Minimum execution time: 8_711_000 picoseconds. - Weight::from_parts(9_515_000, 648) + // Minimum execution time: 8_844_000 picoseconds. + Weight::from_parts(9_678_000, 648) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -2553,8 +2556,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `10658` // Estimated: `10658` - // Minimum execution time: 38_638_000 picoseconds. - Weight::from_parts(40_350_000, 10658) + // Minimum execution time: 38_874_000 picoseconds. + Weight::from_parts(40_600_000, 10658) .saturating_add(RocksDbWeight::get().reads(1_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -2563,8 +2566,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `648` // Estimated: `648` - // Minimum execution time: 9_821_000 picoseconds. - Weight::from_parts(10_671_000, 648) + // Minimum execution time: 9_897_000 picoseconds. + Weight::from_parts(10_866_000, 648) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2574,8 +2577,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `10658` // Estimated: `10658` - // Minimum execution time: 40_396_000 picoseconds. - Weight::from_parts(42_183_000, 10658) + // Minimum execution time: 40_501_000 picoseconds. + Weight::from_parts(42_311_000, 10658) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -2586,10 +2589,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 879_806_000 picoseconds. - Weight::from_parts(938_663_968, 0) - // Standard Error: 1_256 - .saturating_add(Weight::from_parts(1_067_429, 0).saturating_mul(n.into())) + // Minimum execution time: 859_695_000 picoseconds. + Weight::from_parts(907_196_094, 0) + // Standard Error: 2_707 + .saturating_add(Weight::from_parts(1_089_439, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().writes(2048_u64)) } /// Storage: `Skipped::Metadata` (r:0 w:0) @@ -2599,10 +2602,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 748_000 picoseconds. - Weight::from_parts(12_316_473, 0) - // Standard Error: 758 - .saturating_add(Weight::from_parts(890_662, 0).saturating_mul(n.into())) + // Minimum execution time: 726_000 picoseconds. + Weight::from_parts(19_170_522, 0) + // Standard Error: 1_136 + .saturating_add(Weight::from_parts(877_369, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -2612,12 +2615,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + o * (1 ±0)` // Estimated: `247 + o * (1 ±0)` - // Minimum execution time: 9_900_000 picoseconds. - Weight::from_parts(10_662_472, 247) - // Standard Error: 15 - .saturating_add(Weight::from_parts(451, 0).saturating_mul(n.into())) - // Standard Error: 15 - .saturating_add(Weight::from_parts(528, 0).saturating_mul(o.into())) + // Minimum execution time: 9_744_000 picoseconds. + Weight::from_parts(10_716_480, 247) + // Standard Error: 17 + .saturating_add(Weight::from_parts(500, 0).saturating_mul(n.into())) + // Standard Error: 17 + .saturating_add(Weight::from_parts(632, 0).saturating_mul(o.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(o.into())) @@ -2630,12 +2633,12 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_411_000 picoseconds. - Weight::from_parts(4_905_650, 0) - // Standard Error: 7 - .saturating_add(Weight::from_parts(398, 0).saturating_mul(n.into())) - // Standard Error: 7 - .saturating_add(Weight::from_parts(94, 0).saturating_mul(o.into())) + // Minimum execution time: 4_370_000 picoseconds. + Weight::from_parts(4_886_632, 0) + // Standard Error: 9 + .saturating_add(Weight::from_parts(400, 0).saturating_mul(n.into())) + // Standard Error: 9 + .saturating_add(Weight::from_parts(59, 0).saturating_mul(o.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -2644,10 +2647,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 10_942_000 picoseconds. - Weight::from_parts(12_422_926, 247) - // Standard Error: 17 - .saturating_add(Weight::from_parts(674, 0).saturating_mul(n.into())) + // Minimum execution time: 11_447_000 picoseconds. + Weight::from_parts(12_648_167, 247) + // Standard Error: 18 + .saturating_add(Weight::from_parts(748, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -2659,10 +2662,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_897_000 picoseconds. - Weight::from_parts(6_628_641, 0) + // Minimum execution time: 5_939_000 picoseconds. + Weight::from_parts(6_666_812, 0) // Standard Error: 10 - .saturating_add(Weight::from_parts(188, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(154, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -2671,10 +2674,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 8_692_000 picoseconds. - Weight::from_parts(10_072_874, 247) + // Minimum execution time: 9_023_000 picoseconds. + Weight::from_parts(10_208_007, 247) // Standard Error: 15 - .saturating_add(Weight::from_parts(1_260, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_375, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -2685,10 +2688,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_413_000 picoseconds. - Weight::from_parts(3_875_397, 0) + // Minimum execution time: 3_462_000 picoseconds. + Weight::from_parts(3_905_870, 0) // Standard Error: 6 - .saturating_add(Weight::from_parts(659, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(655, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -2697,10 +2700,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 10_181_000 picoseconds. - Weight::from_parts(11_375_558, 247) - // Standard Error: 15 - .saturating_add(Weight::from_parts(679, 0).saturating_mul(n.into())) + // Minimum execution time: 10_188_000 picoseconds. + Weight::from_parts(11_468_250, 247) + // Standard Error: 16 + .saturating_add(Weight::from_parts(756, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -2711,10 +2714,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_052_000 picoseconds. - Weight::from_parts(5_595_259, 0) - // Standard Error: 8 - .saturating_add(Weight::from_parts(53, 0).saturating_mul(n.into())) + // Minimum execution time: 4_958_000 picoseconds. + Weight::from_parts(5_570_149, 0) + // Standard Error: 7 + .saturating_add(Weight::from_parts(119, 0).saturating_mul(n.into())) } /// Storage: `Skipped::Metadata` (r:0 w:0) /// Proof: `Skipped::Metadata` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -2723,10 +2726,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `248 + n * (1 ±0)` // Estimated: `247 + n * (1 ±0)` - // Minimum execution time: 11_488_000 picoseconds. - Weight::from_parts(13_213_620, 247) + // Minimum execution time: 11_454_000 picoseconds. + Weight::from_parts(13_207_272, 247) // Standard Error: 22 - .saturating_add(Weight::from_parts(1_350, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_473, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) @@ -2738,80 +2741,80 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_054_000 picoseconds. - Weight::from_parts(7_026_838, 0) + // Minimum execution time: 5_911_000 picoseconds. + Weight::from_parts(6_933_854, 0) // Standard Error: 12 - .saturating_add(Weight::from_parts(841, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(790, 0).saturating_mul(n.into())) } fn access_list_touch_cold_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_683_000 picoseconds. - Weight::from_parts(4_294_000, 0) + // Minimum execution time: 4_251_000 picoseconds. + Weight::from_parts(4_382_000, 0) } fn access_list_touch_hot_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_051_000 picoseconds. - Weight::from_parts(1_193_000, 0) + // Minimum execution time: 1_035_000 picoseconds. + Weight::from_parts(1_176_000, 0) } fn access_list_touch_cold_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` // Minimum execution time: 458_000 picoseconds. - Weight::from_parts(584_000, 0) + Weight::from_parts(570_000, 0) } fn access_list_touch_hot_single_element() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 593_000 picoseconds. - Weight::from_parts(697_000, 0) + // Minimum execution time: 565_000 picoseconds. + Weight::from_parts(673_000, 0) } fn access_list_rollback_amortization() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_903_000 picoseconds. - Weight::from_parts(4_679_000, 0) + // Minimum execution time: 4_423_000 picoseconds. + Weight::from_parts(4_850_000, 0) } fn set_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_594_000 picoseconds. - Weight::from_parts(1_819_000, 0) + // Minimum execution time: 1_553_000 picoseconds. + Weight::from_parts(1_788_000, 0) } fn set_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_896_000 picoseconds. - Weight::from_parts(2_170_000, 0) + // Minimum execution time: 1_903_000 picoseconds. + Weight::from_parts(2_163_000, 0) } fn get_transient_storage_empty() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_539_000 picoseconds. - Weight::from_parts(1_724_000, 0) + // Minimum execution time: 1_495_000 picoseconds. + Weight::from_parts(1_700_000, 0) } fn get_transient_storage_full() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_678_000 picoseconds. + // Minimum execution time: 1_634_000 picoseconds. Weight::from_parts(1_889_000, 0) } fn rollback_transient_storage() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_127_000 picoseconds. - Weight::from_parts(1_327_000, 0) + // Minimum execution time: 1_229_000 picoseconds. + Weight::from_parts(1_429_000, 0) } /// The range of component `n` is `[0, 416]`. /// The range of component `o` is `[0, 416]`. @@ -2819,59 +2822,57 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_432_000 picoseconds. - Weight::from_parts(2_825_609, 0) - // Standard Error: 5 - .saturating_add(Weight::from_parts(279, 0).saturating_mul(n.into())) - // Standard Error: 5 - .saturating_add(Weight::from_parts(374, 0).saturating_mul(o.into())) + // Minimum execution time: 2_391_000 picoseconds. + Weight::from_parts(2_685_206, 0) + // Standard Error: 4 + .saturating_add(Weight::from_parts(306, 0).saturating_mul(n.into())) + // Standard Error: 4 + .saturating_add(Weight::from_parts(383, 0).saturating_mul(o.into())) } /// The range of component `n` is `[0, 416]`. fn seal_clear_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_811_000 picoseconds. - Weight::from_parts(4_462_331, 0) + // Minimum execution time: 3_892_000 picoseconds. + Weight::from_parts(4_482_704, 0) // Standard Error: 7 - .saturating_add(Weight::from_parts(345, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(400, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_get_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_019_000 picoseconds. - Weight::from_parts(2_428_719, 0) + // Minimum execution time: 1_952_000 picoseconds. + Weight::from_parts(2_347_346, 0) // Standard Error: 3 - .saturating_add(Weight::from_parts(375, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(354, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. fn seal_contains_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_375_000 picoseconds. - Weight::from_parts(3_962_070, 0) + // Minimum execution time: 3_469_000 picoseconds. + Weight::from_parts(3_940_543, 0) // Standard Error: 6 - .saturating_add(Weight::from_parts(143, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(215, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 416]`. - fn seal_take_transient_storage(_n: u32, ) -> Weight { + fn seal_take_transient_storage(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 4_269_000 picoseconds. - Weight::from_parts(4_837_696, 0) + // Minimum execution time: 4_305_000 picoseconds. + Weight::from_parts(4_846_729, 0) + // Standard Error: 6 + .saturating_add(Weight::from_parts(9, 0).saturating_mul(n.into())) } /// Storage: `Revive::OriginalAccount` (r:1 w:0) /// Proof: `Revive::OriginalAccount` (`max_values`: None, `max_size`: Some(52), added: 2527, mode: `Measured`) /// Storage: `Revive::AccountInfoOf` (r:1 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) - /// Storage: `Revive::CodeInfoOf` (r:1 w:0) - /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) - /// Storage: `Revive::PristineCode` (r:1 w:0) - /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `System::Account` (r:1 w:1) /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(128), added: 2603, mode: `Measured`) /// The range of component `t` is `[0, 1]`. @@ -2879,20 +2880,27 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 1048576]`. fn seal_call(t: u32, d: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1236` - // Estimated: `4701` - // Minimum execution time: 89_979_000 picoseconds. - Weight::from_parts(70_070_774, 4701) - // Standard Error: 74_621 - .saturating_add(Weight::from_parts(19_752_547, 0).saturating_mul(t.into())) - // Standard Error: 74_621 - .saturating_add(Weight::from_parts(25_306_220, 0).saturating_mul(d.into())) + // Measured: `572` + // Estimated: `4037` + // Minimum execution time: 83_690_000 picoseconds. + Weight::from_parts(64_824_903, 4037) + // Standard Error: 59_255 + .saturating_add(Weight::from_parts(19_587_216, 0).saturating_mul(t.into())) + // Standard Error: 59_255 + .saturating_add(Weight::from_parts(24_915_648, 0).saturating_mul(d.into())) // Standard Error: 0 .saturating_add(Weight::from_parts(3, 0).saturating_mul(i.into())) - .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(t.into()))) } + fn seal_call_hot() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 23_202_000 picoseconds. + Weight::from_parts(25_313_000, 0) + } /// Storage: `Revive::AccountInfoOf` (r:1 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) /// Storage: `System::Account` (r:1 w:0) @@ -2903,48 +2911,44 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0 + d * (174 ±0)` // Estimated: `1819 + d * (1820 ±0)` - // Minimum execution time: 19_472_000 picoseconds. - Weight::from_parts(9_662_203, 1819) - // Standard Error: 13_916 - .saturating_add(Weight::from_parts(11_153_483, 0).saturating_mul(d.into())) + // Minimum execution time: 19_247_000 picoseconds. + Weight::from_parts(9_327_844, 1819) + // Standard Error: 14_465 + .saturating_add(Weight::from_parts(11_260_656, 0).saturating_mul(d.into())) // Standard Error: 0 - .saturating_add(Weight::from_parts(397, 0).saturating_mul(i.into())) + .saturating_add(Weight::from_parts(401, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads((2_u64).saturating_mul(d.into()))) .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(d.into()))) .saturating_add(Weight::from_parts(0, 1820).saturating_mul(d.into())) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) + fn seal_delegate_call() -> Weight { + // Proof Size summary in bytes: + // Measured: `124` + // Estimated: `3589` + // Minimum execution time: 23_991_000 picoseconds. + Weight::from_parts(26_163_000, 3589) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + } + fn seal_delegate_call_hot() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 21_831_000 picoseconds. + Weight::from_parts(23_947_000, 0) + } /// Storage: `Revive::CodeInfoOf` (r:1 w:0) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) /// Storage: `Revive::PristineCode` (r:1 w:0) /// Proof: `Revive::PristineCode` (`max_values`: None, `max_size`: None, mode: `Measured`) - fn seal_delegate_call() -> Weight { - // Proof Size summary in bytes: - // Measured: `749` - // Estimated: `4214` - // Minimum execution time: 28_151_000 picoseconds. - Weight::from_parts(30_587_000, 4214) - .saturating_add(RocksDbWeight::get().reads(3_u64)) - } - // Placeholder until `/cmd bench` runs the `code_load` benchmark: proof-only - // over-approximation reusing seal_delegate_call's {AccountInfoOf, CodeInfoOf, - // PristineCode} proof, which is a superset of the {CodeInfoOf, PristineCode} read. fn code_load() -> Weight { - Weight::from_parts(0, Self::seal_delegate_call().proof_size()) - } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot call re-reads state already in the proof). - fn seal_call_hot() -> Weight { - Weight::from_parts(70_070_774, 0) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - // Placeholder until `/cmd bench` runs the hot benchmarks: cold ref_time - // with the proof size zeroed (a hot call re-reads state already in the proof). - fn seal_delegate_call_hot() -> Weight { - Weight::from_parts(30_587_000, 0) - .saturating_add(RocksDbWeight::get().reads(3_u64)) + // Proof Size summary in bytes: + // Measured: `883` + // Estimated: `4348` + // Minimum execution time: 12_492_000 picoseconds. + Weight::from_parts(13_486_000, 4348) + .saturating_add(RocksDbWeight::get().reads(2_u64)) } /// Storage: `Revive::CodeInfoOf` (r:1 w:1) /// Proof: `Revive::CodeInfoOf` (`max_values`: None, `max_size`: Some(97), added: 2572, mode: `Measured`) @@ -2961,18 +2965,20 @@ impl WeightInfo for () { /// The range of component `i` is `[0, 131072]`. fn seal_instantiate(t: u32, d: u32, i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `699` - // Estimated: `4192` - // Minimum execution time: 134_215_000 picoseconds. - Weight::from_parts(83_528_095, 4192) - // Standard Error: 438_417 - .saturating_add(Weight::from_parts(21_862_241, 0).saturating_mul(t.into())) - // Standard Error: 438_417 - .saturating_add(Weight::from_parts(34_393_022, 0).saturating_mul(d.into())) - // Standard Error: 5 - .saturating_add(Weight::from_parts(4_144, 0).saturating_mul(i.into())) + // Measured: `647` + // Estimated: `4088 + d * (25 ±5) + t * (25 ±5)` + // Minimum execution time: 134_639_000 picoseconds. + Weight::from_parts(85_480_716, 4088) + // Standard Error: 396_463 + .saturating_add(Weight::from_parts(24_452_682, 0).saturating_mul(t.into())) + // Standard Error: 396_463 + .saturating_add(Weight::from_parts(31_069_410, 0).saturating_mul(d.into())) + // Standard Error: 4 + .saturating_add(Weight::from_parts(4_074, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(Weight::from_parts(0, 25).saturating_mul(d.into())) + .saturating_add(Weight::from_parts(0, 25).saturating_mul(t.into())) } /// Storage: `Revive::AccountInfoOf` (r:1 w:1) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -2993,14 +2999,14 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `302` // Estimated: `6210 + d * (22 ±3) + t * (22 ±3)` - // Minimum execution time: 348_954_000 picoseconds. - Weight::from_parts(225_616_923, 6210) - // Standard Error: 519_988 - .saturating_add(Weight::from_parts(17_118_694, 0).saturating_mul(t.into())) - // Standard Error: 519_988 - .saturating_add(Weight::from_parts(23_827_011, 0).saturating_mul(d.into())) - // Standard Error: 20 - .saturating_add(Weight::from_parts(8_065, 0).saturating_mul(i.into())) + // Minimum execution time: 341_911_000 picoseconds. + Weight::from_parts(221_200_992, 6210) + // Standard Error: 581_753 + .saturating_add(Weight::from_parts(25_664_453, 0).saturating_mul(t.into())) + // Standard Error: 581_753 + .saturating_add(Weight::from_parts(28_107_850, 0).saturating_mul(d.into())) + // Standard Error: 23 + .saturating_add(Weight::from_parts(7_723, 0).saturating_mul(i.into())) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(6_u64)) .saturating_add(Weight::from_parts(0, 22).saturating_mul(d.into())) @@ -3011,18 +3017,18 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_462_000 picoseconds. - Weight::from_parts(17_265_292, 0) + // Minimum execution time: 1_440_000 picoseconds. + Weight::from_parts(11_966_571, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_310, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_301, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn identity(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 925_000 picoseconds. - Weight::from_parts(844_673, 0) + // Minimum execution time: 933_000 picoseconds. + Weight::from_parts(726_785, 0) // Standard Error: 0 .saturating_add(Weight::from_parts(149, 0).saturating_mul(n.into())) } @@ -3031,135 +3037,135 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_487_000 picoseconds. - Weight::from_parts(5_175_760, 0) + // Minimum execution time: 1_465_000 picoseconds. + Weight::from_parts(5_607_347, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(3_772, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_777, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn seal_hash_keccak_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_225_000 picoseconds. - Weight::from_parts(16_636_672, 0) + // Minimum execution time: 1_142_000 picoseconds. + Weight::from_parts(13_605_194, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(3_585, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(3_596, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn hash_blake2_256(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_016_000 picoseconds. - Weight::from_parts(18_049_453, 0) + // Minimum execution time: 1_960_000 picoseconds. + Weight::from_parts(13_496_010, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_451, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_454, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048576]`. fn hash_blake2_128(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_093_000 picoseconds. - Weight::from_parts(18_587_920, 0) + // Minimum execution time: 1_975_000 picoseconds. + Weight::from_parts(13_788_816, 0) // Standard Error: 0 - .saturating_add(Weight::from_parts(1_446, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_452, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1048321]`. fn seal_sr25519_verify(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 45_366_000 picoseconds. - Weight::from_parts(87_519_654, 0) + // Minimum execution time: 45_734_000 picoseconds. + Weight::from_parts(92_269_416, 0) // Standard Error: 3 - .saturating_add(Weight::from_parts(4_966, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(4_861, 0).saturating_mul(n.into())) } fn ecdsa_recover() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 46_127_000 picoseconds. - Weight::from_parts(47_562_000, 0) + // Minimum execution time: 46_483_000 picoseconds. + Weight::from_parts(47_728_000, 0) } fn p256_verify() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_786_952_000 picoseconds. - Weight::from_parts(1_802_203_000, 0) + // Minimum execution time: 1_782_736_000 picoseconds. + Weight::from_parts(1_801_110_000, 0) } fn bn128_add() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 14_768_000 picoseconds. - Weight::from_parts(16_550_000, 0) + // Minimum execution time: 14_745_000 picoseconds. + Weight::from_parts(16_419_000, 0) } fn bn128_mul() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 970_342_000 picoseconds. - Weight::from_parts(985_972_000, 0) + // Minimum execution time: 976_251_000 picoseconds. + Weight::from_parts(991_172_000, 0) } /// The range of component `n` is `[0, 20]`. fn bn128_pairing(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_038_000 picoseconds. - Weight::from_parts(4_872_284_272, 0) - // Standard Error: 10_450_049 - .saturating_add(Weight::from_parts(5_922_447_843, 0).saturating_mul(n.into())) + // Minimum execution time: 980_000 picoseconds. + Weight::from_parts(4_980_929_261, 0) + // Standard Error: 10_760_224 + .saturating_add(Weight::from_parts(5_933_016_201, 0).saturating_mul(n.into())) } /// The range of component `n` is `[0, 1200]`. fn blake2f(n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_206_000 picoseconds. - Weight::from_parts(1_549_126, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(29_703, 0).saturating_mul(n.into())) + // Minimum execution time: 1_130_000 picoseconds. + Weight::from_parts(1_489_126, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(30_587, 0).saturating_mul(n.into())) } fn seal_ecdsa_to_eth_address() -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 12_894_000 picoseconds. - Weight::from_parts(13_172_000, 0) + // Minimum execution time: 12_936_000 picoseconds. + Weight::from_parts(13_228_000, 0) } /// The range of component `r` is `[0, 10000]`. fn evm_opcode(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 689_000 picoseconds. - Weight::from_parts(923_228, 0) - // Standard Error: 1 - .saturating_add(Weight::from_parts(7_743, 0).saturating_mul(r.into())) + // Minimum execution time: 643_000 picoseconds. + Weight::from_parts(902_066, 0) + // Standard Error: 2 + .saturating_add(Weight::from_parts(7_690, 0).saturating_mul(r.into())) } /// The range of component `r` is `[0, 10000]`. fn instr(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 14_123_000 picoseconds. - Weight::from_parts(82_116_844, 0) - // Standard Error: 624 - .saturating_add(Weight::from_parts(86_822, 0).saturating_mul(r.into())) + // Minimum execution time: 12_953_000 picoseconds. + Weight::from_parts(38_184_235, 0) + // Standard Error: 857 + .saturating_add(Weight::from_parts(83_522, 0).saturating_mul(r.into())) } /// The range of component `r` is `[0, 10000]`. fn instr_empty_loop(r: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_519_000 picoseconds. - Weight::from_parts(3_433_593, 0) + // Minimum execution time: 3_404_000 picoseconds. + Weight::from_parts(3_339_267, 0) // Standard Error: 7 - .saturating_add(Weight::from_parts(38_940, 0).saturating_mul(r.into())) + .saturating_add(Weight::from_parts(38_879, 0).saturating_mul(r.into())) } /// Storage: `Revive::AccountInfoOf` (r:1 w:0) /// Proof: `Revive::AccountInfoOf` (`max_values`: None, `max_size`: Some(247), added: 2722, mode: `Measured`) @@ -3170,12 +3176,12 @@ impl WeightInfo for () { /// The range of component `n` is `[1000, 102400]`. fn extcodecopy(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `368 + n * (1 ±0)` - // Estimated: `3831 + n * (1 ±0)` - // Minimum execution time: 18_574_000 picoseconds. - Weight::from_parts(14_934_289, 3831) + // Measured: `369 + n * (1 ±0)` + // Estimated: `3832 + n * (1 ±0)` + // Minimum execution time: 17_962_000 picoseconds. + Weight::from_parts(14_565_992, 3832) // Standard Error: 5 - .saturating_add(Weight::from_parts(1_219, 0).saturating_mul(n.into())) + .saturating_add(Weight::from_parts(1_168, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(Weight::from_parts(0, 1).saturating_mul(n.into())) } @@ -3187,8 +3193,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `382` // Estimated: `6322` - // Minimum execution time: 11_355_000 picoseconds. - Weight::from_parts(12_308_000, 6322) + // Minimum execution time: 11_492_000 picoseconds. + Weight::from_parts(12_362_000, 6322) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -3202,8 +3208,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `505` // Estimated: `7010` - // Minimum execution time: 63_135_000 picoseconds. - Weight::from_parts(67_045_000, 7010) + // Minimum execution time: 62_402_000 picoseconds. + Weight::from_parts(65_929_000, 7010) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -3217,8 +3223,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `629` // Estimated: `6196` - // Minimum execution time: 38_935_000 picoseconds. - Weight::from_parts(41_585_000, 6196) + // Minimum execution time: 38_273_000 picoseconds. + Weight::from_parts(41_047_000, 6196) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -3230,8 +3236,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `498` // Estimated: `6134` - // Minimum execution time: 16_267_000 picoseconds. - Weight::from_parts(17_667_000, 6134) + // Minimum execution time: 16_108_000 picoseconds. + Weight::from_parts(17_373_000, 6134) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -3245,8 +3251,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `909` // Estimated: `6434` - // Minimum execution time: 22_918_000 picoseconds. - Weight::from_parts(24_540_000, 6434) + // Minimum execution time: 22_658_000 picoseconds. + Weight::from_parts(24_312_000, 6434) .saturating_add(RocksDbWeight::get().reads(4_u64)) } /// Storage: `Revive::DeletionQueue` (r:2 w:1) @@ -3255,8 +3261,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `313` // Estimated: `6288` - // Minimum execution time: 9_770_000 picoseconds. - Weight::from_parts(10_686_000, 6288) + // Minimum execution time: 9_481_000 picoseconds. + Weight::from_parts(10_484_000, 6288) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -3277,10 +3283,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3012 + n * (97 ±0)` // Estimated: `6303 + n * (104 ±1)` - // Minimum execution time: 27_570_000 picoseconds. - Weight::from_parts(55_661_437, 6303) - // Standard Error: 4_837 - .saturating_add(Weight::from_parts(546_107, 0).saturating_mul(n.into())) + // Minimum execution time: 27_048_000 picoseconds. + Weight::from_parts(53_620_386, 6303) + // Standard Error: 5_729 + .saturating_add(Weight::from_parts(533_429, 0).saturating_mul(n.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) .saturating_add(Weight::from_parts(0, 104).saturating_mul(n.into())) @@ -3302,10 +3308,10 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `3577 + d * (3 ±0)` // Estimated: `7036 + d * (3 ±0)` - // Minimum execution time: 58_934_000 picoseconds. - Weight::from_parts(61_521_292, 7036) - // Standard Error: 88 - .saturating_add(Weight::from_parts(11_606, 0).saturating_mul(d.into())) + // Minimum execution time: 58_325_000 picoseconds. + Weight::from_parts(60_895_382, 7036) + // Standard Error: 85 + .saturating_add(Weight::from_parts(11_402, 0).saturating_mul(d.into())) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) .saturating_add(Weight::from_parts(0, 3).saturating_mul(d.into())) @@ -3325,12 +3331,14 @@ impl WeightInfo for () { /// Storage: `Revive::ReceiptInfoData` (r:0 w:1) /// Proof: `Revive::ReceiptInfoData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `e` is `[0, 100]`. - fn on_finalize_per_event(_e: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1546` - // Estimated: `5011` - // Minimum execution time: 43_178_000 picoseconds. - Weight::from_parts(45_603_687, 5011) + fn on_finalize_per_event(e: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1547` + // Estimated: `5012` + // Minimum execution time: 43_382_000 picoseconds. + Weight::from_parts(45_448_933, 5012) + // Standard Error: 197 + .saturating_add(Weight::from_parts(417, 0).saturating_mul(e.into())) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -3349,14 +3357,12 @@ impl WeightInfo for () { /// Storage: `Revive::ReceiptInfoData` (r:0 w:1) /// Proof: `Revive::ReceiptInfoData` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) /// The range of component `d` is `[0, 16384]`. - fn on_finalize_per_event_data(d: u32, ) -> Weight { + fn on_finalize_per_event_data(_d: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1546` - // Estimated: `5011` - // Minimum execution time: 43_363_000 picoseconds. - Weight::from_parts(45_583_724, 5011) - // Standard Error: 1 - .saturating_add(Weight::from_parts(13, 0).saturating_mul(d.into())) + // Measured: `1547` + // Estimated: `5012` + // Minimum execution time: 43_346_000 picoseconds. + Weight::from_parts(45_781_402, 5012) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } From 7df9a057d2aa3c4a28abee1098a27da48df7f5b0 Mon Sep 17 00:00:00 2001 From: Marian Radu Date: Mon, 20 Jul 2026 15:37:54 +0300 Subject: [PATCH 6/9] pallet-revive: update stipend reentrancy tests for cold/hot call pricing --- .../revive/fixtures/contracts/Stipends.sol | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/substrate/frame/revive/fixtures/contracts/Stipends.sol b/substrate/frame/revive/fixtures/contracts/Stipends.sol index caf2a1f877e9..3d961b3c1f17 100644 --- a/substrate/frame/revive/fixtures/contracts/Stipends.sol +++ b/substrate/frame/revive/fixtures/contracts/Stipends.sol @@ -194,32 +194,40 @@ contract StipendTest { } // Test that the transfer stipend prevents reentrancy. The attacker's receive() - // tries to call back into attemptTransfer() to drain more ETH, but the 2300 - // gas stipend is not enough for an external call. + // tries to call back into attemptTransfer() to drain more ETH, but the stipend + // starves that call, so it drains nothing: the attacker receives only `amount`. function testTransferReentrancy() public payable { uint256 amount = msg.value / 4; - uint256 balanceBefore = address(reentrancyAttacker).balance; + uint256 attackerBefore = address(reentrancyAttacker).balance; + uint256 selfBefore = address(this).balance; - // The attacker's receive() attempts an external call which exhausts - // the stipend, causing receive() to revert with out-of-gas. - bool failed = false; - try this.attemptTransfer(payable(address(reentrancyAttacker)), amount) { - failed = false; - } catch { - failed = true; - } - require(failed, "Transfer to reentrancy attacker should have failed"); - require(address(reentrancyAttacker).balance == balanceBefore, "Attacker balance should not change"); + this.attemptTransfer(payable(address(reentrancyAttacker)), amount); + require( + address(reentrancyAttacker).balance == attackerBefore + amount, + "Attacker should receive exactly the transferred amount" + ); + require( + address(this).balance == selfBefore - amount, + "StipendTest should lose exactly the transferred amount" + ); } // Test that the send stipend prevents reentrancy. function testSendReentrancy() public payable { uint256 amount = msg.value / 4; - uint256 balanceBefore = address(reentrancyAttacker).balance; + uint256 attackerBefore = address(reentrancyAttacker).balance; + uint256 selfBefore = address(this).balance; bool success = payable(address(reentrancyAttacker)).send(amount); - require(!success, "Send to reentrancy attacker should have failed"); - require(address(reentrancyAttacker).balance == balanceBefore, "Attacker balance should not change"); + require(success, "Send to reentrancy attacker should succeed"); + require( + address(reentrancyAttacker).balance == attackerBefore + amount, + "Attacker should receive exactly the sent amount" + ); + require( + address(this).balance == selfBefore - amount, + "StipendTest should lose exactly the sent amount" + ); } receive() external payable {} From 65c0dce2f99220aa9985db78c2820e885dc56ade Mon Sep 17 00:00:00 2001 From: Marian Radu Date: Mon, 20 Jul 2026 18:29:32 +0300 Subject: [PATCH 7/9] pallet-revive: tidy up cold/hot call opcode tests --- substrate/frame/revive/src/exec.rs | 6 - substrate/frame/revive/src/exec/tests.rs | 137 +++++++----------- .../evm/instructions/contract/call_helpers.rs | 4 +- substrate/frame/revive/src/vm/pvm.rs | 4 +- 4 files changed, 62 insertions(+), 89 deletions(-) diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index bc6f0dcb318c..15561eda015c 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -559,12 +559,6 @@ pub trait PrecompileExt: sealing::Sealed { /// Warmth of the state items `access` reads. fn peek_access(&self, access: StateAccess) -> StateAccessKind; - /// Base cost of a call opcode. Peeks the warmth; the entries are touched - /// when the frame is built, so peek and touch see the same state. - fn call_base_cost(&self, callee: H160, delegate: bool) -> RuntimeCosts { - RuntimeCosts::CallBase(self.peek_access(StateAccess::new(callee, delegate))) - } - /// Charges `diff` from the meter. fn charge_storage(&mut self, diff: &Diff) -> DispatchResult; } diff --git a/substrate/frame/revive/src/exec/tests.rs b/substrate/frame/revive/src/exec/tests.rs index cb6dbdd7148a..1c0e4cdbd20d 100644 --- a/substrate/frame/revive/src/exec/tests.rs +++ b/substrate/frame/revive/src/exec/tests.rs @@ -3281,7 +3281,7 @@ fn cold_hot_transient_skips_access_list() { fn cold_hot_3level_commit_then_revert_drops_committed() { // root → A → grandchild. Grandchild commits a touch into A; A then reverts, // dropping it. The next grandchild call must see the slot cold again. - let grandchild_code_hash = MockLoader::insert(Call, |ctx, _| { + let django_code_hash = MockLoader::insert(Call, |ctx, _| { let key = Key::Fix([99; 32]); assert!( is_cold_touch(ctx.ext, &key), @@ -3302,7 +3302,7 @@ fn cold_hot_3level_commit_then_revert_drops_committed() { }); ExtBuilder::default().build().execute_with(|| { - place_contract(&DJANGO, grandchild_code_hash); + place_contract(&DJANGO, django_code_hash); place_contract(&BOB, a_code_hash); place_contract(&CHARLIE, root_code_hash); run_root_call(CHARLIE_ADDR, vec![]); @@ -3311,9 +3311,7 @@ fn cold_hot_3level_commit_then_revert_drops_committed() { #[test] fn cold_hot_call_target_warms_across_calls() { - // The second call to the same target prices its account state, contract - // metadata, and code as hot. - let child_code_hash = MockLoader::insert(Call, |_, _| exec_success()); + let bob_code_hash = MockLoader::insert(Call, |_, _| exec_success()); let root_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!( @@ -3348,7 +3346,7 @@ fn cold_hot_call_target_warms_across_calls() { }); ExtBuilder::default().build().execute_with(|| { - place_contract(&BOB, child_code_hash); + place_contract(&BOB, bob_code_hash); place_contract(&CHARLIE, root_code_hash); run_root_call(CHARLIE_ADDR, vec![]); }); @@ -3356,14 +3354,10 @@ fn cold_hot_call_target_warms_across_calls() { #[test] fn cold_hot_depth_denied_call_leaves_target_cold() { - // A call denied by the depth limit never builds a frame, so it never warms - // the target: a retry still prices it cold. This diverges from EIP-2929 - // (which warms the address even on a failed call) in the overcharge-safe - // direction, and is the intended behavior. parameter_types! { static ReachedBottom: bool = false; } - let target_ch = MockLoader::insert(Call, |_, _| exec_success()); + let django_code_hash = MockLoader::insert(Call, |_, _| exec_success()); let recurse_ch = MockLoader::insert(Call, |ctx, _| { // Recurse into self until the depth limit denies the call. let r = ctx.ext.call( @@ -3377,7 +3371,6 @@ fn cold_hot_depth_denied_call_leaves_target_cold() { ReachedBottom::mutate(|reached_bottom| { if *reached_bottom { - // Unwinding the stack: the self-call succeeds here. assert_matches!(r, Ok(_)); return; } @@ -3395,7 +3388,6 @@ fn cold_hot_depth_denied_call_leaves_target_cold() { "a fresh target starts cold", ); - // Calling a fresh target at max depth is denied before a frame is built. assert_eq!( ctx.ext.call( &Default::default(), @@ -3430,7 +3422,7 @@ fn cold_hot_depth_denied_call_leaves_target_cold() { ExtBuilder::default().build().execute_with(|| { set_balance(&BOB, 1); place_contract(&BOB, recurse_ch); - place_contract(&DJANGO, target_ch); + place_contract(&DJANGO, django_code_hash); let origin = Origin::from_account_id(ALICE); let mut meter = TransactionMeter::::new_from_limits(WEIGHT_LIMIT, 0).unwrap(); let result = MockStack::run_call( @@ -3447,54 +3439,58 @@ fn cold_hot_depth_denied_call_leaves_target_cold() { #[test] fn cold_hot_delegate_call_leaves_target_account_cold() { - // A delegate call reads only the target's contract metadata and code, so - // a later plain call to the same target still prices the account state - // cold. - let child_code_hash = MockLoader::insert(Call, |_, _| exec_success()); + let bob_code_hash = MockLoader::insert(Call, |_, _| exec_success()); let root_code_hash = MockLoader::insert(Call, |ctx, _| { let before = ctx.ext.access_list_metrics(); assert_matches!(ctx.ext.delegate_call(&CallResources::NoLimits, BOB_ADDR, vec![]), Ok(_)); - let after = ctx.ext.access_list_metrics(); + let after_delegate = ctx.ext.access_list_metrics(); assert_eq!( - after.cold - before.cold, + after_delegate.cold - before.cold, 3, "delegate call: contract info + code metadata + code blob touch cold", ); - assert_eq!(after.hot, before.hot, "delegate call adds no hot touches"); + assert_eq!(after_delegate.hot, before.hot, "delegate call adds no hot touches"); + assert_matches!( - ctx.ext.peek_access(StateAccess::DelegateCall { target: BOB_ADDR }), - StateAccessKind::DelegateCall { contract_info: Warmth::Hot } + ctx.ext.call( + &Default::default(), + &BOB_ADDR, + U256::zero(), + vec![], + ReentrancyProtection::AllowReentry, + false, + ), + Ok(_) ); - assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), - StateAccessKind::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Hot }, - "delegate call warms contract metadata but not account state", + assert_eq!( + ctx.ext.access_list_metrics().cold - after_delegate.cold, + 1, + "plain call adds only the account; delegate already warmed metadata and code", ); exec_success() }); ExtBuilder::default().build().execute_with(|| { - place_contract(&BOB, child_code_hash); + place_contract(&BOB, bob_code_hash); place_contract(&CHARLIE, root_code_hash); run_root_call(CHARLIE_ADDR, vec![]); }); } #[test] -fn cold_hot_reverted_caller_drops_target_warmth_but_keeps_own() { - // B calls DJANGO and then reverts: DJANGO's warmth (touched while B ran) - // is dropped, while B's own warmth (touched by root before B ran) - // persists — the caller's touch of a target survives the target's revert. - let grandchild_code_hash = MockLoader::insert(Call, |_, _| exec_success()); +fn cold_hot_caller_touch_outlives_callee_revert() { + // A caller's touch of a target outlives the target's revert; only the touches + // the reverted frame made itself are dropped. + let django_code_hash = MockLoader::insert(Call, |_, _| exec_success()); - let b_code_hash = MockLoader::insert(Call, |ctx, _| { + let bob_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); Err("revert B".into()) }); let root_code_hash = MockLoader::insert(Call, |ctx, _| { - let _ = run_child_call(ctx.ext, &BOB_ADDR, vec![]); + assert_matches!(run_child_call(ctx.ext, &BOB_ADDR, vec![]), Err(_)); assert_matches!( ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), StateAccessKind::Call { @@ -3512,45 +3508,13 @@ fn cold_hot_reverted_caller_drops_target_warmth_but_keeps_own() { }); ExtBuilder::default().build().execute_with(|| { - place_contract(&DJANGO, grandchild_code_hash); - place_contract(&BOB, b_code_hash); + place_contract(&DJANGO, django_code_hash); + place_contract(&BOB, bob_code_hash); place_contract(&CHARLIE, root_code_hash); run_root_call(CHARLIE_ADDR, vec![]); }); } -#[test] -fn cold_hot_call_to_plain_account_warms_target() { - // Calling an address without code still warms its account state and the - // contract-info absence proof; no code entry is added. - let root_code_hash = MockLoader::insert(Call, |ctx, _| { - let plain_account = H160::from_low_u64_be(0x777); - assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: plain_account }), - StateAccessKind::Call { - account: Warmth::Cold { .. }, - contract_info: Warmth::Cold { .. } - } - ); - let before = ctx.ext.access_list_metrics(); - - assert_matches!(run_child_call(ctx.ext, &plain_account, vec![]), Ok(_)); - assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: plain_account }), - StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, - "a call to a plain account warms it", - ); - let after = ctx.ext.access_list_metrics(); - assert_eq!(after.cold - before.cold, 2, "account + contract info; no code entry"); - exec_success() - }); - - ExtBuilder::default().build().execute_with(|| { - place_contract(&BOB, root_code_hash); - run_root_call(BOB_ADDR, vec![]); - }); -} - #[test] fn cold_hot_shared_code_hash_is_hot_across_addresses() { // Two contracts share one code hash: calling the second prices its @@ -3578,13 +3542,11 @@ fn cold_hot_shared_code_hash_is_hot_across_addresses() { #[test] fn cold_hot_first_frame_warms_entry_target() { - // The first frame's touches are seeded at stack creation, so a reentrant - // self-call prices hot. let root_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!( ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, - "the entry target's entries are seeded by the first frame", + "the entry target is pre-warmed by the first frame", ); exec_success() }); @@ -3596,26 +3558,39 @@ fn cold_hot_first_frame_warms_entry_target() { } #[test] -fn cold_hot_code_loads_cold_after_target_warmed_as_plain_account() { - // Warm an address as a plain account (no code loaded), then place code there, - // so the next call sees account and contract info hot but the code cold. +fn cold_hot_plain_account_warms_then_code_loads_cold() { + // A plain-account call warms account state and contract info, not code. After + // code is added, a repeat call reads account and contract info hot, code cold. let django_code_hash = MockLoader::insert(Call, |_, _| exec_success()); let root_code_hash = MockLoader::insert(Call, move |ctx, _| { + assert_matches!( + ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), + StateAccessKind::Call { + account: Warmth::Cold { .. }, + contract_info: Warmth::Cold { .. } + }, + "an uncalled target starts cold", + ); + + // DJANGO has no code yet: the call warms account + contract info only. + let before = ctx.ext.access_list_metrics(); assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); assert_matches!( ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, - "the plain-account call warmed account and contract info", + "a call to a plain account warms it", ); + let after_plain = ctx.ext.access_list_metrics(); + assert_eq!(after_plain.cold - before.cold, 2, "account + contract info; no code entry"); + // Place code, then call again: account and contract info stay hot (read by + // the first call), while the newly added code loads cold. place_contract(&DJANGO, django_code_hash); - - let before = ctx.ext.access_list_metrics(); assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); - let after = ctx.ext.access_list_metrics(); - assert_eq!(after.hot - before.hot, 2, "account + contract info are already hot"); - assert_eq!(after.cold - before.cold, 2, "code metadata + blob load",); + let after_coded = ctx.ext.access_list_metrics(); + assert_eq!(after_coded.hot - after_plain.hot, 2, "account + contract info are already hot"); + assert_eq!(after_coded.cold - after_plain.cold, 2, "code metadata + blob load"); exec_success() }); diff --git a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs index b00cc44faf27..5bc1bf19f8a2 100644 --- a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs +++ b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs @@ -17,6 +17,7 @@ use crate::{ Pallet, RuntimeCosts, + access_list::StateAccess, precompiles::{All as AllPrecompiles, Precompiles}, vm::{ Ext, @@ -84,7 +85,8 @@ pub fn charge_call_gas<'a, E: Ext>( }, None => { // Regular CALL / DELEGATECALL base cost / CALLCODE not supported. - let cost = interpreter.ext.call_base_cost(callee, scheme.is_delegate_call()); + let access = StateAccess::new(callee, scheme.is_delegate_call()); + let cost = RuntimeCosts::CallBase(interpreter.ext.peek_access(access)); interpreter.ext.charge_or_halt(cost)?; interpreter diff --git a/substrate/frame/revive/src/vm/pvm.rs b/substrate/frame/revive/src/vm/pvm.rs index 3b57a998150f..5160c8864017 100644 --- a/substrate/frame/revive/src/vm/pvm.rs +++ b/substrate/frame/revive/src/vm/pvm.rs @@ -21,6 +21,7 @@ pub mod env; use crate::{ Code, Config, Error, LOG_TARGET, Pallet, ReentrancyProtection, RuntimeCosts, SENTINEL, + access_list::StateAccess, exec::{CallResources, ExecError, ExecResult, Ext, Key}, limits, metering::ChargedAmount, @@ -280,7 +281,8 @@ enum CallType { impl CallType { /// Base cost of the call. fn cost(&self, ext: &impl Ext, callee: &sp_core::H160) -> RuntimeCosts { - ext.call_base_cost(*callee, matches!(self, CallType::DelegateCall)) + let access = StateAccess::new(*callee, matches!(self, CallType::DelegateCall)); + RuntimeCosts::CallBase(ext.peek_access(access)) } } From 8727b3d1cfd058a4358babd6a3fea4ee121cfe67 Mon Sep 17 00:00:00 2001 From: Marian Radu Date: Tue, 21 Jul 2026 12:06:33 +0300 Subject: [PATCH 8/9] pallet-revive: give the access-list warmth API clearer names --- substrate/frame/revive/src/access_list.rs | 110 ++++++++---------- substrate/frame/revive/src/benchmarking.rs | 2 +- substrate/frame/revive/src/exec.rs | 50 ++++---- substrate/frame/revive/src/exec/mock_ext.rs | 18 +-- substrate/frame/revive/src/exec/tests.rs | 56 ++++----- substrate/frame/revive/src/lib.rs | 8 +- .../evm/instructions/contract/call_helpers.rs | 2 +- substrate/frame/revive/src/vm/mod.rs | 8 +- substrate/frame/revive/src/vm/pvm.rs | 2 +- .../frame/revive/src/vm/runtime_costs.rs | 70 +++++++---- 10 files changed, 161 insertions(+), 165 deletions(-) diff --git a/substrate/frame/revive/src/access_list.rs b/substrate/frame/revive/src/access_list.rs index e8d6c886857e..c77be38cabf5 100644 --- a/substrate/frame/revive/src/access_list.rs +++ b/substrate/frame/revive/src/access_list.rs @@ -73,7 +73,7 @@ pub const MAX_ACCESS_LIST_ENTRY_BYTES: usize = 512; pub const MAX_ACCESS_LIST_BYTES: u32 = MAX_ACCESS_LIST_ENTRIES.saturating_mul(MAX_ACCESS_LIST_ENTRY_BYTES) as u32; -/// Storage slot identifier for an access-list entry. +/// The storage key of an [`AccessEntry::Storage`] entry. #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Clone)] pub enum Slot { /// Fixed 32-byte storage key. @@ -110,14 +110,14 @@ impl From<&Key> for Slot { pub enum Warmth { /// Entry is in the access list. Hot, - /// Entry is not in the access list; when `revertible` is true, the touch - /// journals the entry under the open frame, so a `rollback_frame` drops - /// it and the entry becomes cold again. + /// Entry is not in the access list; when `revertible` is true, the touch is + /// tied to the current frame, so a `rollback_frame` drops it and the entry + /// becomes cold again. Cold { revertible: bool }, } impl Warmth { - pub fn cold_nonrevertible() -> Self { + pub fn cold_non_revertible() -> Self { Self::Cold { revertible: false } } @@ -125,6 +125,7 @@ impl Warmth { matches!(self, Self::Hot) } + /// Converts a cold touch to non-revertible. pub fn non_revertible(self) -> Self { match self { Self::Hot => Self::Hot, @@ -143,33 +144,13 @@ pub struct CodeLoadWarmth { } impl CodeLoadWarmth { - pub fn cold_nonrevertible() -> Self { - Self { info: Warmth::cold_nonrevertible(), blob: Warmth::cold_nonrevertible() } + pub fn cold_non_revertible() -> Self { + Self { info: Warmth::cold_non_revertible(), blob: Warmth::cold_non_revertible() } } } -/// Classification of a storage access for pricing. -#[cfg_attr(test, derive(PartialEq, Eq))] -#[derive(Clone, Copy, Debug)] -pub enum StorageAccessKind { - /// Persistent storage, tracked by the access list. - Persistent(Warmth), - /// Transient storage, not tracked by the access list. - Transient, -} - -impl StorageAccessKind { - /// See [`Warmth::non_revertible`]. - pub fn non_revertible(self) -> Self { - match self { - Self::Persistent(warmth) => Self::Persistent(warmth.non_revertible()), - Self::Transient => Self::Transient, - } - } -} - -/// A state access of an opcode, tracked by the access list. -#[derive(Clone, Copy)] +/// A call-family opcode's state access, tracked by the access list. Storage +/// opcodes touch [`AccessEntry::Storage`] directly and are not modelled here. pub enum StateAccess { Call { target: H160 }, DelegateCall { target: H160 }, @@ -182,14 +163,14 @@ impl StateAccess { } /// Maps `warmth_of` over each state item this access reads and collects - /// the results into a [`StateAccessKind`]. - pub fn expand(self, mut warmth_of: impl FnMut(AccessEntry) -> Warmth) -> StateAccessKind { + /// the results into a [`StateAccessWarmth`]. + pub fn expand(self, mut warmth_of: impl FnMut(AccessEntry) -> Warmth) -> StateAccessWarmth { match self { - Self::Call { target } => StateAccessKind::Call { + Self::Call { target } => StateAccessWarmth::Call { account: warmth_of(AccessEntry::Account { address: target }), contract_info: warmth_of(AccessEntry::ContractInfo { address: target }), }, - Self::DelegateCall { target } => StateAccessKind::DelegateCall { + Self::DelegateCall { target } => StateAccessWarmth::DelegateCall { contract_info: warmth_of(AccessEntry::ContractInfo { address: target }), }, } @@ -199,7 +180,7 @@ impl StateAccess { /// Warmth of the read state items, one variant per [`StateAccess`] opcode. #[cfg_attr(test, derive(PartialEq, Eq))] #[derive(Clone, Copy, Debug)] -pub enum StateAccessKind { +pub enum StateAccessWarmth { /// A call reads the target's account state and contract metadata. Call { account: Warmth, contract_info: Warmth }, /// A delegate call runs in the caller's context and reads only the @@ -221,7 +202,7 @@ pub struct AccessListMetrics { /// One entry per distinct state item accessed in the current transaction. #[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Clone)] pub enum AccessEntry { - /// Account-level state of `address`. + /// Account at `address`: both `System::Account` and `OriginalAccount`. Account { address: H160 }, /// A contract storage slot. Field order is `slot, address` so comparison /// decides on `slot` first, the most-discriminating field in the typical @@ -240,11 +221,13 @@ pub enum AccessEntry { /// follows [`crate::transient_storage::TransientStorage`]: a current-state /// set, a flat journal of insertions, and journal-index checkpoints. /// -/// # Safety invariant +/// A reverting frame rolls back every entry it touched, regardless of whether +/// the touch happened before or after its charge: /// -/// Storage opcodes touch before charging, so reverts must roll back the -/// touches the reverted frame made; otherwise an out-of-gas at the charge -/// would leave the entry warm without its cold cost ever being paid. +/// - Touch before charge: an out-of-gas at the charge must not leave the entry warm without its +/// cold cost ever being paid. +/// - Charge before touch: a reverting frame discards the warmth it added (EIP-2929 revert +/// semantics). #[derive(Default)] pub struct AccessList { @@ -306,28 +289,28 @@ impl AccessList { } } + /// Whether the set is at the entry cap. + fn is_full(&self) -> bool { + self.accessed.len() >= MAX_ACCESS_LIST_ENTRIES + } + + /// Whether a nested-frame checkpoint is open. + fn in_nested_frame(&self) -> bool { + !self.checkpoints.is_empty() + } + /// Non-mutating sibling of [`touch`](Self::touch): the `Warmth` a touch /// of this entry would return. pub fn peek(&self, entry: &AccessEntry) -> Warmth { if self.accessed.contains(entry) { Warmth::Hot } else if self.is_full() { - Warmth::cold_nonrevertible() + Warmth::cold_non_revertible() } else { Warmth::Cold { revertible: self.in_nested_frame() } } } - /// Whether the set is at the entry cap. - fn is_full(&self) -> bool { - self.accessed.len() >= MAX_ACCESS_LIST_ENTRIES - } - - /// Whether a nested-frame checkpoint is open. - fn in_nested_frame(&self) -> bool { - !self.checkpoints.is_empty() - } - /// Register the entry, returning its warmth **before** this touch: the /// first touch of an entry returns `Cold` although the entry is tracked /// from now on. @@ -359,26 +342,27 @@ impl AccessList { kind } - /// Touches each state item read by `access` and returns its warmth. - pub fn touch_access(&mut self, access: StateAccess) -> StateAccessKind { + /// Warms every state item `access` reads, returning its warmth. Keeps the + /// per-entry `touch` an `AccessList` detail: callers speak opcodes. + pub fn warm(&mut self, access: StateAccess) -> StateAccessWarmth { access.expand(|entry| self.touch(entry)) } - /// Non-mutating sibling of [`touch_access`](Self::touch_access). - pub fn peek_access(&self, access: StateAccess) -> StateAccessKind { + /// Non-mutating sibling of [`warm`](Self::warm): the warmth without registering. + pub fn warmth_of(&self, access: StateAccess) -> StateAccessWarmth { access.expand(|entry| self.peek(&entry)) } - /// Registers the two state items a code load reads, returning their warmth. - pub fn touch_code(&mut self, hash: H256) -> CodeLoadWarmth { + /// Registers the two entries a code load reads, returning their warmth. + pub fn warm_code(&mut self, hash: H256) -> CodeLoadWarmth { CodeLoadWarmth { info: self.touch(AccessEntry::CodeInfo { hash }), blob: self.touch(AccessEntry::CodeBlob { hash }), } } - /// Non-mutating sibling of [`touch_code`](Self::touch_code). - pub fn peek_code(&self, hash: H256) -> CodeLoadWarmth { + /// Non-mutating sibling of [`warm_code`](Self::warm_code). + pub fn code_warmth_of(&self, hash: H256) -> CodeLoadWarmth { CodeLoadWarmth { info: self.peek(&AccessEntry::CodeInfo { hash }), blob: self.peek(&AccessEntry::CodeBlob { hash }), @@ -502,8 +486,8 @@ mod tests { // The set is below the cap, so peek prices both call entries revertible // cold: it cannot see that touching the first entry fills the cap. assert_eq!( - al.peek_access(StateAccess::Call { target }), - StateAccessKind::Call { + al.warmth_of(StateAccess::Call { target }), + StateAccessWarmth::Call { account: Warmth::Cold { revertible: true }, contract_info: Warmth::Cold { revertible: true }, }, @@ -512,10 +496,10 @@ mod tests { // The first touch fills the cap, so ContractInfo lands past it: non-revertible. assert_eq!( - al.touch_access(StateAccess::Call { target }), - StateAccessKind::Call { + al.warm(StateAccess::Call { target }), + StateAccessWarmth::Call { account: Warmth::Cold { revertible: true }, - contract_info: Warmth::cold_nonrevertible(), + contract_info: Warmth::cold_non_revertible(), }, "touch journals only the first entry before the cap fills", ); diff --git a/substrate/frame/revive/src/benchmarking.rs b/substrate/frame/revive/src/benchmarking.rs index 4eda2be0c66c..881897b80912 100644 --- a/substrate/frame/revive/src/benchmarking.rs +++ b/substrate/frame/revive/src/benchmarking.rs @@ -2674,7 +2674,7 @@ mod benchmarks { blob = ContractBlob::::from_storage( code_hash, &mut meter, - CodeLoadWarmth::cold_nonrevertible(), + CodeLoadWarmth::cold_non_revertible(), ); } assert!(blob.is_ok(), "loading the code of an existing contract must succeed"); diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index 15561eda015c..bfe9a0e75113 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -17,11 +17,9 @@ use crate::{ AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, Code, CodeInfo, CodeInfoOf, - CodeRemoved, Config, ContractInfo, Error, Event, ImmutableData, ImmutableDataOf, LOG_TARGET, - Pallet as Contracts, RuntimeCosts, TrieId, - access_list::{ - AccessEntry, AccessList, CodeLoadWarmth, StateAccess, StateAccessKind, StorageAccessKind, - }, + CodeRemoved, Config, ContractInfo, ContractStorageKind, Error, Event, ImmutableData, + ImmutableDataOf, LOG_TARGET, Pallet as Contracts, RuntimeCosts, TrieId, + access_list::{AccessEntry, AccessList, CodeLoadWarmth, StateAccess, StateAccessWarmth}, address::{self, AddressMapper}, deposit_payment::Deposit as _, evm::{block_storage, fees::InfoT as _, transfer_with_dust}, @@ -548,16 +546,16 @@ pub trait PrecompileExt: sealing::Sealed { /// Checks if `key` was already accessed in this transaction and inserts it /// otherwise, so subsequent accesses to the same slot bill as hot. Returns - /// the [`StorageAccessKind`]: hot if `key` was already accessed, cold + /// the [`ContractStorageKind`]: hot if `key` was already accessed, cold /// otherwise. When `transient` is true, skips the access list and returns /// the `Transient` variant. - fn touch_storage_access(&mut self, transient: bool, key: &Key) -> StorageAccessKind; + fn touch_storage_access(&mut self, transient: bool, key: &Key) -> ContractStorageKind; /// Non-mutating sibling of `touch_storage_access`. - fn peek_storage_access(&self, transient: bool, key: &Key) -> StorageAccessKind; + fn peek_storage_access(&self, transient: bool, key: &Key) -> ContractStorageKind; /// Warmth of the state items `access` reads. - fn peek_access(&self, access: StateAccess) -> StateAccessKind; + fn warmth_of(&self, access: StateAccess) -> StateAccessWarmth; /// Charges `diff` from the meter. fn charge_storage(&mut self, diff: &Diff) -> DispatchResult; @@ -1103,7 +1101,7 @@ where ), }; if !target_is_precompile { - access_list.touch_access(access); + access_list.warm(access); } // which contract info to load is unaffected by the fact if this @@ -1155,9 +1153,9 @@ where }; // Touch only after the charge succeeds, so a failed load // leaves nothing warm. - let code_warmth = access_list.peek_code(info.code_hash); + let code_warmth = access_list.code_warmth_of(info.code_hash); let executable = E::from_storage(info.code_hash, meter, code_warmth)?; - access_list.touch_code(info.code_hash); + access_list.warm_code(info.code_hash); ExecutableOrPrecompile::Executable(executable) } } else { @@ -1173,9 +1171,9 @@ where .code_hash; // Touch only after the charge succeeds, so a failed load // leaves nothing warm. - let code_warmth = access_list.peek_code(code_hash); + let code_warmth = access_list.code_warmth_of(code_hash); let executable = E::from_storage(code_hash, meter, code_warmth)?; - access_list.touch_code(code_hash); + access_list.warm_code(code_hash); ExecutableOrPrecompile::Executable(executable) } }; @@ -1949,8 +1947,8 @@ where /// Touches the access-list entries `access` reads, plus the code, as if the call already ran. #[cfg(feature = "runtime-benchmarks")] pub(crate) fn touch_call_target(&mut self, access: StateAccess, code_hash: H256) { - self.access_list.touch_access(access); - self.access_list.touch_code(code_hash); + self.access_list.warm(access); + self.access_list.warm_code(code_hash); } /// Per-transaction access list metrics (testing). @@ -2165,9 +2163,9 @@ where Code::Existing(hash) => { // Touch only after the charge succeeds, so a failed load // leaves nothing warm. - let code_warmth = self.access_list.peek_code(*hash); + let code_warmth = self.access_list.code_warmth_of(*hash); let executable = E::from_storage(*hash, self.frame_meter_mut(), code_warmth)?; - self.access_list.touch_code(*hash); + self.access_list.warm_code(*hash); ensure!(executable.code_info().is_pvm(), >::EvmConstructedFromHash); executable }, @@ -2670,28 +2668,28 @@ where ) } - fn touch_storage_access(&mut self, transient: bool, key: &Key) -> StorageAccessKind { + fn touch_storage_access(&mut self, transient: bool, key: &Key) -> ContractStorageKind { if transient { - return StorageAccessKind::Transient; + return ContractStorageKind::Transient; } let address = self.address(); - StorageAccessKind::Persistent( + ContractStorageKind::Persistent( self.access_list.touch(AccessEntry::Storage { address, slot: key.into() }), ) } - fn peek_storage_access(&self, transient: bool, key: &Key) -> StorageAccessKind { + fn peek_storage_access(&self, transient: bool, key: &Key) -> ContractStorageKind { if transient { - return StorageAccessKind::Transient; + return ContractStorageKind::Transient; } let address = self.address(); - StorageAccessKind::Persistent( + ContractStorageKind::Persistent( self.access_list.peek(&AccessEntry::Storage { address, slot: key.into() }), ) } - fn peek_access(&self, access: StateAccess) -> StateAccessKind { - self.access_list.peek_access(access) + fn warmth_of(&self, access: StateAccess) -> StateAccessWarmth { + self.access_list.warmth_of(access) } fn charge_storage(&mut self, diff: &Diff) -> DispatchResult { diff --git a/substrate/frame/revive/src/exec/mock_ext.rs b/substrate/frame/revive/src/exec/mock_ext.rs index 6712ec8309b5..de46d0307859 100644 --- a/substrate/frame/revive/src/exec/mock_ext.rs +++ b/substrate/frame/revive/src/exec/mock_ext.rs @@ -256,27 +256,19 @@ impl PrecompileExt for MockExt { panic!("MockExt::set_storage") } - fn touch_storage_access( - &mut self, - _transient: bool, - _key: &Key, - ) -> crate::access_list::StorageAccessKind { + fn touch_storage_access(&mut self, _transient: bool, _key: &Key) -> crate::ContractStorageKind { panic!("MockExt::touch_storage_access") } - fn peek_storage_access( - &self, - _transient: bool, - _key: &Key, - ) -> crate::access_list::StorageAccessKind { + fn peek_storage_access(&self, _transient: bool, _key: &Key) -> crate::ContractStorageKind { panic!("MockExt::peek_storage_access") } - fn peek_access( + fn warmth_of( &self, _opcode: crate::access_list::StateAccess, - ) -> crate::access_list::StateAccessKind { - panic!("MockExt::peek_access") + ) -> crate::access_list::StateAccessWarmth { + panic!("MockExt::warmth_of") } fn charge_storage(&mut self, _diff: &Diff) -> DispatchResult { diff --git a/substrate/frame/revive/src/exec/tests.rs b/substrate/frame/revive/src/exec/tests.rs index 1c0e4cdbd20d..dd40f2eadbba 100644 --- a/substrate/frame/revive/src/exec/tests.rs +++ b/substrate/frame/revive/src/exec/tests.rs @@ -24,8 +24,8 @@ use super::*; use crate::{ AddressMapper, Error, Pallet, ReentrancyProtection, access_list::{ - CodeLoadWarmth, MAX_ACCESS_LIST_ENTRIES, MAX_INLINE_KEY_LEN, StateAccess, StateAccessKind, - Warmth, + CodeLoadWarmth, MAX_ACCESS_LIST_ENTRIES, MAX_INLINE_KEY_LEN, StateAccess, + StateAccessWarmth, Warmth, }, exec::ExportedFunction::*, metering::TransactionMeter, @@ -209,7 +209,7 @@ fn from_storage_cold( code_hash: H256, meter: &mut crate::metering::ResourceMeter, ) -> Result { - MockExecutable::from_storage(code_hash, meter, CodeLoadWarmth::cold_nonrevertible()) + MockExecutable::from_storage(code_hash, meter, CodeLoadWarmth::cold_non_revertible()) } #[test] @@ -3045,7 +3045,7 @@ fn delegatecall_tracer_reports_correct_addresses() { fn is_cold_touch(ext: &mut E, key: &Key) -> bool { matches!( ext.touch_storage_access(false, key), - StorageAccessKind::Persistent(Warmth::Cold { .. }) + ContractStorageKind::Persistent(Warmth::Cold { .. }) ) } @@ -3194,7 +3194,7 @@ fn cold_hot_revertible_only_inside_nested_frame() { let child_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!( ctx.ext.touch_storage_access(false, &Key::Fix(SLOT)), - StorageAccessKind::Persistent(Warmth::Cold { revertible: true }), + ContractStorageKind::Persistent(Warmth::Cold { revertible: true }), "a cold touch in a nested frame is revertible", ); exec_success() @@ -3203,7 +3203,7 @@ fn cold_hot_revertible_only_inside_nested_frame() { let root_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!( ctx.ext.touch_storage_access(false, &Key::Fix(SLOT)), - StorageAccessKind::Persistent(Warmth::Cold { revertible: false }), + ContractStorageKind::Persistent(Warmth::Cold { revertible: false }), "a cold touch in the root frame is not revertible", ); assert_matches!(run_child_call(ctx.ext, &BOB_ADDR, vec![]), Ok(_)); @@ -3228,13 +3228,13 @@ fn cold_hot_past_cap_touch_is_not_revertible() { slot[..4].copy_from_slice(&i.to_le_bytes()); assert_matches!( ctx.ext.touch_storage_access(false, &Key::Fix(slot)), - StorageAccessKind::Persistent(Warmth::Cold { revertible: true }) + ContractStorageKind::Persistent(Warmth::Cold { revertible: true }) ); } // A further distinct slot is past the cap: cold but not revertible. assert_matches!( ctx.ext.touch_storage_access(false, &Key::Fix([0xFF; 32])), - StorageAccessKind::Persistent(Warmth::Cold { revertible: false }), + ContractStorageKind::Persistent(Warmth::Cold { revertible: false }), "past-cap touch is cold but not revertible", ); exec_success() @@ -3259,12 +3259,12 @@ fn cold_hot_transient_skips_access_list() { // `transient: true` classifies as `Transient` without touching the access list. let kind = ctx.ext.touch_storage_access(true, &key); - assert!(matches!(kind, StorageAccessKind::Transient)); + assert!(matches!(kind, ContractStorageKind::Transient)); // The same key is still cold in the persistent access list. let persistent_kind = ctx.ext.peek_storage_access(false, &key); assert!( - matches!(persistent_kind, StorageAccessKind::Persistent(Warmth::Cold { .. })), + matches!(persistent_kind, ContractStorageKind::Persistent(Warmth::Cold { .. })), "transient access must not warm the persistent access list", ); @@ -3315,8 +3315,8 @@ fn cold_hot_call_target_warms_across_calls() { let root_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), - StateAccessKind::Call { + ctx.ext.warmth_of(StateAccess::Call { target: BOB_ADDR }), + StateAccessWarmth::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Cold { .. } }, @@ -3326,8 +3326,8 @@ fn cold_hot_call_target_warms_across_calls() { assert_matches!(run_child_call(ctx.ext, &BOB_ADDR, vec![]), Ok(_)); assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), - StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + ctx.ext.warmth_of(StateAccess::Call { target: BOB_ADDR }), + StateAccessWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, "account state and contract metadata are hot after the first call", ); let mid = ctx.ext.access_list_metrics(); @@ -3380,8 +3380,8 @@ fn cold_hot_depth_denied_call_leaves_target_cold() { let before = ctx.ext.access_list_metrics(); assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), - StateAccessKind::Call { + ctx.ext.warmth_of(StateAccess::Call { target: DJANGO_ADDR }), + StateAccessWarmth::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Cold { .. } }, @@ -3407,8 +3407,8 @@ fn cold_hot_depth_denied_call_leaves_target_cold() { "the denied call warms nothing", ); assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), - StateAccessKind::Call { + ctx.ext.warmth_of(StateAccess::Call { target: DJANGO_ADDR }), + StateAccessWarmth::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Cold { .. } }, @@ -3492,16 +3492,16 @@ fn cold_hot_caller_touch_outlives_callee_revert() { let root_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!(run_child_call(ctx.ext, &BOB_ADDR, vec![]), Err(_)); assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), - StateAccessKind::Call { + ctx.ext.warmth_of(StateAccess::Call { target: DJANGO_ADDR }), + StateAccessWarmth::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Cold { .. } }, "B's revert drops the warmth of targets B touched", ); assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), - StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + ctx.ext.warmth_of(StateAccess::Call { target: BOB_ADDR }), + StateAccessWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, "the caller's touch of B persists even though B reverted", ); exec_success() @@ -3544,8 +3544,8 @@ fn cold_hot_shared_code_hash_is_hot_across_addresses() { fn cold_hot_first_frame_warms_entry_target() { let root_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: BOB_ADDR }), - StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + ctx.ext.warmth_of(StateAccess::Call { target: BOB_ADDR }), + StateAccessWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, "the entry target is pre-warmed by the first frame", ); exec_success() @@ -3565,8 +3565,8 @@ fn cold_hot_plain_account_warms_then_code_loads_cold() { let root_code_hash = MockLoader::insert(Call, move |ctx, _| { assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), - StateAccessKind::Call { + ctx.ext.warmth_of(StateAccess::Call { target: DJANGO_ADDR }), + StateAccessWarmth::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Cold { .. } }, @@ -3577,8 +3577,8 @@ fn cold_hot_plain_account_warms_then_code_loads_cold() { let before = ctx.ext.access_list_metrics(); assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); assert_matches!( - ctx.ext.peek_access(StateAccess::Call { target: DJANGO_ADDR }), - StateAccessKind::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + ctx.ext.warmth_of(StateAccess::Call { target: DJANGO_ADDR }), + StateAccessWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, "a call to a plain account warms it", ); let after_plain = ctx.ext.access_list_metrics(); diff --git a/substrate/frame/revive/src/lib.rs b/substrate/frame/revive/src/lib.rs index ecbe20ae2cbc..2c3d6cb053ed 100644 --- a/substrate/frame/revive/src/lib.rs +++ b/substrate/frame/revive/src/lib.rs @@ -54,7 +54,7 @@ pub mod tracing; pub mod weights; use crate::{ - access_list::{StorageAccessKind, Warmth}, + access_list::Warmth, evm::{ CallTracer, CreateCallMode, ExecutionTracer, GenericTransaction, PrestateTracer, TYPE_EIP1559, Tracer, TracerType, block_hash::EthereumBlockBuilderIR, block_storage, @@ -64,7 +64,7 @@ use crate::{ sp_runtime::TransactionOutcome, storage::{AccountType, DeletionQueueManager}, tracing::if_tracing, - vm::{CodeInfo, RuntimeCosts, pvm::extract_code_and_data}, + vm::{CodeInfo, ContractStorageKind, RuntimeCosts, pvm::extract_code_and_data}, weightinfo_extension::OnFinalizeBlockParts, }; use alloc::{boxed::Box, format, vec}; @@ -1115,7 +1115,7 @@ pub mod pallet { &>::weight(&RuntimeCosts::SetStorage { new_bytes: limits::STORAGE_BYTES, old_bytes: 0, - kind: StorageAccessKind::Persistent(Warmth::Cold { revertible: true }), + kind: ContractStorageKind::Persistent(Warmth::Cold { revertible: true }), }) .saturating_mul(u64::from(limits::STORAGE_BYTES).saturating_add(max_key_size)), ) @@ -1890,7 +1890,7 @@ impl Pallet { let executable = ContractBlob::from_storage( code_hash, &mut transaction_meter, - access_list::CodeLoadWarmth::cold_nonrevertible(), + access_list::CodeLoadWarmth::cold_non_revertible(), )?; ensure!(executable.code_info().is_pvm(), >::EvmConstructedFromHash); executable diff --git a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs index 5bc1bf19f8a2..6e878f22589c 100644 --- a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs +++ b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs @@ -86,7 +86,7 @@ pub fn charge_call_gas<'a, E: Ext>( None => { // Regular CALL / DELEGATECALL base cost / CALLCODE not supported. let access = StateAccess::new(callee, scheme.is_delegate_call()); - let cost = RuntimeCosts::CallBase(interpreter.ext.peek_access(access)); + let cost = RuntimeCosts::CallBase(interpreter.ext.warmth_of(access)); interpreter.ext.charge_or_halt(cost)?; interpreter diff --git a/substrate/frame/revive/src/vm/mod.rs b/substrate/frame/revive/src/vm/mod.rs index 4ecbea910e90..0bb5342ff217 100644 --- a/substrate/frame/revive/src/vm/mod.rs +++ b/substrate/frame/revive/src/vm/mod.rs @@ -22,7 +22,7 @@ pub mod evm; pub mod pvm; mod runtime_costs; -pub use runtime_costs::RuntimeCosts; +pub use runtime_costs::{ContractStorageKind, RuntimeCosts}; use crate::{ AccountIdOf, BalanceOf, CodeInfoOf, CodeRemoved, Config, Error, ExecConfig, ExecError, @@ -182,7 +182,7 @@ pub fn code_load_weight(code_len: u32) -> Weight { Token::::weight(&CodeLoadToken { code_len, code_type: BytecodeType::Pvm, - warmth: CodeLoadWarmth::cold_nonrevertible(), + warmth: CodeLoadWarmth::cold_non_revertible(), }) } @@ -441,7 +441,7 @@ mod tests { }; for code_type in [BytecodeType::Pvm, BytecodeType::Evm] { - let cold = weight_of(code_type, CodeLoadWarmth::cold_nonrevertible()); + let cold = weight_of(code_type, CodeLoadWarmth::cold_non_revertible()); let hot = weight_of(code_type, CodeLoadWarmth { info: Warmth::Hot, blob: Warmth::Hot }); let cold_revertible = weight_of( code_type, @@ -473,7 +473,7 @@ mod tests { // load must still bill the full cold base. let info_only = weight_of( code_type, - CodeLoadWarmth { info: Warmth::Hot, blob: Warmth::cold_nonrevertible() }, + CodeLoadWarmth { info: Warmth::Hot, blob: Warmth::cold_non_revertible() }, ); assert!( info_only.proof_size() > hot.proof_size(), diff --git a/substrate/frame/revive/src/vm/pvm.rs b/substrate/frame/revive/src/vm/pvm.rs index 5160c8864017..e9c7b32b6d95 100644 --- a/substrate/frame/revive/src/vm/pvm.rs +++ b/substrate/frame/revive/src/vm/pvm.rs @@ -282,7 +282,7 @@ impl CallType { /// Base cost of the call. fn cost(&self, ext: &impl Ext, callee: &sp_core::H160) -> RuntimeCosts { let access = StateAccess::new(*callee, matches!(self, CallType::DelegateCall)); - RuntimeCosts::CallBase(ext.peek_access(access)) + RuntimeCosts::CallBase(ext.warmth_of(access)) } } diff --git a/substrate/frame/revive/src/vm/runtime_costs.rs b/substrate/frame/revive/src/vm/runtime_costs.rs index 36b944e12303..c49cb6b75568 100644 --- a/substrate/frame/revive/src/vm/runtime_costs.rs +++ b/substrate/frame/revive/src/vm/runtime_costs.rs @@ -17,7 +17,7 @@ use crate::{ Config, - access_list::{StateAccessKind, StorageAccessKind, Warmth}, + access_list::{StateAccessWarmth, Warmth}, limits, metering::Token, weightinfo_extension::OnFinalizeBlockParts, @@ -36,6 +36,27 @@ const GAS_PER_SECOND: u64 = 40_000_000; /// gas. const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND / GAS_PER_SECOND; +/// Classification of a storage access for pricing: persistent (tracked by the +/// access list, so priced by its warmth) or transient (not tracked, own bench). +#[cfg_attr(test, derive(PartialEq, Eq))] +#[derive(Clone, Copy, Debug)] +pub enum ContractStorageKind { + /// Persistent storage, priced by its access-list warmth. + Persistent(Warmth), + /// Transient storage, not tracked by the access list. + Transient, +} + +impl ContractStorageKind { + /// See [`Warmth::non_revertible`]. + pub fn non_revertible(self) -> Self { + match self { + Self::Persistent(warmth) => Self::Persistent(warmth.non_revertible()), + Self::Transient => Self::Transient, + } + } +} + #[cfg_attr(test, derive(Debug, PartialEq, Eq))] #[derive(Copy, Clone)] pub enum RuntimeCosts { @@ -105,17 +126,17 @@ pub enum RuntimeCosts { DepositEvent { num_topic: u32, len: u32 }, /// Weight of `seal_set_storage` / `seal_set_transient_storage`. `kind` picks /// the persistent (cold/hot) or transient bench. - SetStorage { new_bytes: u32, old_bytes: u32, kind: StorageAccessKind }, + SetStorage { new_bytes: u32, old_bytes: u32, kind: ContractStorageKind }, /// Weight of the `clearStorage` precompile / `seal_clear_transient_storage`. - ClearStorage { len: u32, kind: StorageAccessKind }, + ClearStorage { len: u32, kind: ContractStorageKind }, /// Weight of the `containsStorage` precompile / `seal_contains_transient_storage`. - ContainsStorage { len: u32, kind: StorageAccessKind }, + ContainsStorage { len: u32, kind: ContractStorageKind }, /// Weight of `seal_get_storage` / `seal_get_transient_storage`. - GetStorage { len: u32, kind: StorageAccessKind }, + GetStorage { len: u32, kind: ContractStorageKind }, /// Weight of the `takeStorage` precompile / `seal_take_transient_storage`. - TakeStorage { len: u32, kind: StorageAccessKind }, + TakeStorage { len: u32, kind: ContractStorageKind }, /// Base weight of a call-family opcode. - CallBase(StateAccessKind), + CallBase(StateAccessWarmth), /// Weight of calling a precompile. PrecompileBase, /// Weight of calling a precompile that has a contract info. @@ -224,16 +245,16 @@ impl RuntimeCosts { /// Pick the matching storage bench for the access `kind`. fn weight_for_storage_access( - kind: StorageAccessKind, + kind: ContractStorageKind, cold: impl FnOnce() -> Weight, hot: impl FnOnce() -> Weight, transient: impl FnOnce() -> Weight, ) -> Weight { match kind { - StorageAccessKind::Persistent(warmth) => { + ContractStorageKind::Persistent(warmth) => { cold_hot_base::(&[warmth], 1, CostPair { cold, hot }) // probe: the slot }, - StorageAccessKind::Transient => transient(), + ContractStorageKind::Transient => transient(), } } } @@ -378,7 +399,7 @@ impl Token for RuntimeCosts { || cost_storage!(write_transient, seal_take_transient_storage, len), ), CallBase(access_kind) => match access_kind { - StateAccessKind::Call { account, contract_info } => cold_hot_base::( + StateAccessWarmth::Call { account, contract_info } => cold_hot_base::( &[account, contract_info], 3, // probes: address mapping, system account, contract info CostPair { @@ -386,7 +407,7 @@ impl Token for RuntimeCosts { hot: T::WeightInfo::seal_call_hot, }, ), - StateAccessKind::DelegateCall { contract_info } => cold_hot_base::( + StateAccessWarmth::DelegateCall { contract_info } => cold_hot_base::( &[contract_info], 1, // probe: the callee's contract info CostPair { @@ -446,11 +467,11 @@ mod tests { #[test] fn cold_hot_pricing_cold_is_strictly_more_expensive_than_hot() { let len = 64u32; - let cold = StorageAccessKind::Persistent(Warmth::cold_nonrevertible()); - let cold_revertible = StorageAccessKind::Persistent(Warmth::Cold { revertible: true }); - let hot = StorageAccessKind::Persistent(Warmth::Hot); + let cold = ContractStorageKind::Persistent(Warmth::cold_non_revertible()); + let cold_revertible = ContractStorageKind::Persistent(Warmth::Cold { revertible: true }); + let hot = ContractStorageKind::Persistent(Warmth::Hot); - let with_kind = |kind: StorageAccessKind| -> Vec { + let with_kind = |kind: ContractStorageKind| -> Vec { vec![ RuntimeCosts::GetStorage { len, kind }, RuntimeCosts::SetStorage { new_bytes: len, old_bytes: len, kind }, @@ -491,19 +512,19 @@ mod tests { #[test] fn call_base_cold_hot_pricing() { let hot = Warmth::Hot; - let cold = Warmth::cold_nonrevertible(); + let cold = Warmth::cold_non_revertible(); let cold_revertible = Warmth::Cold { revertible: true }; let weight_of = |cost: RuntimeCosts| >::weight(&cost); - let all_hot = weight_of(RuntimeCosts::CallBase(StateAccessKind::Call { + let all_hot = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::Call { account: hot, contract_info: hot, })); - let all_cold = weight_of(RuntimeCosts::CallBase(StateAccessKind::Call { + let all_cold = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::Call { account: cold, contract_info: cold, })); - let mixed = weight_of(RuntimeCosts::CallBase(StateAccessKind::Call { + let mixed = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::Call { account: cold, contract_info: hot, })); @@ -516,7 +537,7 @@ mod tests { assert!(all_cold.proof_size() > 0, "cold call pays proof size: {all_cold:?}"); assert!(mixed.proof_size() > 0, "any cold item prices the full cold base: {mixed:?}",); - let revertible = weight_of(RuntimeCosts::CallBase(StateAccessKind::Call { + let revertible = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::Call { account: cold_revertible, contract_info: cold, })); @@ -525,9 +546,10 @@ mod tests { "a revertible cold touch prepays the rollback: rev={revertible:?} cold={all_cold:?}", ); - let delegate_hot = - weight_of(RuntimeCosts::CallBase(StateAccessKind::DelegateCall { contract_info: hot })); - let delegate_cold = weight_of(RuntimeCosts::CallBase(StateAccessKind::DelegateCall { + let delegate_hot = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::DelegateCall { + contract_info: hot, + })); + let delegate_cold = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::DelegateCall { contract_info: cold, })); assert!( From 9df90a0bc98815192361055b856a2ae09d32d885 Mon Sep 17 00:00:00 2001 From: Marian Radu Date: Tue, 21 Jul 2026 15:46:39 +0300 Subject: [PATCH 9/9] pallet-revive: name the call warmth types after the call opcode --- substrate/frame/revive/src/access_list.rs | 46 +++++++++--------- substrate/frame/revive/src/benchmarking.rs | 4 +- substrate/frame/revive/src/exec.rs | 24 +++++----- substrate/frame/revive/src/exec/mock_ext.rs | 8 ++-- substrate/frame/revive/src/exec/tests.rs | 48 ++++++++----------- .../evm/instructions/contract/call_helpers.rs | 6 +-- substrate/frame/revive/src/vm/pvm.rs | 6 +-- .../frame/revive/src/vm/runtime_costs.rs | 26 +++++----- 8 files changed, 77 insertions(+), 91 deletions(-) diff --git a/substrate/frame/revive/src/access_list.rs b/substrate/frame/revive/src/access_list.rs index c77be38cabf5..e0784463a8be 100644 --- a/substrate/frame/revive/src/access_list.rs +++ b/substrate/frame/revive/src/access_list.rs @@ -149,38 +149,37 @@ impl CodeLoadWarmth { } } -/// A call-family opcode's state access, tracked by the access list. Storage -/// opcodes touch [`AccessEntry::Storage`] directly and are not modelled here. -pub enum StateAccess { +/// A call-family opcode (Call/DelegateCall). +pub enum CallKind { Call { target: H160 }, DelegateCall { target: H160 }, } -impl StateAccess { - /// The state access of a call or delegate call. +impl CallKind { + /// Builds a [`CallKind`] from the given address and delegate flag. pub fn new(target: H160, delegate: bool) -> Self { if delegate { Self::DelegateCall { target } } else { Self::Call { target } } } - /// Maps `warmth_of` over each state item this access reads and collects - /// the results into a [`StateAccessWarmth`]. - pub fn expand(self, mut warmth_of: impl FnMut(AccessEntry) -> Warmth) -> StateAccessWarmth { + /// Maps `warmth_of` over each state item this call reads and collects + /// the results into a [`CallWarmth`]. + pub fn expand(self, mut warmth_of: impl FnMut(AccessEntry) -> Warmth) -> CallWarmth { match self { - Self::Call { target } => StateAccessWarmth::Call { + Self::Call { target } => CallWarmth::Call { account: warmth_of(AccessEntry::Account { address: target }), contract_info: warmth_of(AccessEntry::ContractInfo { address: target }), }, - Self::DelegateCall { target } => StateAccessWarmth::DelegateCall { + Self::DelegateCall { target } => CallWarmth::DelegateCall { contract_info: warmth_of(AccessEntry::ContractInfo { address: target }), }, } } } -/// Warmth of the read state items, one variant per [`StateAccess`] opcode. +/// Warmth of the state items a [`CallKind`] reads, one variant per opcode. #[cfg_attr(test, derive(PartialEq, Eq))] #[derive(Clone, Copy, Debug)] -pub enum StateAccessWarmth { +pub enum CallWarmth { /// A call reads the target's account state and contract metadata. Call { account: Warmth, contract_info: Warmth }, /// A delegate call runs in the caller's context and reads only the @@ -342,18 +341,17 @@ impl AccessList { kind } - /// Warms every state item `access` reads, returning its warmth. Keeps the - /// per-entry `touch` an `AccessList` detail: callers speak opcodes. - pub fn warm(&mut self, access: StateAccess) -> StateAccessWarmth { - access.expand(|entry| self.touch(entry)) + /// Warms every state item this call reads, returning its warmth. + pub fn warm_call(&mut self, kind: CallKind) -> CallWarmth { + kind.expand(|entry| self.touch(entry)) } - /// Non-mutating sibling of [`warm`](Self::warm): the warmth without registering. - pub fn warmth_of(&self, access: StateAccess) -> StateAccessWarmth { - access.expand(|entry| self.peek(&entry)) + /// Non-mutating sibling of [`warm_call`](Self::warm_call): the warmth without registering. + pub fn call_warmth_of(&self, kind: CallKind) -> CallWarmth { + kind.expand(|entry| self.peek(&entry)) } - /// Registers the two entries a code load reads, returning their warmth. + /// Warms the two entries a code load reads, returning their warmth. pub fn warm_code(&mut self, hash: H256) -> CodeLoadWarmth { CodeLoadWarmth { info: self.touch(AccessEntry::CodeInfo { hash }), @@ -486,8 +484,8 @@ mod tests { // The set is below the cap, so peek prices both call entries revertible // cold: it cannot see that touching the first entry fills the cap. assert_eq!( - al.warmth_of(StateAccess::Call { target }), - StateAccessWarmth::Call { + al.call_warmth_of(CallKind::Call { target }), + CallWarmth::Call { account: Warmth::Cold { revertible: true }, contract_info: Warmth::Cold { revertible: true }, }, @@ -496,8 +494,8 @@ mod tests { // The first touch fills the cap, so ContractInfo lands past it: non-revertible. assert_eq!( - al.warm(StateAccess::Call { target }), - StateAccessWarmth::Call { + al.warm_call(CallKind::Call { target }), + CallWarmth::Call { account: Warmth::Cold { revertible: true }, contract_info: Warmth::cold_non_revertible(), }, diff --git a/substrate/frame/revive/src/benchmarking.rs b/substrate/frame/revive/src/benchmarking.rs index 881897b80912..13428a2c8dd7 100644 --- a/substrate/frame/revive/src/benchmarking.rs +++ b/substrate/frame/revive/src/benchmarking.rs @@ -20,7 +20,7 @@ #![cfg(feature = "runtime-benchmarks")] use crate::{ Pallet as Contracts, - access_list::{AccessEntry, AccessList, CodeLoadWarmth, MAX_ACCESS_LIST_ENTRIES, StateAccess}, + access_list::{AccessEntry, AccessList, CallKind, CodeLoadWarmth, MAX_ACCESS_LIST_ENTRIES}, call_builder::{CallSetup, Contract, VmBinaryModule, caller_funding, default_deposit_limit}, evm::{ TransactionLegacyUnsigned, TransactionSigned, TransactionUnsigned, @@ -267,7 +267,7 @@ mod benchmarks { setup.set_origin(ExecOrigin::from_account_id(setup.contract().account_id.clone())); let (mut ext, _) = setup.ext(); - ext.touch_call_target(StateAccess::new(callee_contract.address, $delegate), code_hash); + ext.touch_call_target(CallKind::new(callee_contract.address, $delegate), code_hash); let mut $runtime = pvm::Runtime::<_, [u8]>::new(&mut ext, vec![]); let mut $memory = memory!(callee_bytes, deposit_bytes, value_bytes,); }; diff --git a/substrate/frame/revive/src/exec.rs b/substrate/frame/revive/src/exec.rs index bfe9a0e75113..816979e30b9d 100644 --- a/substrate/frame/revive/src/exec.rs +++ b/substrate/frame/revive/src/exec.rs @@ -19,7 +19,7 @@ use crate::{ AccountInfo, AccountInfoOf, BalanceOf, BalanceWithDust, Code, CodeInfo, CodeInfoOf, CodeRemoved, Config, ContractInfo, ContractStorageKind, Error, Event, ImmutableData, ImmutableDataOf, LOG_TARGET, Pallet as Contracts, RuntimeCosts, TrieId, - access_list::{AccessEntry, AccessList, CodeLoadWarmth, StateAccess, StateAccessWarmth}, + access_list::{AccessEntry, AccessList, CallKind, CallWarmth, CodeLoadWarmth}, address::{self, AddressMapper}, deposit_payment::Deposit as _, evm::{block_storage, fees::InfoT as _, transfer_with_dust}, @@ -554,8 +554,8 @@ pub trait PrecompileExt: sealing::Sealed { /// Non-mutating sibling of `touch_storage_access`. fn peek_storage_access(&self, transient: bool, key: &Key) -> ContractStorageKind; - /// Warmth of the state items `access` reads. - fn warmth_of(&self, access: StateAccess) -> StateAccessWarmth; + /// Warmth of the state items this call reads. + fn call_warmth_of(&self, kind: CallKind) -> CallWarmth; /// Charges `diff` from the meter. fn charge_storage(&mut self, diff: &Diff) -> DispatchResult; @@ -1093,15 +1093,15 @@ where // // Precompiles are not warmed. Reuse the `precompile` lookup for // a plain call; a delegate call reuses its own. - let (access, target_is_precompile) = match &delegated_call { - None => (StateAccess::Call { target: address }, precompile.is_some()), + let (kind, target_is_precompile) = match &delegated_call { + None => (CallKind::Call { target: address }, precompile.is_some()), Some(delegated) => ( - StateAccess::DelegateCall { target: delegated.callee }, + CallKind::DelegateCall { target: delegated.callee }, delegate_precompile.is_some(), ), }; if !target_is_precompile { - access_list.warm(access); + access_list.warm_call(kind); } // which contract info to load is unaffected by the fact if this @@ -1944,10 +1944,10 @@ where self.block_number = block_number; } - /// Touches the access-list entries `access` reads, plus the code, as if the call already ran. + /// Touches the access-list entries the call reads, plus the code, as if the call already ran. #[cfg(feature = "runtime-benchmarks")] - pub(crate) fn touch_call_target(&mut self, access: StateAccess, code_hash: H256) { - self.access_list.warm(access); + pub(crate) fn touch_call_target(&mut self, kind: CallKind, code_hash: H256) { + self.access_list.warm_call(kind); self.access_list.warm_code(code_hash); } @@ -2688,8 +2688,8 @@ where ) } - fn warmth_of(&self, access: StateAccess) -> StateAccessWarmth { - self.access_list.warmth_of(access) + fn call_warmth_of(&self, kind: CallKind) -> CallWarmth { + self.access_list.call_warmth_of(kind) } fn charge_storage(&mut self, diff: &Diff) -> DispatchResult { diff --git a/substrate/frame/revive/src/exec/mock_ext.rs b/substrate/frame/revive/src/exec/mock_ext.rs index de46d0307859..754f5303ba09 100644 --- a/substrate/frame/revive/src/exec/mock_ext.rs +++ b/substrate/frame/revive/src/exec/mock_ext.rs @@ -264,11 +264,11 @@ impl PrecompileExt for MockExt { panic!("MockExt::peek_storage_access") } - fn warmth_of( + fn call_warmth_of( &self, - _opcode: crate::access_list::StateAccess, - ) -> crate::access_list::StateAccessWarmth { - panic!("MockExt::warmth_of") + _kind: crate::access_list::CallKind, + ) -> crate::access_list::CallWarmth { + panic!("MockExt::call_warmth_of") } fn charge_storage(&mut self, _diff: &Diff) -> DispatchResult { diff --git a/substrate/frame/revive/src/exec/tests.rs b/substrate/frame/revive/src/exec/tests.rs index dd40f2eadbba..85283b30a14b 100644 --- a/substrate/frame/revive/src/exec/tests.rs +++ b/substrate/frame/revive/src/exec/tests.rs @@ -24,8 +24,7 @@ use super::*; use crate::{ AddressMapper, Error, Pallet, ReentrancyProtection, access_list::{ - CodeLoadWarmth, MAX_ACCESS_LIST_ENTRIES, MAX_INLINE_KEY_LEN, StateAccess, - StateAccessWarmth, Warmth, + CallKind, CallWarmth, CodeLoadWarmth, MAX_ACCESS_LIST_ENTRIES, MAX_INLINE_KEY_LEN, Warmth, }, exec::ExportedFunction::*, metering::TransactionMeter, @@ -3315,19 +3314,16 @@ fn cold_hot_call_target_warms_across_calls() { let root_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!( - ctx.ext.warmth_of(StateAccess::Call { target: BOB_ADDR }), - StateAccessWarmth::Call { - account: Warmth::Cold { .. }, - contract_info: Warmth::Cold { .. } - }, + ctx.ext.call_warmth_of(CallKind::Call { target: BOB_ADDR }), + CallWarmth::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Cold { .. } }, "an uncalled target starts cold", ); let before = ctx.ext.access_list_metrics(); assert_matches!(run_child_call(ctx.ext, &BOB_ADDR, vec![]), Ok(_)); assert_matches!( - ctx.ext.warmth_of(StateAccess::Call { target: BOB_ADDR }), - StateAccessWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + ctx.ext.call_warmth_of(CallKind::Call { target: BOB_ADDR }), + CallWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, "account state and contract metadata are hot after the first call", ); let mid = ctx.ext.access_list_metrics(); @@ -3380,8 +3376,8 @@ fn cold_hot_depth_denied_call_leaves_target_cold() { let before = ctx.ext.access_list_metrics(); assert_matches!( - ctx.ext.warmth_of(StateAccess::Call { target: DJANGO_ADDR }), - StateAccessWarmth::Call { + ctx.ext.call_warmth_of(CallKind::Call { target: DJANGO_ADDR }), + CallWarmth::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Cold { .. } }, @@ -3407,8 +3403,8 @@ fn cold_hot_depth_denied_call_leaves_target_cold() { "the denied call warms nothing", ); assert_matches!( - ctx.ext.warmth_of(StateAccess::Call { target: DJANGO_ADDR }), - StateAccessWarmth::Call { + ctx.ext.call_warmth_of(CallKind::Call { target: DJANGO_ADDR }), + CallWarmth::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Cold { .. } }, @@ -3492,16 +3488,13 @@ fn cold_hot_caller_touch_outlives_callee_revert() { let root_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!(run_child_call(ctx.ext, &BOB_ADDR, vec![]), Err(_)); assert_matches!( - ctx.ext.warmth_of(StateAccess::Call { target: DJANGO_ADDR }), - StateAccessWarmth::Call { - account: Warmth::Cold { .. }, - contract_info: Warmth::Cold { .. } - }, + ctx.ext.call_warmth_of(CallKind::Call { target: DJANGO_ADDR }), + CallWarmth::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Cold { .. } }, "B's revert drops the warmth of targets B touched", ); assert_matches!( - ctx.ext.warmth_of(StateAccess::Call { target: BOB_ADDR }), - StateAccessWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + ctx.ext.call_warmth_of(CallKind::Call { target: BOB_ADDR }), + CallWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, "the caller's touch of B persists even though B reverted", ); exec_success() @@ -3544,8 +3537,8 @@ fn cold_hot_shared_code_hash_is_hot_across_addresses() { fn cold_hot_first_frame_warms_entry_target() { let root_code_hash = MockLoader::insert(Call, |ctx, _| { assert_matches!( - ctx.ext.warmth_of(StateAccess::Call { target: BOB_ADDR }), - StateAccessWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + ctx.ext.call_warmth_of(CallKind::Call { target: BOB_ADDR }), + CallWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, "the entry target is pre-warmed by the first frame", ); exec_success() @@ -3565,11 +3558,8 @@ fn cold_hot_plain_account_warms_then_code_loads_cold() { let root_code_hash = MockLoader::insert(Call, move |ctx, _| { assert_matches!( - ctx.ext.warmth_of(StateAccess::Call { target: DJANGO_ADDR }), - StateAccessWarmth::Call { - account: Warmth::Cold { .. }, - contract_info: Warmth::Cold { .. } - }, + ctx.ext.call_warmth_of(CallKind::Call { target: DJANGO_ADDR }), + CallWarmth::Call { account: Warmth::Cold { .. }, contract_info: Warmth::Cold { .. } }, "an uncalled target starts cold", ); @@ -3577,8 +3567,8 @@ fn cold_hot_plain_account_warms_then_code_loads_cold() { let before = ctx.ext.access_list_metrics(); assert_matches!(run_child_call(ctx.ext, &DJANGO_ADDR, vec![]), Ok(_)); assert_matches!( - ctx.ext.warmth_of(StateAccess::Call { target: DJANGO_ADDR }), - StateAccessWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, + ctx.ext.call_warmth_of(CallKind::Call { target: DJANGO_ADDR }), + CallWarmth::Call { account: Warmth::Hot, contract_info: Warmth::Hot }, "a call to a plain account warms it", ); let after_plain = ctx.ext.access_list_metrics(); diff --git a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs index 6e878f22589c..a66b7a31afc2 100644 --- a/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs +++ b/substrate/frame/revive/src/vm/evm/instructions/contract/call_helpers.rs @@ -17,7 +17,7 @@ use crate::{ Pallet, RuntimeCosts, - access_list::StateAccess, + access_list::CallKind, precompiles::{All as AllPrecompiles, Precompiles}, vm::{ Ext, @@ -85,8 +85,8 @@ pub fn charge_call_gas<'a, E: Ext>( }, None => { // Regular CALL / DELEGATECALL base cost / CALLCODE not supported. - let access = StateAccess::new(callee, scheme.is_delegate_call()); - let cost = RuntimeCosts::CallBase(interpreter.ext.warmth_of(access)); + let kind = CallKind::new(callee, scheme.is_delegate_call()); + let cost = RuntimeCosts::CallBase(interpreter.ext.call_warmth_of(kind)); interpreter.ext.charge_or_halt(cost)?; interpreter diff --git a/substrate/frame/revive/src/vm/pvm.rs b/substrate/frame/revive/src/vm/pvm.rs index e9c7b32b6d95..8132d4653b7d 100644 --- a/substrate/frame/revive/src/vm/pvm.rs +++ b/substrate/frame/revive/src/vm/pvm.rs @@ -21,7 +21,7 @@ pub mod env; use crate::{ Code, Config, Error, LOG_TARGET, Pallet, ReentrancyProtection, RuntimeCosts, SENTINEL, - access_list::StateAccess, + access_list::CallKind, exec::{CallResources, ExecError, ExecResult, Ext, Key}, limits, metering::ChargedAmount, @@ -281,8 +281,8 @@ enum CallType { impl CallType { /// Base cost of the call. fn cost(&self, ext: &impl Ext, callee: &sp_core::H160) -> RuntimeCosts { - let access = StateAccess::new(*callee, matches!(self, CallType::DelegateCall)); - RuntimeCosts::CallBase(ext.warmth_of(access)) + let kind = CallKind::new(*callee, matches!(self, CallType::DelegateCall)); + RuntimeCosts::CallBase(ext.call_warmth_of(kind)) } } diff --git a/substrate/frame/revive/src/vm/runtime_costs.rs b/substrate/frame/revive/src/vm/runtime_costs.rs index c49cb6b75568..4da37ea7cc29 100644 --- a/substrate/frame/revive/src/vm/runtime_costs.rs +++ b/substrate/frame/revive/src/vm/runtime_costs.rs @@ -17,7 +17,7 @@ use crate::{ Config, - access_list::{StateAccessWarmth, Warmth}, + access_list::{CallWarmth, Warmth}, limits, metering::Token, weightinfo_extension::OnFinalizeBlockParts, @@ -136,7 +136,7 @@ pub enum RuntimeCosts { /// Weight of the `takeStorage` precompile / `seal_take_transient_storage`. TakeStorage { len: u32, kind: ContractStorageKind }, /// Base weight of a call-family opcode. - CallBase(StateAccessWarmth), + CallBase(CallWarmth), /// Weight of calling a precompile. PrecompileBase, /// Weight of calling a precompile that has a contract info. @@ -399,7 +399,7 @@ impl Token for RuntimeCosts { || cost_storage!(write_transient, seal_take_transient_storage, len), ), CallBase(access_kind) => match access_kind { - StateAccessWarmth::Call { account, contract_info } => cold_hot_base::( + CallWarmth::Call { account, contract_info } => cold_hot_base::( &[account, contract_info], 3, // probes: address mapping, system account, contract info CostPair { @@ -407,7 +407,7 @@ impl Token for RuntimeCosts { hot: T::WeightInfo::seal_call_hot, }, ), - StateAccessWarmth::DelegateCall { contract_info } => cold_hot_base::( + CallWarmth::DelegateCall { contract_info } => cold_hot_base::( &[contract_info], 1, // probe: the callee's contract info CostPair { @@ -516,15 +516,15 @@ mod tests { let cold_revertible = Warmth::Cold { revertible: true }; let weight_of = |cost: RuntimeCosts| >::weight(&cost); - let all_hot = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::Call { + let all_hot = weight_of(RuntimeCosts::CallBase(CallWarmth::Call { account: hot, contract_info: hot, })); - let all_cold = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::Call { + let all_cold = weight_of(RuntimeCosts::CallBase(CallWarmth::Call { account: cold, contract_info: cold, })); - let mixed = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::Call { + let mixed = weight_of(RuntimeCosts::CallBase(CallWarmth::Call { account: cold, contract_info: hot, })); @@ -537,7 +537,7 @@ mod tests { assert!(all_cold.proof_size() > 0, "cold call pays proof size: {all_cold:?}"); assert!(mixed.proof_size() > 0, "any cold item prices the full cold base: {mixed:?}",); - let revertible = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::Call { + let revertible = weight_of(RuntimeCosts::CallBase(CallWarmth::Call { account: cold_revertible, contract_info: cold, })); @@ -546,12 +546,10 @@ mod tests { "a revertible cold touch prepays the rollback: rev={revertible:?} cold={all_cold:?}", ); - let delegate_hot = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::DelegateCall { - contract_info: hot, - })); - let delegate_cold = weight_of(RuntimeCosts::CallBase(StateAccessWarmth::DelegateCall { - contract_info: cold, - })); + let delegate_hot = + weight_of(RuntimeCosts::CallBase(CallWarmth::DelegateCall { contract_info: hot })); + let delegate_cold = + weight_of(RuntimeCosts::CallBase(CallWarmth::DelegateCall { contract_info: cold })); assert!( delegate_cold.ref_time() >= delegate_hot.ref_time(), "cold delegate call must not be cheaper than hot: cold={delegate_cold:?} hot={delegate_hot:?}",