Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

contracts: Use proof_size from benchmarks #13268

Merged
merged 23 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
76484a6
Avoid reading contract code when it is supplied in the extrinsic
athei Jan 29, 2023
f5825c8
Remove custom proof size injection from schedule
athei Jan 29, 2023
719a72e
Set benchmarks pov_mode to Measure
athei Jan 29, 2023
5234f15
Reduce overestimation of code size on re-instrument
athei Jan 29, 2023
9631500
Merge branch 'master' of https://github.com/paritytech/substrate into…
Jan 29, 2023
ad417a2
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Jan 30, 2023
8954917
Do not override proof size from benchmark
athei Jan 30, 2023
1d76cb1
Do not charge proof size for basic block
athei Jan 30, 2023
3cdf92a
Incrase gas limit for tests
athei Jan 30, 2023
a53f9de
Fix deletion queue to also use `proof_size`
athei Jan 30, 2023
5003631
Fix tests
athei Jan 30, 2023
c1083ca
Merge branch 'master' into at/contracts-proof-size
athei Feb 1, 2023
d81d8c2
Update frame/contracts/src/schedule.rs
athei Feb 2, 2023
e45af85
Merge remote-tracking branch 'origin/master' into at/contracts-proof-…
Feb 2, 2023
df3e0b8
Merge branch 'master' into at/contracts-proof-size
athei Feb 4, 2023
9850fe0
Fix wrong schedule macro invocations
athei Feb 4, 2023
89824cb
Remove stale docs
athei Feb 4, 2023
6aff0d6
Merge branch 'master' into at/contracts-proof-size
athei Feb 14, 2023
f21fa90
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Feb 14, 2023
2e0818a
Handle zero components
athei Feb 15, 2023
9b43b15
Merge branch 'master' of https://github.com/paritytech/substrate into…
Feb 15, 2023
eef36ee
".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts
Feb 15, 2023
606df89
Fix instruction weight
athei Feb 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 73 additions & 75 deletions frame/contracts/src/benchmarking/mod.rs

Large diffs are not rendered by default.

173 changes: 71 additions & 102 deletions frame/contracts/src/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ macro_rules! call_zero {

macro_rules! cost_args {
($name:ident, $( $arg: expr ),+) => {
(T::WeightInfo::$name($( $arg ),+).saturating_sub(call_zero!($name, $( $arg ),+))).ref_time()
(T::WeightInfo::$name($( $arg ),+).saturating_sub(call_zero!($name, $( $arg ),+)))
}
}

Expand All @@ -459,7 +459,7 @@ macro_rules! cost_batched_args {

macro_rules! cost_instr_no_params_with_batch_size {
($name:ident, $batch_size:expr) => {
(cost_args!($name, 1) / u64::from($batch_size)) as u32
(cost_args!($name, 1).ref_time() / u64::from($batch_size)) as u32
};
}

Expand Down Expand Up @@ -514,12 +514,6 @@ macro_rules! cost_byte_batched {
};
}

macro_rules! to_weight {
($ref_time:expr $(, $proof_size:expr )?) => {
Weight::from_ref_time($ref_time)$(.set_proof_size($proof_size))?
};
}

impl Default for Limits {
fn default() -> Self {
Self {
Expand Down Expand Up @@ -554,8 +548,8 @@ impl<T: Config> Default for InstructionWeights<T> {
br_table_per_entry: cost_instr!(instr_br_table_per_entry, 0),
call: cost_instr!(instr_call, 2),
call_indirect: cost_instr!(instr_call_indirect, 3),
call_indirect_per_param: cost_instr!(instr_call_indirect_per_param, 1),
call_per_local: cost_instr!(instr_call_per_local, 1),
call_indirect_per_param: cost_instr!(instr_call_indirect_per_param, 0),
call_per_local: cost_instr!(instr_call_per_local, 0),
local_get: cost_instr!(instr_local_get, 1),
local_set: cost_instr!(instr_local_set, 1),
local_tee: cost_instr!(instr_local_tee, 2),
Expand Down Expand Up @@ -601,116 +595,91 @@ impl<T: Config> Default for InstructionWeights<T> {
}

impl<T: Config> Default for HostFnWeights<T> {
/// PoV should contain all trie nodes that are read during state transition (i.e. block
/// production). Hence we need to charge the `proof_size` weight for every host function which
/// reads storage, namely:
/// - get_storage,
/// - take_storage,
/// - contains_storage,
/// - clear_storage,
/// - set_storage.
///
/// The last two functions write to storage, but they also do read storage in order to return
/// the size of the pre-existed value. Till we have PoV benchmarks implemented, we approximate
/// `proof_size` as being equal to the size of storage read.
fn default() -> Self {
Self {
caller: to_weight!(cost_batched!(seal_caller)),
is_contract: to_weight!(cost_batched!(seal_is_contract)),
code_hash: to_weight!(cost_batched!(seal_code_hash)),
own_code_hash: to_weight!(cost_batched!(seal_own_code_hash)),
caller_is_origin: to_weight!(cost_batched!(seal_caller_is_origin)),
address: to_weight!(cost_batched!(seal_address)),
gas_left: to_weight!(cost_batched!(seal_gas_left)),
balance: to_weight!(cost_batched!(seal_balance)),
value_transferred: to_weight!(cost_batched!(seal_value_transferred)),
minimum_balance: to_weight!(cost_batched!(seal_minimum_balance)),
block_number: to_weight!(cost_batched!(seal_block_number)),
now: to_weight!(cost_batched!(seal_now)),
weight_to_fee: to_weight!(cost_batched!(seal_weight_to_fee)),
gas: to_weight!(cost_batched!(seal_gas)),
input: to_weight!(cost_batched!(seal_input)),
input_per_byte: to_weight!(cost_byte_batched!(seal_input_per_kb)),
r#return: to_weight!(cost!(seal_return)),
return_per_byte: to_weight!(cost_byte!(seal_return_per_kb)),
terminate: to_weight!(cost!(seal_terminate)),
random: to_weight!(cost_batched!(seal_random)),
deposit_event: to_weight!(cost_batched!(seal_deposit_event)),
deposit_event_per_topic: to_weight!(cost_batched_args!(
seal_deposit_event_per_topic_and_kb,
1,
0
)),
deposit_event_per_byte: to_weight!(cost_byte_batched_args!(
caller: cost_batched!(seal_caller),
is_contract: cost_batched!(seal_is_contract),
code_hash: cost_batched!(seal_code_hash),
own_code_hash: cost_batched!(seal_own_code_hash),
caller_is_origin: cost_batched!(seal_caller_is_origin),
address: cost_batched!(seal_address),
gas_left: cost_batched!(seal_gas_left),
balance: cost_batched!(seal_balance),
value_transferred: cost_batched!(seal_value_transferred),
minimum_balance: cost_batched!(seal_minimum_balance),
block_number: cost_batched!(seal_block_number),
now: cost_batched!(seal_now),
weight_to_fee: cost_batched!(seal_weight_to_fee),
// Manually remove proof size from basic block cost.
//
// Due to imperfect benchmarking some host functions incur a small
// amount of proof size. Usually this is ok. However, charging a basic block is such
// a frequent operation that this would be a vast overestimation.
gas: cost_batched!(seal_gas).set_proof_size(0),
input: cost_batched!(seal_input),
input_per_byte: cost_byte_batched!(seal_input_per_kb),
r#return: cost!(seal_return),
return_per_byte: cost_byte!(seal_return_per_kb),
terminate: cost!(seal_terminate),
random: cost_batched!(seal_random),
deposit_event: cost_batched!(seal_deposit_event),
deposit_event_per_topic: cost_batched_args!(seal_deposit_event_per_topic_and_kb, 1, 0),
deposit_event_per_byte: cost_byte_batched_args!(
seal_deposit_event_per_topic_and_kb,
0,
1
)),
debug_message: to_weight!(cost_batched!(seal_debug_message)),
debug_message_per_byte: to_weight!(cost_byte!(seal_debug_message_per_kb)),
set_storage: to_weight!(cost_batched!(seal_set_storage), 1024u64),
set_code_hash: to_weight!(cost_batched!(seal_set_code_hash)),
set_storage_per_new_byte: to_weight!(cost_byte_batched!(seal_set_storage_per_new_kb)),
set_storage_per_old_byte: to_weight!(
cost_byte_batched!(seal_set_storage_per_old_kb),
1u64
),
clear_storage: to_weight!(cost_batched!(seal_clear_storage), 1024u64),
clear_storage_per_byte: to_weight!(cost_byte_batched!(seal_clear_storage_per_kb), 1u64),
contains_storage: to_weight!(cost_batched!(seal_contains_storage), 1024u64),
contains_storage_per_byte: to_weight!(
cost_byte_batched!(seal_contains_storage_per_kb),
1u64
),
get_storage: to_weight!(cost_batched!(seal_get_storage), 1024u64),
get_storage_per_byte: to_weight!(cost_byte_batched!(seal_get_storage_per_kb), 1u64),
take_storage: to_weight!(cost_batched!(seal_take_storage), 1024u64),
take_storage_per_byte: to_weight!(cost_byte_batched!(seal_take_storage_per_kb), 1u64),
transfer: to_weight!(cost_batched!(seal_transfer)),
call: to_weight!(cost_batched!(seal_call)),
delegate_call: to_weight!(cost_batched!(seal_delegate_call)),
call_transfer_surcharge: to_weight!(cost_batched_args!(
seal_call_per_transfer_clone_kb,
1,
0
)),
call_per_cloned_byte: to_weight!(cost_batched_args!(
seal_call_per_transfer_clone_kb,
0,
1
)),
instantiate: to_weight!(cost_batched!(seal_instantiate)),
instantiate_transfer_surcharge: to_weight!(cost_byte_batched_args!(
debug_message: cost_batched!(seal_debug_message),
debug_message_per_byte: cost_byte!(seal_debug_message_per_kb),
set_storage: cost_batched!(seal_set_storage),
set_code_hash: cost_batched!(seal_set_code_hash),
set_storage_per_new_byte: cost_byte_batched!(seal_set_storage_per_new_kb),
set_storage_per_old_byte: cost_byte_batched!(seal_set_storage_per_old_kb),
clear_storage: cost_batched!(seal_clear_storage),
clear_storage_per_byte: cost_byte_batched!(seal_clear_storage_per_kb),
contains_storage: cost_batched!(seal_contains_storage),
contains_storage_per_byte: cost_byte_batched!(seal_contains_storage_per_kb),
get_storage: cost_batched!(seal_get_storage),
get_storage_per_byte: cost_byte_batched!(seal_get_storage_per_kb),
take_storage: cost_batched!(seal_take_storage),
take_storage_per_byte: cost_byte_batched!(seal_take_storage_per_kb),
transfer: cost_batched!(seal_transfer),
call: cost_batched!(seal_call),
delegate_call: cost_batched!(seal_delegate_call),
call_transfer_surcharge: cost_batched_args!(seal_call_per_transfer_clone_kb, 1, 0),
call_per_cloned_byte: cost_byte_batched_args!(seal_call_per_transfer_clone_kb, 0, 1),
instantiate: cost_batched!(seal_instantiate),
instantiate_transfer_surcharge: cost_batched_args!(
seal_instantiate_per_transfer_input_salt_kb,
1,
0,
0
)),
instantiate_per_input_byte: to_weight!(cost_byte_batched_args!(
),
instantiate_per_input_byte: cost_byte_batched_args!(
seal_instantiate_per_transfer_input_salt_kb,
0,
1,
0
)),
instantiate_per_salt_byte: to_weight!(cost_byte_batched_args!(
),
instantiate_per_salt_byte: cost_byte_batched_args!(
seal_instantiate_per_transfer_input_salt_kb,
0,
0,
1
)),
hash_sha2_256: to_weight!(cost_batched!(seal_hash_sha2_256)),
hash_sha2_256_per_byte: to_weight!(cost_byte_batched!(seal_hash_sha2_256_per_kb)),
hash_keccak_256: to_weight!(cost_batched!(seal_hash_keccak_256)),
hash_keccak_256_per_byte: to_weight!(cost_byte_batched!(seal_hash_keccak_256_per_kb)),
hash_blake2_256: to_weight!(cost_batched!(seal_hash_blake2_256)),
hash_blake2_256_per_byte: to_weight!(cost_byte_batched!(seal_hash_blake2_256_per_kb)),
hash_blake2_128: to_weight!(cost_batched!(seal_hash_blake2_128)),
hash_blake2_128_per_byte: to_weight!(cost_byte_batched!(seal_hash_blake2_128_per_kb)),
ecdsa_recover: to_weight!(cost_batched!(seal_ecdsa_recover)),
ecdsa_to_eth_address: to_weight!(cost_batched!(seal_ecdsa_to_eth_address)),
reentrance_count: to_weight!(cost_batched!(seal_reentrance_count)),
account_reentrance_count: to_weight!(cost_batched!(seal_account_reentrance_count)),
instantiation_nonce: to_weight!(cost_batched!(seal_instantiation_nonce)),
),
hash_sha2_256: cost_batched!(seal_hash_sha2_256),
hash_sha2_256_per_byte: cost_byte_batched!(seal_hash_sha2_256_per_kb),
hash_keccak_256: cost_batched!(seal_hash_keccak_256),
hash_keccak_256_per_byte: cost_byte_batched!(seal_hash_keccak_256_per_kb),
hash_blake2_256: cost_batched!(seal_hash_blake2_256),
hash_blake2_256_per_byte: cost_byte_batched!(seal_hash_blake2_256_per_kb),
hash_blake2_128: cost_batched!(seal_hash_blake2_128),
hash_blake2_128_per_byte: cost_byte_batched!(seal_hash_blake2_128_per_kb),
ecdsa_recover: cost_batched!(seal_ecdsa_recover),
ecdsa_to_eth_address: cost_batched!(seal_ecdsa_to_eth_address),
reentrance_count: cost_batched!(seal_reentrance_count),
account_reentrance_count: cost_batched!(seal_account_reentrance_count),
instantiation_nonce: cost_batched!(seal_instantiation_nonce),
_phantom: PhantomData,
}
}
Expand Down
17 changes: 6 additions & 11 deletions frame/contracts/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,23 +245,21 @@ impl<T: Config> Storage<T> {
/// Calculates the weight that is necessary to remove one key from the trie and how many
/// of those keys can be deleted from the deletion queue given the supplied queue length
/// and weight limit.
pub fn deletion_budget(queue_len: usize, weight_limit: Weight) -> (u64, u32) {
pub fn deletion_budget(queue_len: usize, weight_limit: Weight) -> (Weight, u32) {
let base_weight = T::WeightInfo::on_process_deletion_queue_batch();
let weight_per_queue_item = T::WeightInfo::on_initialize_per_queue_item(1) -
T::WeightInfo::on_initialize_per_queue_item(0);
let weight_per_key = (T::WeightInfo::on_initialize_per_trie_key(1) -
T::WeightInfo::on_initialize_per_trie_key(0))
.ref_time();
let weight_per_key = T::WeightInfo::on_initialize_per_trie_key(1) -
T::WeightInfo::on_initialize_per_trie_key(0);
let decoding_weight = weight_per_queue_item.saturating_mul(queue_len as u64);

// `weight_per_key` being zero makes no sense and would constitute a failure to
// benchmark properly. We opt for not removing any keys at all in this case.
let key_budget = weight_limit
.saturating_sub(base_weight)
.saturating_sub(decoding_weight)
.checked_div(weight_per_key)
.unwrap_or(Weight::zero())
.ref_time() as u32;
.checked_div_per_component(&weight_per_key)
.unwrap_or(0) as u32;

(weight_per_key, key_budget)
}
Expand Down Expand Up @@ -306,10 +304,7 @@ impl<T: Config> Storage<T> {
}

<DeletionQueue<T>>::put(queue);
let ref_time_weight = weight_limit
.ref_time()
.saturating_sub(weight_per_key.saturating_mul(u64::from(remaining_key_budget)));
Weight::from_ref_time(ref_time_weight)
weight_limit.saturating_sub(weight_per_key.saturating_mul(u64::from(remaining_key_budget)))
}

/// Generates a unique trie id by returning `hash(account_id ++ nonce)`.
Expand Down
8 changes: 4 additions & 4 deletions frame/contracts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ impl Contains<RuntimeCall> for TestFilter {
}

parameter_types! {
pub const DeletionWeightLimit: Weight = Weight::from_ref_time(500_000_000_000);
pub const DeletionWeightLimit: Weight = GAS_LIMIT;
pub static UnstableInterface: bool = true;
}

Expand Down Expand Up @@ -416,7 +416,7 @@ pub const BOB: AccountId32 = AccountId32::new([2u8; 32]);
pub const CHARLIE: AccountId32 = AccountId32::new([3u8; 32]);
pub const DJANGO: AccountId32 = AccountId32::new([4u8; 32]);

pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 512 * 1024);
pub const GAS_LIMIT: Weight = Weight::from_parts(100_000_000_000, 3 * 1024 * 1024);

pub struct ExtBuilder {
existential_deposit: u64,
Expand Down Expand Up @@ -2322,7 +2322,7 @@ fn lazy_removal_does_no_run_on_low_remaining_weight() {
fn lazy_removal_does_not_use_all_weight() {
let (code, _hash) = compile_module::<Test>("self_destruct").unwrap();

let weight_limit = Weight::from_ref_time(5_000_000_000);
let weight_limit = Weight::from_parts(5_000_000_000, 100 * 1024);
let mut ext = ExtBuilder::default().existential_deposit(50).build();

let (trie, vals, weight_per_key) = ext.execute_with(|| {
Expand Down Expand Up @@ -2396,7 +2396,7 @@ fn lazy_removal_does_not_use_all_weight() {
let weight_used = Storage::<Test>::process_deletion_queue_batch(weight_limit);

// We have one less key in our trie than our weight limit suffices for
assert_eq!(weight_used, weight_limit - Weight::from_ref_time(weight_per_key));
assert_eq!(weight_used, weight_limit - weight_per_key);

// All the keys are removed
for val in vals {
Expand Down
Loading