mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-09 20:11:09 +00:00
contracts: Use proof_size from benchmarks (#13268)
* Avoid reading contract code when it is supplied in the extrinsic * Remove custom proof size injection from schedule * Set benchmarks pov_mode to Measure * Reduce overestimation of code size on re-instrument * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * Do not override proof size from benchmark * Do not charge proof size for basic block * Incrase gas limit for tests * Fix deletion queue to also use `proof_size` * Fix tests * Update frame/contracts/src/schedule.rs Co-authored-by: Cyrill Leutwiler <bigcyrill@hotmail.com> * Fix wrong schedule macro invocations * Remove stale docs * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * Handle zero components * ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts * Fix instruction weight --------- Co-authored-by: command-bot <> Co-authored-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
committed by
GitHub
parent
3c0d8fe149
commit
1c04ab0f6f
@@ -205,13 +205,13 @@ benchmarks! {
|
||||
}
|
||||
|
||||
// The base weight consumed on processing contracts deletion queue.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
on_process_deletion_queue_batch {}: {
|
||||
Storage::<T>::process_deletion_queue_batch(Weight::MAX)
|
||||
}
|
||||
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
on_initialize_per_trie_key {
|
||||
let k in 0..1024;
|
||||
let instance = Contract::<T>::with_storage(WasmModule::dummy(), k, T::Schedule::get().limits.payload_len)?;
|
||||
@@ -220,7 +220,7 @@ benchmarks! {
|
||||
Storage::<T>::process_deletion_queue_batch(Weight::MAX)
|
||||
}
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
on_initialize_per_queue_item {
|
||||
let q in 0..1024.min(T::DeletionQueueDepth::get());
|
||||
for i in 0 .. q {
|
||||
@@ -235,7 +235,7 @@ benchmarks! {
|
||||
// This benchmarks the additional weight that is charged when a contract is executed the
|
||||
// first time after a new schedule was deployed: For every new schedule a contract needs
|
||||
// to re-run the instrumentation once.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
reinstrument {
|
||||
let c in 0 .. Perbill::from_percent(49).mul_ceil(T::MaxCodeLen::get());
|
||||
let WasmModule { code, hash, .. } = WasmModule::<T>::sized(c, Location::Call);
|
||||
@@ -252,7 +252,7 @@ benchmarks! {
|
||||
// is responsible. This is achieved by generating all code to the `deploy` function
|
||||
// which is in the wasm module but not executed on `call`.
|
||||
// The results are supposed to be used as `call_with_code_kb(c) - call_with_code_kb(0)`.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
call_with_code_per_byte {
|
||||
let c in 0 .. T::MaxCodeLen::get();
|
||||
let instance = Contract::<T>::with_caller(
|
||||
@@ -278,7 +278,7 @@ benchmarks! {
|
||||
//
|
||||
// We cannot let `c` grow to the maximum code size because the code is not allowed
|
||||
// to be larger than the maximum size **after instrumentation**.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
instantiate_with_code {
|
||||
let c in 0 .. Perbill::from_percent(49).mul_ceil(T::MaxCodeLen::get());
|
||||
let i in 0 .. code::max_pages::<T>() * 64 * 1024;
|
||||
@@ -310,7 +310,7 @@ benchmarks! {
|
||||
// Instantiate uses a dummy contract constructor to measure the overhead of the instantiate.
|
||||
// `i`: Size of the input in kilobytes.
|
||||
// `s`: Size of the salt in kilobytes.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
instantiate {
|
||||
let i in 0 .. code::max_pages::<T>() * 64 * 1024;
|
||||
let s in 0 .. code::max_pages::<T>() * 64 * 1024;
|
||||
@@ -342,7 +342,7 @@ benchmarks! {
|
||||
// part of `seal_input`. The costs for invoking a contract of a specific size are not part
|
||||
// of this benchmark because we cannot know the size of the contract when issuing a call
|
||||
// transaction. See `invoke_per_code_kb` for this.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
call {
|
||||
let data = vec![42u8; 1024];
|
||||
let instance = Contract::<T>::with_caller(
|
||||
@@ -375,7 +375,7 @@ benchmarks! {
|
||||
//
|
||||
// We cannot let `c` grow to the maximum code size because the code is not allowed
|
||||
// to be larger than the maximum size **after instrumentation**.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
upload_code {
|
||||
let c in 0 .. Perbill::from_percent(49).mul_ceil(T::MaxCodeLen::get());
|
||||
let caller = whitelisted_caller();
|
||||
@@ -392,7 +392,7 @@ benchmarks! {
|
||||
// Removing code does not depend on the size of the contract because all the information
|
||||
// needed to verify the removal claim (refcount, owner) is stored in a separate storage
|
||||
// item (`OwnerInfoOf`).
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
remove_code {
|
||||
let caller = whitelisted_caller();
|
||||
T::Currency::make_free_balance_be(&caller, caller_funding::<T>());
|
||||
@@ -409,7 +409,7 @@ benchmarks! {
|
||||
assert!(<Contract<T>>::code_removed(&hash));
|
||||
}
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
set_code {
|
||||
let instance = <Contract<T>>::with_caller(
|
||||
whitelisted_caller(), WasmModule::dummy(), vec![],
|
||||
@@ -424,7 +424,7 @@ benchmarks! {
|
||||
assert_eq!(instance.info()?.code_hash, hash);
|
||||
}
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_caller {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let instance = Contract::<T>::new(WasmModule::getter(
|
||||
@@ -433,7 +433,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_is_contract {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let accounts = (0 .. r * API_BENCHMARK_BATCH_SIZE)
|
||||
@@ -471,7 +471,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_code_hash {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let accounts = (0 .. r * API_BENCHMARK_BATCH_SIZE)
|
||||
@@ -517,7 +517,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_own_code_hash {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let instance = Contract::<T>::new(WasmModule::getter(
|
||||
@@ -526,7 +526,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_caller_is_origin {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -547,7 +547,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_address {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let instance = Contract::<T>::new(WasmModule::getter(
|
||||
@@ -556,7 +556,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_gas_left {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let instance = Contract::<T>::new(WasmModule::getter(
|
||||
@@ -565,7 +565,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_balance {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let instance = Contract::<T>::new(WasmModule::getter(
|
||||
@@ -574,7 +574,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_value_transferred {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let instance = Contract::<T>::new(WasmModule::getter(
|
||||
@@ -583,7 +583,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_minimum_balance {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let instance = Contract::<T>::new(WasmModule::getter(
|
||||
@@ -592,7 +592,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_block_number {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let instance = Contract::<T>::new(WasmModule::getter(
|
||||
@@ -601,7 +601,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_now {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let instance = Contract::<T>::new(WasmModule::getter(
|
||||
@@ -610,7 +610,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_weight_to_fee {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let pages = code::max_pages::<T>();
|
||||
@@ -638,7 +638,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_gas {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -659,7 +659,7 @@ benchmarks! {
|
||||
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_input {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -687,7 +687,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_input_per_kb {
|
||||
let n in 0 .. code::max_pages::<T>() * 64;
|
||||
let pages = code::max_pages::<T>();
|
||||
@@ -721,7 +721,7 @@ benchmarks! {
|
||||
// We cannot call `seal_return` multiple times. Therefore our weight determination is not
|
||||
// as precise as with other APIs. Because this function can only be called once per
|
||||
// contract it cannot be used as an attack vector.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_return {
|
||||
let r in 0 .. 1;
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -744,7 +744,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_return_per_kb {
|
||||
let n in 0 .. code::max_pages::<T>() * 64;
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -769,7 +769,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// The same argument as for `seal_return` is true here.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_terminate {
|
||||
let r in 0 .. 1;
|
||||
let beneficiary = account::<T::AccountId>("beneficiary", 0, 0);
|
||||
@@ -812,7 +812,7 @@ benchmarks! {
|
||||
// We benchmark only for the maximum subject length. We assume that this is some lowish
|
||||
// number (< 1 KB). Therefore we are not overcharging too much in case a smaller subject is
|
||||
// used.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_random {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let pages = code::max_pages::<T>();
|
||||
@@ -847,7 +847,7 @@ benchmarks! {
|
||||
|
||||
// Overhead of calling the function without any topic.
|
||||
// We benchmark for the worst case (largest event).
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_deposit_event {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -874,7 +874,7 @@ benchmarks! {
|
||||
// Benchmark the overhead that topics generate.
|
||||
// `t`: Number of topics
|
||||
// `n`: Size of event payload in kb
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_deposit_event_per_topic_and_kb {
|
||||
let t in 0 .. T::Schedule::get().limits.event_topics;
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 1024;
|
||||
@@ -913,7 +913,7 @@ benchmarks! {
|
||||
// Benchmark debug_message call with zero input data.
|
||||
// Whereas this function is used in RPC mode only, it still should be secured
|
||||
// against an excessive use.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_debug_message {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -1003,7 +1003,7 @@ benchmarks! {
|
||||
// because re-writing at an existing key is always more expensive than writing
|
||||
// it at a virgin key.
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_set_storage {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES/2;
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1052,7 +1052,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_set_storage_per_new_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1101,7 +1101,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_set_storage_per_old_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1154,7 +1154,7 @@ benchmarks! {
|
||||
// deleting a non existing key. We generate keys of a maximum length, and have to
|
||||
// reduce batch size in order to make resulting contract code size less than MaxCodeLen.
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_clear_storage {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES/2;
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1202,7 +1202,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_clear_storage_per_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1250,7 +1250,7 @@ benchmarks! {
|
||||
|
||||
// We make sure that all storage accesses are to unique keys.
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_get_storage {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES/2;
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1305,7 +1305,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_get_storage_per_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1361,7 +1361,7 @@ benchmarks! {
|
||||
|
||||
// We make sure that all storage accesses are to unique keys.
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_contains_storage {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES/2;
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1410,7 +1410,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_contains_storage_per_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1458,7 +1458,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_take_storage {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES/2;
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1513,7 +1513,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[skip_meta]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_take_storage_per_kb {
|
||||
let n in 0 .. T::Schedule::get().limits.payload_len / 2048; // half of the max payload_len in kb
|
||||
let max_key_len = T::MaxStorageKeyLen::get();
|
||||
@@ -1568,7 +1568,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// We transfer to unique accounts.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_transfer {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let accounts = (0..r * API_BENCHMARK_BATCH_SIZE)
|
||||
@@ -1622,7 +1622,7 @@ benchmarks! {
|
||||
}
|
||||
|
||||
// We call unique accounts.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_call {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let dummy_code = WasmModule::<T>::dummy_with_bytes(0);
|
||||
@@ -1681,7 +1681,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_delegate_call {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let hashes = (0..r * API_BENCHMARK_BATCH_SIZE)
|
||||
@@ -1734,7 +1734,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller);
|
||||
}: call(origin, callee, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_call_per_transfer_clone_kb {
|
||||
let t in 0 .. 1;
|
||||
let c in 0 .. code::max_pages::<T>() * 64;
|
||||
@@ -1793,7 +1793,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, bytes)
|
||||
|
||||
// We assume that every instantiate sends at least the minimum balance.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_instantiate {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let hashes = (0..r * API_BENCHMARK_BATCH_SIZE)
|
||||
@@ -1907,7 +1907,7 @@ benchmarks! {
|
||||
}
|
||||
}
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_instantiate_per_transfer_input_salt_kb {
|
||||
let t in 0 .. 1;
|
||||
let i in 0 .. (code::max_pages::<T>() - 1) * 64;
|
||||
@@ -2002,7 +2002,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// Only the overhead of calling the function itself with minimal arguments.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_hash_sha2_256 {
|
||||
let r in 0 .. 1;
|
||||
let instance = Contract::<T>::new(WasmModule::hasher(
|
||||
@@ -2012,7 +2012,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// `n`: Input to hash in kilobytes
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_hash_sha2_256_per_kb {
|
||||
let n in 0 .. code::max_pages::<T>() * 64;
|
||||
let instance = Contract::<T>::new(WasmModule::hasher(
|
||||
@@ -2022,7 +2022,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// Only the overhead of calling the function itself with minimal arguments.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_hash_keccak_256 {
|
||||
let r in 0 .. 1;
|
||||
let instance = Contract::<T>::new(WasmModule::hasher(
|
||||
@@ -2032,7 +2032,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// `n`: Input to hash in kilobytes
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_hash_keccak_256_per_kb {
|
||||
let n in 0 .. code::max_pages::<T>() * 64;
|
||||
let instance = Contract::<T>::new(WasmModule::hasher(
|
||||
@@ -2042,7 +2042,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// Only the overhead of calling the function itself with minimal arguments.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_hash_blake2_256 {
|
||||
let r in 0 .. 1;
|
||||
let instance = Contract::<T>::new(WasmModule::hasher(
|
||||
@@ -2052,7 +2052,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// `n`: Input to hash in kilobytes
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_hash_blake2_256_per_kb {
|
||||
let n in 0 .. code::max_pages::<T>() * 64;
|
||||
let instance = Contract::<T>::new(WasmModule::hasher(
|
||||
@@ -2062,7 +2062,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// Only the overhead of calling the function itself with minimal arguments.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_hash_blake2_128 {
|
||||
let r in 0 .. 1;
|
||||
let instance = Contract::<T>::new(WasmModule::hasher(
|
||||
@@ -2072,7 +2072,7 @@ benchmarks! {
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
// `n`: Input to hash in kilobytes
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_hash_blake2_128_per_kb {
|
||||
let n in 0 .. code::max_pages::<T>() * 64;
|
||||
let instance = Contract::<T>::new(WasmModule::hasher(
|
||||
@@ -2083,7 +2083,7 @@ benchmarks! {
|
||||
|
||||
// Only calling the function itself with valid arguments.
|
||||
// It generates different private keys and signatures for the message "Hello world".
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_ecdsa_recover {
|
||||
let r in 0 .. 1;
|
||||
|
||||
@@ -2132,7 +2132,7 @@ benchmarks! {
|
||||
|
||||
// Only calling the function itself for the list of
|
||||
// generated different ECDSA keys.
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_ecdsa_to_eth_address {
|
||||
let r in 0 .. 1;
|
||||
let key_type = sp_core::crypto::KeyTypeId(*b"code");
|
||||
@@ -2168,7 +2168,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_set_code_hash {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let code_hashes = (0..r * API_BENCHMARK_BATCH_SIZE)
|
||||
@@ -2209,7 +2209,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_reentrance_count {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -2230,7 +2230,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_account_reentrance_count {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let dummy_code = WasmModule::<T>::dummy_with_bytes(0);
|
||||
@@ -2264,7 +2264,7 @@ benchmarks! {
|
||||
let origin = RawOrigin::Signed(instance.caller.clone());
|
||||
}: call(origin, instance.addr, 0u32.into(), Weight::MAX, None, vec![])
|
||||
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
seal_instantiation_nonce {
|
||||
let r in 0 .. API_BENCHMARK_BATCHES;
|
||||
let code = WasmModule::<T>::from(ModuleDefinition {
|
||||
@@ -3103,7 +3103,7 @@ benchmarks! {
|
||||
// This is no benchmark. It merely exist to have an easy way to pretty print the curently
|
||||
// configured `Schedule` during benchmark development.
|
||||
// It can be outputed using the following command:
|
||||
// cargo run --manifest-path=bin/node/cli/Cargo.toml --release \
|
||||
// cargo run --manifest-path=bin/node/cli/Cargo.toml \
|
||||
// --features runtime-benchmarks -- benchmark pallet --extra --dev --execution=native \
|
||||
// -p pallet_contracts -e print_schedule --no-median-slopes --no-min-squares
|
||||
#[extra]
|
||||
@@ -3111,17 +3111,15 @@ benchmarks! {
|
||||
print_schedule {
|
||||
#[cfg(feature = "std")]
|
||||
{
|
||||
let weight_per_key = T::WeightInfo::on_initialize_per_trie_key(1) -
|
||||
T::WeightInfo::on_initialize_per_trie_key(0);
|
||||
let weight_per_queue_item = T::WeightInfo::on_initialize_per_queue_item(1) -
|
||||
T::WeightInfo::on_initialize_per_queue_item(0);
|
||||
let weight_limit = T::DeletionWeightLimit::get();
|
||||
let queue_depth: u64 = T::DeletionQueueDepth::get().into();
|
||||
let max_queue_depth = T::DeletionQueueDepth::get() as usize;
|
||||
let empty_queue_throughput = Storage::<T>::deletion_budget(0, weight_limit);
|
||||
let full_queue_throughput = Storage::<T>::deletion_budget(max_queue_depth, weight_limit);
|
||||
println!("{:#?}", Schedule::<T>::default());
|
||||
println!("###############################################");
|
||||
println!("Lazy deletion weight per key: {}", empty_queue_throughput.0);
|
||||
println!("Lazy deletion throughput per block (empty queue, full queue): {}, {}",
|
||||
weight_limit / weight_per_key.ref_time(),
|
||||
(weight_limit - weight_per_queue_item * queue_depth) / weight_per_key.ref_time(),
|
||||
empty_queue_throughput.1, full_queue_throughput.1,
|
||||
);
|
||||
}
|
||||
#[cfg(not(feature = "std"))]
|
||||
@@ -3133,7 +3131,7 @@ benchmarks! {
|
||||
// `g` is used to enable gas instrumentation to compare the performance impact of
|
||||
// that instrumentation at runtime.
|
||||
#[extra]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
ink_erc20_transfer {
|
||||
let g in 0 .. 1;
|
||||
let gas_metering = g != 0;
|
||||
@@ -3172,7 +3170,7 @@ benchmarks! {
|
||||
// `g` is used to enable gas instrumentation to compare the performance impact of
|
||||
// that instrumentation at runtime.
|
||||
#[extra]
|
||||
#[pov_mode = Ignored]
|
||||
#[pov_mode = Measured]
|
||||
solang_erc20_transfer {
|
||||
let g in 0 .. 1;
|
||||
let gas_metering = g != 0;
|
||||
|
||||
@@ -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 ),+)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -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),
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,13 +245,12 @@ 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
|
||||
@@ -259,9 +258,8 @@ impl<T: Config> Storage<T> {
|
||||
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)
|
||||
}
|
||||
@@ -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)`.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -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(|| {
|
||||
@@ -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 {
|
||||
|
||||
@@ -50,53 +50,61 @@ use sp_std::vec;
|
||||
/// under the specified `code_hash`.
|
||||
pub fn store<T: Config>(mut module: PrefabWasmModule<T>, instantiated: bool) -> DispatchResult {
|
||||
let code_hash = sp_std::mem::take(&mut module.code_hash);
|
||||
<CodeStorage<T>>::mutate(&code_hash, |existing| match existing {
|
||||
Some(existing) => {
|
||||
// We instrument any uploaded contract anyways. We might as well store it to save
|
||||
// a potential re-instrumentation later.
|
||||
existing.code = module.code;
|
||||
existing.instruction_weights_version = module.instruction_weights_version;
|
||||
// When the code was merely uploaded but not instantiated we can skip this.
|
||||
if instantiated {
|
||||
<OwnerInfoOf<T>>::mutate(&code_hash, |owner_info| {
|
||||
if let Some(owner_info) = owner_info {
|
||||
owner_info.refcount = owner_info.refcount.checked_add(1).expect(
|
||||
"
|
||||
refcount is 64bit. Generating this overflow would require to store
|
||||
_at least_ 18 exabyte of data assuming that a contract consumes only
|
||||
one byte of data. Any node would run out of storage space before hitting
|
||||
this overflow.
|
||||
qed
|
||||
",
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
None => {
|
||||
let orig_code = module.original_code.take().expect(
|
||||
"
|
||||
<OwnerInfoOf<T>>::mutate(&code_hash, |owner_info| {
|
||||
match owner_info {
|
||||
// Instantiate existing contract.
|
||||
//
|
||||
// No need to update the `CodeStorage` as any re-instrumentation eagerly saves
|
||||
// the re-instrumented code.
|
||||
Some(owner_info) if instantiated => {
|
||||
owner_info.refcount = owner_info.refcount.checked_add(1).expect(
|
||||
"
|
||||
refcount is 64bit. Generating this overflow would require to store
|
||||
_at least_ 18 exabyte of data assuming that a contract consumes only
|
||||
one byte of data. Any node would run out of storage space before hitting
|
||||
this overflow.
|
||||
qed
|
||||
",
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
// Re-upload existing contract without executing it.
|
||||
//
|
||||
// We are careful here to just overwrite the code to not include it into the PoV.
|
||||
// We do this because the uploaded code was instrumented with the latest schedule
|
||||
// and hence we persist those changes. Otherwise the next execution will pay again
|
||||
// for the instrumentation.
|
||||
Some(_) => {
|
||||
<CodeStorage<T>>::insert(&code_hash, module);
|
||||
Ok(())
|
||||
},
|
||||
// Upload a new contract.
|
||||
//
|
||||
// We need to write all data structures and collect the deposit.
|
||||
None => {
|
||||
let orig_code = module.original_code.take().expect(
|
||||
"
|
||||
If an executable isn't in storage it was uploaded.
|
||||
If it was uploaded the original code must exist. qed
|
||||
",
|
||||
);
|
||||
let mut owner_info = module.owner_info.take().expect(
|
||||
"If an executable isn't in storage it was uploaded.
|
||||
);
|
||||
let mut new_owner_info = module.owner_info.take().expect(
|
||||
"If an executable isn't in storage it was uploaded.
|
||||
If it was uploaded the owner info was generated and attached. qed
|
||||
",
|
||||
);
|
||||
// This `None` case happens only in freshly uploaded modules. This means that
|
||||
// the `owner` is always the origin of the current transaction.
|
||||
T::Currency::reserve(&owner_info.owner, owner_info.deposit)
|
||||
.map_err(|_| <Error<T>>::StorageDepositNotEnoughFunds)?;
|
||||
owner_info.refcount = if instantiated { 1 } else { 0 };
|
||||
<PristineCode<T>>::insert(&code_hash, orig_code);
|
||||
<OwnerInfoOf<T>>::insert(&code_hash, owner_info);
|
||||
*existing = Some(module);
|
||||
<Pallet<T>>::deposit_event(vec![code_hash], Event::CodeStored { code_hash });
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
// This `None` case happens only in freshly uploaded modules. This means that
|
||||
// the `owner` is always the origin of the current transaction.
|
||||
T::Currency::reserve(&new_owner_info.owner, new_owner_info.deposit)
|
||||
.map_err(|_| <Error<T>>::StorageDepositNotEnoughFunds)?;
|
||||
new_owner_info.refcount = if instantiated { 1 } else { 0 };
|
||||
<PristineCode<T>>::insert(&code_hash, orig_code);
|
||||
<CodeStorage<T>>::insert(&code_hash, module);
|
||||
*owner_info = Some(new_owner_info);
|
||||
<Pallet<T>>::deposit_event(vec![code_hash], Event::CodeStored { code_hash });
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -162,15 +170,16 @@ pub fn load<T: Config>(
|
||||
let charged = gas_meter.charge(CodeToken::Load(max_code_len))?;
|
||||
|
||||
let mut prefab_module = <CodeStorage<T>>::get(code_hash).ok_or(Error::<T>::CodeNotFound)?;
|
||||
gas_meter.adjust_gas(charged, CodeToken::Load(prefab_module.code.len() as u32));
|
||||
let instrumented_code_len = prefab_module.code.len() as u32;
|
||||
gas_meter.adjust_gas(charged, CodeToken::Load(instrumented_code_len));
|
||||
prefab_module.code_hash = code_hash;
|
||||
|
||||
if prefab_module.instruction_weights_version < schedule.instruction_weights.version {
|
||||
// The instruction weights have changed.
|
||||
// We need to re-instrument the code with the new instruction weights.
|
||||
let charged = gas_meter.charge(CodeToken::Reinstrument(max_code_len))?;
|
||||
let code_size = reinstrument(&mut prefab_module, schedule)?;
|
||||
gas_meter.adjust_gas(charged, CodeToken::Reinstrument(code_size));
|
||||
let charged = gas_meter.charge(CodeToken::Reinstrument(instrumented_code_len))?;
|
||||
let orig_code_len = reinstrument(&mut prefab_module, schedule)?;
|
||||
gas_meter.adjust_gas(charged, CodeToken::Reinstrument(orig_code_len));
|
||||
}
|
||||
|
||||
Ok(prefab_module)
|
||||
@@ -224,8 +233,7 @@ impl<T: Config> Token<T> for CodeToken {
|
||||
match *self {
|
||||
Reinstrument(len) => T::WeightInfo::reinstrument(len),
|
||||
Load(len) => T::WeightInfo::call_with_code_per_byte(len)
|
||||
.saturating_sub(T::WeightInfo::call_with_code_per_byte(0))
|
||||
.set_proof_size(len.into()),
|
||||
.saturating_sub(T::WeightInfo::call_with_code_per_byte(0)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ pub use crate::wasm::{
|
||||
use crate::{
|
||||
exec::{ExecResult, Executable, ExportedFunction, Ext},
|
||||
gas::GasMeter,
|
||||
AccountIdOf, BalanceOf, CodeHash, CodeStorage, CodeVec, Config, Error, RelaxedCodeVec,
|
||||
AccountIdOf, BalanceOf, CodeHash, CodeVec, Config, Error, OwnerInfoOf, RelaxedCodeVec,
|
||||
Schedule,
|
||||
};
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
@@ -191,7 +191,7 @@ impl<T: Config> PrefabWasmModule<T> {
|
||||
/// Returns `0` if the module is already in storage and hence no deposit will
|
||||
/// be charged when storing it.
|
||||
pub fn open_deposit(&self) -> BalanceOf<T> {
|
||||
if <CodeStorage<T>>::contains_key(&self.code_hash) {
|
||||
if <OwnerInfoOf<T>>::contains_key(&self.code_hash) {
|
||||
0u32.into()
|
||||
} else {
|
||||
// Only already in-storage contracts have their `owner_info` set to `None`.
|
||||
|
||||
+1885
-1779
File diff suppressed because it is too large
Load Diff
@@ -232,6 +232,38 @@ impl Weight {
|
||||
Some(Self { ref_time, proof_size })
|
||||
}
|
||||
|
||||
/// Calculates how many `other` fit into `self`.
|
||||
///
|
||||
/// Divides each component of `self` against the same component of `other`. Returns the minimum
|
||||
/// of all those divisions. Returns `None` in case **all** components of `other` are zero.
|
||||
///
|
||||
/// This returns `Some` even if some components of `other` are zero as long as there is at least
|
||||
/// one non-zero component in `other`. The devision for this particular component will then
|
||||
/// yield the maximum value (e.g u64::MAX). This is because we assume not every operation and
|
||||
/// hence each `Weight` will necessarily use each resource.
|
||||
pub const fn checked_div_per_component(self, other: &Self) -> Option<u64> {
|
||||
let mut all_zero = true;
|
||||
let ref_time = match self.ref_time.checked_div(other.ref_time) {
|
||||
Some(ref_time) => {
|
||||
all_zero = false;
|
||||
ref_time
|
||||
},
|
||||
None => u64::MAX,
|
||||
};
|
||||
let proof_size = match self.proof_size.checked_div(other.proof_size) {
|
||||
Some(proof_size) => {
|
||||
all_zero = false;
|
||||
proof_size
|
||||
},
|
||||
None => u64::MAX,
|
||||
};
|
||||
if all_zero {
|
||||
None
|
||||
} else {
|
||||
Some(if ref_time < proof_size { ref_time } else { proof_size })
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to increase `self` by `amount` via checked addition.
|
||||
pub fn checked_accrue(&mut self, amount: Self) -> Option<()> {
|
||||
self.checked_add(&amount).map(|new_self| *self = new_self)
|
||||
@@ -582,4 +614,48 @@ mod tests {
|
||||
assert!(weight.checked_reduce(Weight::from_parts(0, 18)).is_some());
|
||||
assert!(weight.is_zero());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checked_div_per_component_works() {
|
||||
assert_eq!(
|
||||
Weight::from_parts(10, 20).checked_div_per_component(&Weight::from_parts(2, 10)),
|
||||
Some(2)
|
||||
);
|
||||
assert_eq!(
|
||||
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(2, 10)),
|
||||
Some(5)
|
||||
);
|
||||
assert_eq!(
|
||||
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(1, 10)),
|
||||
Some(10)
|
||||
);
|
||||
assert_eq!(
|
||||
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(2, 1)),
|
||||
Some(5)
|
||||
);
|
||||
assert_eq!(
|
||||
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(0, 10)),
|
||||
Some(20)
|
||||
);
|
||||
assert_eq!(
|
||||
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(1, 0)),
|
||||
Some(10)
|
||||
);
|
||||
assert_eq!(
|
||||
Weight::from_parts(0, 200).checked_div_per_component(&Weight::from_parts(2, 3)),
|
||||
Some(0)
|
||||
);
|
||||
assert_eq!(
|
||||
Weight::from_parts(10, 0).checked_div_per_component(&Weight::from_parts(2, 3)),
|
||||
Some(0)
|
||||
);
|
||||
assert_eq!(
|
||||
Weight::from_parts(10, 200).checked_div_per_component(&Weight::from_parts(0, 0)),
|
||||
None,
|
||||
);
|
||||
assert_eq!(
|
||||
Weight::from_parts(0, 0).checked_div_per_component(&Weight::from_parts(0, 0)),
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user