1234567891011121314151617181920#![cfg(feature = "runtime-benchmarks")]2122mod code;23mod sandbox;2425use crate::{26 *, Pallet as Contracts,27 exec::StorageKey,28 rent::Rent,29 schedule::{API_BENCHMARK_BATCH_SIZE, INSTR_BENCHMARK_BATCH_SIZE},30 storage::Storage,31};32use self::{33 code::{34 body::{self, DynInstr::*},35 ModuleDefinition, DataSegment, ImportedMemory, ImportedFunction, WasmModule,36 },37 sandbox::Sandbox,38};39use codec::Encode;40use frame_benchmarking::{benchmarks, account, whitelisted_caller, impl_benchmark_test_suite};41use frame_system::{Pallet as System, RawOrigin};42use parity_wasm::elements::{Instruction, ValueType, BlockType};43use sp_runtime::traits::{Hash, Bounded, Zero};44use sp_std::{45 default::Default,46 convert::{TryInto},47 vec::Vec,48 vec,49};50use pallet_contracts_primitives::RentProjection;51use frame_support::weights::Weight;525354const API_BENCHMARK_BATCHES: u32 = 20;555657const INSTR_BENCHMARK_BATCHES: u32 = 1;585960struct Contract<T: Config> {61 caller: T::AccountId,62 account_id: T::AccountId,63 addr: <T::Lookup as StaticLookup>::Source,64 endowment: BalanceOf<T>,65 code_hash: <T::Hashing as Hash>::Output,66}676869enum Endow {70 71 72 Max,73 74 75 CollectRent,76}7778impl Endow {79 80 81 82 fn max<T: Config>() -> BalanceOf<T> {83 caller_funding::<T>().saturating_sub(T::Currency::minimum_balance())84 }85}8687impl<T: Config> Contract<T>88where89 T: Config,90 T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,91{92 93 fn new(94 module: WasmModule<T>,95 data: Vec<u8>,96 endowment: Endow,97 ) -> Result<Contract<T>, &'static str> {98 Self::with_index(0, module, data, endowment)99 }100101 102 fn with_index(103 index: u32,104 module: WasmModule<T>,105 data: Vec<u8>,106 endowment: Endow,107 ) -> Result<Contract<T>, &'static str> {108 Self::with_caller(account("instantiator", index, 0), module, data, endowment)109 }110111 112 fn with_caller(113 caller: T::AccountId,114 module: WasmModule<T>,115 data: Vec<u8>,116 endowment: Endow,117 ) -> Result<Contract<T>, &'static str> {118 let (storage_size, endowment) = match endowment {119 Endow::CollectRent => {120 121 122 123 let storage_size = u32::max_value() / 10;124125 126 127 let endowment = T::DepositPerStorageByte::get()128 .saturating_mul(<BalanceOf<T>>::from(storage_size) / 2u32.into())129 .saturating_add(T::DepositPerContract::get());130131 (storage_size, endowment)132 }133 Endow::Max => (0u32.into(), Endow::max::<T>()),134 };135 T::Currency::make_free_balance_be(&caller, caller_funding::<T>());136 let salt = vec![0xff];137 let addr = Contracts::<T>::contract_address(&caller, &module.hash, &salt);138139 140 141 142 143 144 System::<T>::set_block_number(1u32.into());145146 Contracts::<T>::store_code_raw(module.code)?;147 Contracts::<T>::instantiate(148 RawOrigin::Signed(caller.clone()).into(),149 endowment,150 Weight::max_value(),151 module.hash,152 data,153 salt,154 )?;155156 let result = Contract {157 caller,158 account_id: addr.clone(),159 addr: T::Lookup::unlookup(addr),160 endowment,161 code_hash: module.hash.clone(),162 };163164 let mut contract = result.alive_info()?;165 contract.storage_size = storage_size;166 ContractInfoOf::<T>::insert(&result.account_id, ContractInfo::Alive(contract));167168 Ok(result)169 }170171 172 fn store(&self, items: &Vec<(StorageKey, Vec<u8>)>) -> Result<(), &'static str> {173 let info = self.alive_info()?;174 for item in items {175 Storage::<T>::write(176 &self.account_id,177 &info.trie_id,178 &item.0,179 Some(item.1.clone()),180 )181 .map_err(|_| "Failed to write storage to restoration dest")?;182 }183 Ok(())184 }185186 187 fn address_alive_info(addr: &T::AccountId) -> Result<AliveContractInfo<T>, &'static str> {188 ContractInfoOf::<T>::get(addr)189 .and_then(|c| c.get_alive())190 .ok_or("Expected contract to be alive at this point.")191 }192193 194 fn alive_info(&self) -> Result<AliveContractInfo<T>, &'static str> {195 Self::address_alive_info(&self.account_id)196 }197198 199 fn ensure_tombstone(&self) -> Result<(), &'static str> {200 ContractInfoOf::<T>::get(&self.account_id)201 .and_then(|c| c.get_tombstone())202 .ok_or("Expected contract to be a tombstone at this point.")203 .map(|_| ())204 }205206 207 208 fn eviction_at(&self) -> Result<T::BlockNumber, &'static str> {209 let projection = Rent::<T, PrefabWasmModule<T>>::compute_projection(&self.account_id)210 .map_err(|_| "Invalid acc for rent")?;211 match projection {212 RentProjection::EvictionAt(at) => Ok(at),213 _ => Err("Account does not pay rent.")?,214 }215 }216}217218219220221222struct ContractWithStorage<T: Config> {223 224 contract: Contract<T>,225 226 storage: Vec<(StorageKey, Vec<u8>)>,227}228229impl<T: Config> ContractWithStorage<T>230where231 T: Config,232 T::AccountId: UncheckedFrom<T::Hash> + AsRef<[u8]>,233{234 235 fn new(stor_num: u32, stor_size: u32) -> Result<Self, &'static str> {236 Self::with_code(WasmModule::dummy(), stor_num, stor_size)237 }238239 240 fn with_code(code: WasmModule<T>, stor_num: u32, stor_size: u32) -> Result<Self, &'static str> {241 let contract = Contract::<T>::new(code, vec![], Endow::CollectRent)?;242 let storage_items = create_storage::<T>(stor_num, stor_size)?;243 contract.store(&storage_items)?;244 Ok(Self {245 contract,246 storage: storage_items,247 })248 }249250 251 fn set_block_num_for_eviction(&self) -> Result<(), &'static str> {252 System::<T>::set_block_number(253 self.contract.eviction_at()? + T::SignedClaimHandicap::get() + 5u32.into(),254 );255 Ok(())256 }257258 259 fn evict(&mut self) -> Result<(), &'static str> {260 self.set_block_num_for_eviction()?;261 Rent::<T, PrefabWasmModule<T>>::try_eviction(&self.contract.account_id, Zero::zero())?;262 self.contract.ensure_tombstone()263 }264}265266267fn create_storage<T: Config>(268 stor_num: u32,269 stor_size: u32,270) -> Result<Vec<(StorageKey, Vec<u8>)>, &'static str> {271 (0..stor_num)272 .map(|i| {273 let hash = T::Hashing::hash_of(&i)274 .as_ref()275 .try_into()276 .map_err(|_| "Hash too big for storage key")?;277 Ok((hash, vec![42u8; stor_size as usize]))278 })279 .collect::<Result<Vec<_>, &'static str>>()280}281282283fn caller_funding<T: Config>() -> BalanceOf<T> {284 BalanceOf::<T>::max_value() / 2u32.into()285}286287benchmarks! {288 where_clause { where289 T::AccountId: UncheckedFrom<T::Hash>,290 T::AccountId: AsRef<[u8]>,291 }292293 294 on_initialize {}: {295 Storage::<T>::process_deletion_queue_batch(Weight::max_value())296 }297298 on_initialize_per_trie_key {299 let k in 0..1024;300 let instance = ContractWithStorage::<T>::new(k, T::MaxValueSize::get())?;301 Storage::<T>::queue_trie_for_deletion(&instance.contract.alive_info()?)?;302 }: {303 Storage::<T>::process_deletion_queue_batch(Weight::max_value())304 }305306 on_initialize_per_queue_item {307 let q in 0..1024.min(T::DeletionQueueDepth::get());308 for i in 0 .. q {309 let instance = Contract::<T>::with_index(i, WasmModule::dummy(), vec![], Endow::Max)?;310 Storage::<T>::queue_trie_for_deletion(&instance.alive_info()?)?;311 ContractInfoOf::<T>::remove(instance.account_id);312 }313 }: {314 Storage::<T>::process_deletion_queue_batch(Weight::max_value())315 }316317 318 319 320 instrument {321 let c in 0 .. T::MaxCodeSize::get() / 1024;322 let WasmModule { code, hash, .. } = WasmModule::<T>::sized(c * 1024);323 Contracts::<T>::store_code_raw(code)?;324 let mut module = PrefabWasmModule::from_storage_noinstr(hash)?;325 let schedule = <CurrentSchedule<T>>::get();326 }: {327 Contracts::<T>::reinstrument_module(&mut module, &schedule)?;328 }329330 331 update_schedule {332 let schedule = Schedule {333 version: 1,334 .. Default::default()335 };336 }: _(RawOrigin::Root, schedule)337338 339 340 341 342 343 344 345 346 347 348 349 instantiate_with_code {350 let c in 0 .. Perbill::from_percent(50).mul_ceil(T::MaxCodeSize::get() / 1024);351 let s in 0 .. code::max_pages::<T>() * 64;352 let salt = vec![42u8; (s * 1024) as usize];353 let endowment = caller_funding::<T>() / 3u32.into();354 let caller = whitelisted_caller();355 T::Currency::make_free_balance_be(&caller, caller_funding::<T>());356 let WasmModule { code, hash, .. } = WasmModule::<T>::sized(c * 1024);357 let origin = RawOrigin::Signed(caller.clone());358 let addr = Contracts::<T>::contract_address(&caller, &hash, &salt);359 }: _(origin, endowment, Weight::max_value(), code, vec![], salt)360 verify {361 362 assert_eq!(T::Currency::free_balance(&caller), caller_funding::<T>() - endowment);363 364 assert_eq!(T::Currency::free_balance(&addr), endowment);365 366 Contract::<T>::address_alive_info(&addr)?;367 }368369 370 371 372 instantiate {373 let c in 0 .. T::MaxCodeSize::get() / 1024;374 let s in 0 .. code::max_pages::<T>() * 64;375 let salt = vec![42u8; (s * 1024) as usize];376 let endowment = caller_funding::<T>() / 3u32.into();377 let caller = whitelisted_caller();378 T::Currency::make_free_balance_be(&caller, caller_funding::<T>());379 let WasmModule { code, hash, .. } = WasmModule::<T>::dummy_with_bytes(c * 1024);380 let origin = RawOrigin::Signed(caller.clone());381 let addr = Contracts::<T>::contract_address(&caller, &hash, &salt);382 Contracts::<T>::store_code_raw(code)?;383 }: _(origin, endowment, Weight::max_value(), hash, vec![], salt)384 verify {385 386 assert_eq!(T::Currency::free_balance(&caller), caller_funding::<T>() - endowment);387 388 assert_eq!(T::Currency::free_balance(&addr), endowment);389 390 Contract::<T>::address_alive_info(&addr)?;391 }392393 394 395 396 397 398 399 call {400 let c in 0 .. T::MaxCodeSize::get() / 1024;401 let data = vec![42u8; 1024];402 let instance = Contract::<T>::with_caller(403 whitelisted_caller(), WasmModule::dummy_with_bytes(c * 1024), vec![], Endow::CollectRent404 )?;405 let value = T::Currency::minimum_balance() * 100u32.into();406 let origin = RawOrigin::Signed(instance.caller.clone());407 let callee = instance.addr.clone();408409 410 System::<T>::set_block_number(instance.eviction_at()? - 5u32.into());411 let before = T::Currency::free_balance(&instance.account_id);412 }: _(origin, callee, value, Weight::max_value(), data)413 verify {414 415 assert_eq!(416 T::Currency::free_balance(&instance.caller),417 caller_funding::<T>() - instance.endowment - value,418 );419 420 assert!(T::Currency::free_balance(&instance.account_id) < before + value);421 422 instance.alive_info()?;423 }424425 426 427 428 429 430 431 432 claim_surcharge {433 let c in 0 .. T::MaxCodeSize::get() / 1024;434 let instance = Contract::<T>::with_caller(435 whitelisted_caller(), WasmModule::dummy_with_bytes(c * 1024), vec![], Endow::CollectRent436 )?;437 let origin = RawOrigin::Signed(instance.caller.clone());438 let account_id = instance.account_id.clone();439440 441 instance.alive_info()?;442443 444 System::<T>::set_block_number(445 instance.eviction_at()? + T::SignedClaimHandicap::get() + 5u32.into()446 );447 }: _(origin, account_id, None)448 verify {449 450 instance.ensure_tombstone()?;451452 453 454 455 assert!(456 T::Currency::free_balance(&instance.caller) >457 caller_funding::<T>() - instance.endowment458 );459 assert!(460 T::Currency::free_balance(&instance.caller) <=461 caller_funding::<T>() - instance.endowment + <T as Config>::SurchargeReward::get(),462 );463 }464465 seal_caller {466 let r in 0 .. API_BENCHMARK_BATCHES;467 let instance = Contract::<T>::new(WasmModule::getter(468 "seal_caller", r * API_BENCHMARK_BATCH_SIZE469 ), vec![], Endow::Max)?;470 let origin = RawOrigin::Signed(instance.caller.clone());471 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])472473 seal_address {474 let r in 0 .. API_BENCHMARK_BATCHES;475 let instance = Contract::<T>::new(WasmModule::getter(476 "seal_address", r * API_BENCHMARK_BATCH_SIZE477 ), vec![], Endow::Max)?;478 let origin = RawOrigin::Signed(instance.caller.clone());479 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])480481 seal_gas_left {482 let r in 0 .. API_BENCHMARK_BATCHES;483 let instance = Contract::<T>::new(WasmModule::getter(484 "seal_gas_left", r * API_BENCHMARK_BATCH_SIZE485 ), vec![], Endow::Max)?;486 let origin = RawOrigin::Signed(instance.caller.clone());487 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])488489 seal_balance {490 let r in 0 .. API_BENCHMARK_BATCHES;491 let instance = Contract::<T>::new(WasmModule::getter(492 "seal_balance", r * API_BENCHMARK_BATCH_SIZE493 ), vec![], Endow::Max)?;494 let origin = RawOrigin::Signed(instance.caller.clone());495 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])496497 seal_value_transferred {498 let r in 0 .. API_BENCHMARK_BATCHES;499 let instance = Contract::<T>::new(WasmModule::getter(500 "seal_value_transferred", r * API_BENCHMARK_BATCH_SIZE501 ), vec![], Endow::Max)?;502 let origin = RawOrigin::Signed(instance.caller.clone());503 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])504505 seal_minimum_balance {506 let r in 0 .. API_BENCHMARK_BATCHES;507 let instance = Contract::<T>::new(WasmModule::getter(508 "seal_minimum_balance", r * API_BENCHMARK_BATCH_SIZE509 ), vec![], Endow::Max)?;510 let origin = RawOrigin::Signed(instance.caller.clone());511 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])512513 seal_tombstone_deposit {514 let r in 0 .. API_BENCHMARK_BATCHES;515 let instance = Contract::<T>::new(WasmModule::getter(516 "seal_tombstone_deposit", r * API_BENCHMARK_BATCH_SIZE517 ), vec![], Endow::Max)?;518 let origin = RawOrigin::Signed(instance.caller.clone());519 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])520521 seal_rent_allowance {522 let r in 0 .. API_BENCHMARK_BATCHES;523 let instance = Contract::<T>::new(WasmModule::getter(524 "seal_rent_allowance", r * API_BENCHMARK_BATCH_SIZE525 ), vec![], Endow::Max)?;526 let origin = RawOrigin::Signed(instance.caller.clone());527 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])528529 seal_block_number {530 let r in 0 .. API_BENCHMARK_BATCHES;531 let instance = Contract::<T>::new(WasmModule::getter(532 "seal_block_number", r * API_BENCHMARK_BATCH_SIZE533 ), vec![], Endow::Max)?;534 let origin = RawOrigin::Signed(instance.caller.clone());535 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])536537 seal_now {538 let r in 0 .. API_BENCHMARK_BATCHES;539 let instance = Contract::<T>::new(WasmModule::getter(540 "seal_now", r * API_BENCHMARK_BATCH_SIZE541 ), vec![], Endow::Max)?;542 let origin = RawOrigin::Signed(instance.caller.clone());543 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])544545 seal_rent_params {546 let r in 0 .. API_BENCHMARK_BATCHES;547 let instance = Contract::<T>::new(WasmModule::getter(548 "seal_rent_params", r * API_BENCHMARK_BATCH_SIZE549 ), vec![], Endow::Max)?;550 let origin = RawOrigin::Signed(instance.caller.clone());551 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])552553 seal_weight_to_fee {554 let r in 0 .. API_BENCHMARK_BATCHES;555 let pages = code::max_pages::<T>();556 let code = WasmModule::<T>::from(ModuleDefinition {557 memory: Some(ImportedMemory::max::<T>()),558 imported_functions: vec![ImportedFunction {559 name: "seal_weight_to_fee",560 params: vec![ValueType::I64, ValueType::I32, ValueType::I32],561 return_type: None,562 }],563 data_segments: vec![DataSegment {564 offset: 0,565 value: (pages * 64 * 1024 - 4).to_le_bytes().to_vec(),566 }],567 call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[568 Instruction::I64Const(500_000),569 Instruction::I32Const(4),570 Instruction::I32Const(0),571 Instruction::Call(0),572 ])),573 .. Default::default()574 });575 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;576 let origin = RawOrigin::Signed(instance.caller.clone());577 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])578579 seal_gas {580 let r in 0 .. API_BENCHMARK_BATCHES;581 let code = WasmModule::<T>::from(ModuleDefinition {582 imported_functions: vec![ImportedFunction {583 name: "gas",584 params: vec![ValueType::I32],585 return_type: None,586 }],587 call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[588 Instruction::I32Const(42),589 Instruction::Call(0),590 ])),591 .. Default::default()592 });593 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;594 let origin = RawOrigin::Signed(instance.caller.clone());595596 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])597598 599 600 601 seal_input {602 let r in 0 .. 1;603 let code = WasmModule::<T>::from(ModuleDefinition {604 memory: Some(ImportedMemory::max::<T>()),605 imported_functions: vec![ImportedFunction {606 name: "seal_input",607 params: vec![ValueType::I32, ValueType::I32],608 return_type: None,609 }],610 data_segments: vec![611 DataSegment {612 offset: 0,613 value: 0u32.to_le_bytes().to_vec(),614 },615 ],616 call_body: Some(body::repeated(r, &[617 Instruction::I32Const(4), 618 Instruction::I32Const(0), 619 Instruction::Call(0),620 ])),621 .. Default::default()622 });623 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;624 let origin = RawOrigin::Signed(instance.caller.clone());625 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])626627 seal_input_per_kb {628 let n in 0 .. code::max_pages::<T>() * 64;629 let pages = code::max_pages::<T>();630 let buffer_size = pages * 64 * 1024 - 4;631 let code = WasmModule::<T>::from(ModuleDefinition {632 memory: Some(ImportedMemory::max::<T>()),633 imported_functions: vec![ImportedFunction {634 name: "seal_input",635 params: vec![ValueType::I32, ValueType::I32],636 return_type: None,637 }],638 data_segments: vec![639 DataSegment {640 offset: 0,641 value: buffer_size.to_le_bytes().to_vec(),642 },643 ],644 call_body: Some(body::plain(vec![645 Instruction::I32Const(4), 646 Instruction::I32Const(0), 647 Instruction::Call(0),648 Instruction::End,649 ])),650 .. Default::default()651 });652 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;653 let data = vec![42u8; (n * 1024).min(buffer_size) as usize];654 let origin = RawOrigin::Signed(instance.caller.clone());655 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), data)656657 658 seal_return {659 let r in 0 .. 1;660 let code = WasmModule::<T>::from(ModuleDefinition {661 memory: Some(ImportedMemory::max::<T>()),662 imported_functions: vec![ImportedFunction {663 name: "seal_return",664 params: vec![ValueType::I32, ValueType::I32, ValueType::I32],665 return_type: None,666 }],667 call_body: Some(body::repeated(r, &[668 Instruction::I32Const(0), 669 Instruction::I32Const(0), 670 Instruction::I32Const(0), 671 Instruction::Call(0),672 ])),673 .. Default::default()674 });675 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;676 let origin = RawOrigin::Signed(instance.caller.clone());677 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])678679 seal_return_per_kb {680 let n in 0 .. code::max_pages::<T>() * 64;681 let code = WasmModule::<T>::from(ModuleDefinition {682 memory: Some(ImportedMemory::max::<T>()),683 imported_functions: vec![ImportedFunction {684 name: "seal_return",685 params: vec![ValueType::I32, ValueType::I32, ValueType::I32],686 return_type: None,687 }],688 call_body: Some(body::plain(vec![689 Instruction::I32Const(0), 690 Instruction::I32Const(0), 691 Instruction::I32Const((n * 1024) as i32), 692 Instruction::Call(0),693 Instruction::End,694 ])),695 .. Default::default()696 });697 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;698 let origin = RawOrigin::Signed(instance.caller.clone());699 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])700701 702 seal_terminate {703 let r in 0 .. 1;704 let beneficiary = account::<T::AccountId>("beneficiary", 0, 0);705 let beneficiary_bytes = beneficiary.encode();706 let beneficiary_len = beneficiary_bytes.len();707 let code = WasmModule::<T>::from(ModuleDefinition {708 memory: Some(ImportedMemory::max::<T>()),709 imported_functions: vec![ImportedFunction {710 name: "seal_terminate",711 params: vec![ValueType::I32, ValueType::I32],712 return_type: None,713 }],714 data_segments: vec![715 DataSegment {716 offset: 0,717 value: beneficiary_bytes,718 },719 ],720 call_body: Some(body::repeated(r, &[721 Instruction::I32Const(0), 722 Instruction::I32Const(beneficiary_len as i32), 723 Instruction::Call(0),724 ])),725 .. Default::default()726 });727 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;728 let origin = RawOrigin::Signed(instance.caller.clone());729 assert_eq!(T::Currency::total_balance(&beneficiary), 0u32.into());730 assert_eq!(T::Currency::total_balance(&instance.account_id), Endow::max::<T>());731 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])732 verify {733 if r > 0 {734 assert_eq!(T::Currency::total_balance(&instance.account_id), 0u32.into());735 assert_eq!(T::Currency::total_balance(&beneficiary), Endow::max::<T>());736 }737 }738739 seal_terminate_per_code_kb {740 let c in 0 .. T::MaxCodeSize::get() / 1024;741 let beneficiary = account::<T::AccountId>("beneficiary", 0, 0);742 let beneficiary_bytes = beneficiary.encode();743 let beneficiary_len = beneficiary_bytes.len();744 let code = WasmModule::<T>::from(ModuleDefinition {745 memory: Some(ImportedMemory::max::<T>()),746 imported_functions: vec![ImportedFunction {747 name: "seal_terminate",748 params: vec![ValueType::I32, ValueType::I32],749 return_type: None,750 }],751 data_segments: vec![752 DataSegment {753 offset: 0,754 value: beneficiary_bytes,755 },756 ],757 call_body: Some(body::repeated(1, &[758 Instruction::I32Const(0), 759 Instruction::I32Const(beneficiary_len as i32), 760 Instruction::Call(0),761 ])),762 dummy_section: c * 1024,763 .. Default::default()764 });765 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;766 let origin = RawOrigin::Signed(instance.caller.clone());767 assert_eq!(T::Currency::total_balance(&beneficiary), 0u32.into());768 assert_eq!(T::Currency::total_balance(&instance.account_id), Endow::max::<T>());769 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])770 verify {771 assert_eq!(T::Currency::total_balance(&instance.account_id), 0u32.into());772 assert_eq!(T::Currency::total_balance(&beneficiary), Endow::max::<T>());773 }774775 seal_restore_to {776 let r in 0 .. 1;777778 779 780 781 let mut tombstone = ContractWithStorage::<T>::new(10, T::MaxValueSize::get())?;782 tombstone.evict()?;783784 let dest = tombstone.contract.account_id.encode();785 let dest_len = dest.len();786 let code_hash = tombstone.contract.code_hash.encode();787 let code_hash_len = code_hash.len();788 let rent_allowance = BalanceOf::<T>::max_value().encode();789 let rent_allowance_len = rent_allowance.len();790791 let dest_offset = 0;792 let code_hash_offset = dest_offset + dest_len;793 let rent_allowance_offset = code_hash_offset + code_hash_len;794795 let code = WasmModule::<T>::from(ModuleDefinition {796 memory: Some(ImportedMemory::max::<T>()),797 imported_functions: vec![ImportedFunction {798 name: "seal_restore_to",799 params: vec![800 ValueType::I32,801 ValueType::I32,802 ValueType::I32,803 ValueType::I32,804 ValueType::I32,805 ValueType::I32,806 ValueType::I32,807 ValueType::I32,808 ],809 return_type: None,810 }],811 data_segments: vec![812 DataSegment {813 offset: dest_offset as u32,814 value: dest,815 },816 DataSegment {817 offset: code_hash_offset as u32,818 value: code_hash,819 },820 DataSegment {821 offset: rent_allowance_offset as u32,822 value: rent_allowance,823 },824 ],825 call_body: Some(body::repeated(r, &[826 Instruction::I32Const(dest_offset as i32),827 Instruction::I32Const(dest_len as i32),828 Instruction::I32Const(code_hash_offset as i32),829 Instruction::I32Const(code_hash_len as i32),830 Instruction::I32Const(rent_allowance_offset as i32),831 Instruction::I32Const(rent_allowance_len as i32),832 Instruction::I32Const(0), 833 Instruction::I32Const(0), 834 Instruction::Call(0),835 ])),836 .. Default::default()837 });838839 let instance = Contract::<T>::with_caller(840 account("origin", 0, 0), code, vec![], Endow::Max841 )?;842 instance.store(&tombstone.storage)?;843 System::<T>::set_block_number(System::<T>::block_number() + 1u32.into());844845 let origin = RawOrigin::Signed(instance.caller.clone());846 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])847 verify {848 if r > 0 {849 tombstone.contract.alive_info()?;850 }851 }852853 854 855 856 seal_restore_to_per_code_kb_delta {857 let c in 0 .. T::MaxCodeSize::get() / 1024;858 let t in 0 .. T::MaxCodeSize::get() / 1024;859 let d in 0 .. API_BENCHMARK_BATCHES;860 let mut tombstone = ContractWithStorage::<T>::with_code(861 WasmModule::<T>::dummy_with_bytes(t * 1024), 0, 0862 )?;863 tombstone.evict()?;864 let delta = create_storage::<T>(d * API_BENCHMARK_BATCH_SIZE, T::MaxValueSize::get())?;865866 let dest = tombstone.contract.account_id.encode();867 let dest_len = dest.len();868 let code_hash = tombstone.contract.code_hash.encode();869 let code_hash_len = code_hash.len();870 let rent_allowance = BalanceOf::<T>::max_value().encode();871 let rent_allowance_len = rent_allowance.len();872 let delta_keys = delta.iter().flat_map(|(key, _)| key).cloned().collect::<Vec<_>>();873874 let dest_offset = 0;875 let code_hash_offset = dest_offset + dest_len;876 let rent_allowance_offset = code_hash_offset + code_hash_len;877 let delta_keys_offset = rent_allowance_offset + rent_allowance_len;878879 let code = WasmModule::<T>::from(ModuleDefinition {880 memory: Some(ImportedMemory::max::<T>()),881 imported_functions: vec![ImportedFunction {882 name: "seal_restore_to",883 params: vec![884 ValueType::I32,885 ValueType::I32,886 ValueType::I32,887 ValueType::I32,888 ValueType::I32,889 ValueType::I32,890 ValueType::I32,891 ValueType::I32,892 ],893 return_type: None,894 }],895 data_segments: vec![896 DataSegment {897 offset: dest_offset as u32,898 value: dest,899 },900 DataSegment {901 offset: code_hash_offset as u32,902 value: code_hash,903 },904 DataSegment {905 offset: rent_allowance_offset as u32,906 value: rent_allowance,907 },908 DataSegment {909 offset: delta_keys_offset as u32,910 value: delta_keys,911 },912 ],913 call_body: Some(body::plain(vec![914 Instruction::I32Const(dest_offset as i32),915 Instruction::I32Const(dest_len as i32),916 Instruction::I32Const(code_hash_offset as i32),917 Instruction::I32Const(code_hash_len as i32),918 Instruction::I32Const(rent_allowance_offset as i32),919 Instruction::I32Const(rent_allowance_len as i32),920 Instruction::I32Const(delta_keys_offset as i32), 921 Instruction::I32Const(delta.len() as i32), 922 Instruction::Call(0),923 Instruction::End,924 ])),925 dummy_section: c * 1024,926 .. Default::default()927 });928929 let instance = Contract::<T>::with_caller(930 account("origin", 0, 0), code, vec![], Endow::Max931 )?;932 instance.store(&tombstone.storage)?;933 instance.store(&delta)?;934 System::<T>::set_block_number(System::<T>::block_number() + 1u32.into());935936 let origin = RawOrigin::Signed(instance.caller.clone());937 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])938 verify {939 tombstone.contract.alive_info()?;940 }941942 943 944 945 seal_random {946 let r in 0 .. API_BENCHMARK_BATCHES;947 let pages = code::max_pages::<T>();948 let subject_len = <CurrentSchedule<T>>::get().limits.subject_len;949 assert!(subject_len < 1024);950 let code = WasmModule::<T>::from(ModuleDefinition {951 memory: Some(ImportedMemory::max::<T>()),952 imported_functions: vec![ImportedFunction {953 name: "seal_random",954 params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],955 return_type: None,956 }],957 data_segments: vec![958 DataSegment {959 offset: 0,960 value: (pages * 64 * 1024 - subject_len - 4).to_le_bytes().to_vec(),961 },962 ],963 call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[964 Instruction::I32Const(4), 965 Instruction::I32Const(subject_len as i32), 966 Instruction::I32Const((subject_len + 4) as i32), 967 Instruction::I32Const(0), 968 Instruction::Call(0),969 ])),970 .. Default::default()971 });972 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;973 let origin = RawOrigin::Signed(instance.caller.clone());974 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])975976 977 978 seal_deposit_event {979 let r in 0 .. API_BENCHMARK_BATCHES;980 let code = WasmModule::<T>::from(ModuleDefinition {981 memory: Some(ImportedMemory::max::<T>()),982 imported_functions: vec![ImportedFunction {983 name: "seal_deposit_event",984 params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],985 return_type: None,986 }],987 call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[988 Instruction::I32Const(0), 989 Instruction::I32Const(0), 990 Instruction::I32Const(0), 991 Instruction::I32Const(0), 992 Instruction::Call(0),993 ])),994 .. Default::default()995 });996 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;997 let origin = RawOrigin::Signed(instance.caller.clone());998 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])9991000 1001 1002 1003 seal_deposit_event_per_topic_and_kb {1004 let t in 0 .. <CurrentSchedule<T>>::get().limits.event_topics;1005 let n in 0 .. T::MaxValueSize::get() / 1024;1006 let mut topics = (0..API_BENCHMARK_BATCH_SIZE)1007 .map(|n| (n * t..n * t + t).map(|i| T::Hashing::hash_of(&i)).collect::<Vec<_>>().encode())1008 .peekable();1009 let topics_len = topics.peek().map(|i| i.len()).unwrap_or(0);1010 let topics = topics.flatten().collect();1011 let code = WasmModule::<T>::from(ModuleDefinition {1012 memory: Some(ImportedMemory::max::<T>()),1013 imported_functions: vec![ImportedFunction {1014 name: "seal_deposit_event",1015 params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],1016 return_type: None,1017 }],1018 data_segments: vec![1019 DataSegment {1020 offset: 0,1021 value: topics,1022 },1023 ],1024 call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![1025 Counter(0, topics_len as u32), 1026 Regular(Instruction::I32Const(topics_len as i32)), 1027 Regular(Instruction::I32Const(0)), 1028 Regular(Instruction::I32Const((n * 1024) as i32)), 1029 Regular(Instruction::Call(0)),1030 ])),1031 .. Default::default()1032 });1033 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1034 let origin = RawOrigin::Signed(instance.caller.clone());1035 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])10361037 seal_set_rent_allowance {1038 let r in 0 .. API_BENCHMARK_BATCHES;1039 let allowance = caller_funding::<T>().encode();1040 let allowance_len = allowance.len();1041 let code = WasmModule::<T>::from(ModuleDefinition {1042 memory: Some(ImportedMemory { min_pages: 1, max_pages: 1 }),1043 imported_functions: vec![ImportedFunction {1044 name: "seal_set_rent_allowance",1045 params: vec![ValueType::I32, ValueType::I32],1046 return_type: None,1047 }],1048 data_segments: vec![1049 DataSegment {1050 offset: 0,1051 value: allowance,1052 },1053 ],1054 call_body: Some(body::repeated(r * API_BENCHMARK_BATCH_SIZE, &[1055 Instruction::I32Const(0), 1056 Instruction::I32Const(allowance_len as i32), 1057 Instruction::Call(0),1058 ])),1059 .. Default::default()1060 });1061 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1062 let origin = RawOrigin::Signed(instance.caller.clone());1063 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])10641065 1066 1067 1068 1069 seal_set_storage {1070 let r in 0 .. API_BENCHMARK_BATCHES;1071 let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)1072 .flat_map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())1073 .collect::<Vec<_>>();1074 let key_len = sp_std::mem::size_of::<<T::Hashing as sp_runtime::traits::Hash>::Output>();1075 let code = WasmModule::<T>::from(ModuleDefinition {1076 memory: Some(ImportedMemory::max::<T>()),1077 imported_functions: vec![ImportedFunction {1078 name: "seal_set_storage",1079 params: vec![ValueType::I32, ValueType::I32, ValueType::I32],1080 return_type: None,1081 }],1082 data_segments: vec![1083 DataSegment {1084 offset: 0,1085 value: keys,1086 },1087 ],1088 call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![1089 Counter(0, key_len as u32), 1090 Regular(Instruction::I32Const(0)), 1091 Regular(Instruction::I32Const(0)), 1092 Regular(Instruction::Call(0)),1093 ])),1094 .. Default::default()1095 });1096 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1097 let origin = RawOrigin::Signed(instance.caller.clone());1098 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])10991100 seal_set_storage_per_kb {1101 let n in 0 .. T::MaxValueSize::get() / 1024;1102 let key = T::Hashing::hash_of(&1u32).as_ref().to_vec();1103 let key_len = key.len();1104 let code = WasmModule::<T>::from(ModuleDefinition {1105 memory: Some(ImportedMemory::max::<T>()),1106 imported_functions: vec![ImportedFunction {1107 name: "seal_set_storage",1108 params: vec![ValueType::I32, ValueType::I32, ValueType::I32],1109 return_type: None,1110 }],1111 data_segments: vec![1112 DataSegment {1113 offset: 0,1114 value: key,1115 },1116 ],1117 call_body: Some(body::repeated(API_BENCHMARK_BATCH_SIZE, &[1118 Instruction::I32Const(0), 1119 Instruction::I32Const(0), 1120 Instruction::I32Const((n * 1024) as i32), 1121 Instruction::Call(0),1122 ])),1123 .. Default::default()1124 });1125 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1126 let origin = RawOrigin::Signed(instance.caller.clone());1127 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])11281129 1130 1131 1132 seal_clear_storage {1133 let r in 0 .. API_BENCHMARK_BATCHES;1134 let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)1135 .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())1136 .collect::<Vec<_>>();1137 let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();1138 let key_len = sp_std::mem::size_of::<<T::Hashing as sp_runtime::traits::Hash>::Output>();1139 let code = WasmModule::<T>::from(ModuleDefinition {1140 memory: Some(ImportedMemory::max::<T>()),1141 imported_functions: vec![ImportedFunction {1142 name: "seal_clear_storage",1143 params: vec![ValueType::I32],1144 return_type: None,1145 }],1146 data_segments: vec![1147 DataSegment {1148 offset: 0,1149 value: key_bytes,1150 },1151 ],1152 call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![1153 Counter(0, key_len as u32),1154 Regular(Instruction::Call(0)),1155 ])),1156 .. Default::default()1157 });1158 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1159 let trie_id = instance.alive_info()?.trie_id;1160 for key in keys {1161 Storage::<T>::write(1162 &instance.account_id,1163 &trie_id,1164 key.as_slice().try_into().map_err(|e| "Key has wrong length")?,1165 Some(vec![42; T::MaxValueSize::get() as usize])1166 )1167 .map_err(|_| "Failed to write to storage during setup.")?;1168 }1169 let origin = RawOrigin::Signed(instance.caller.clone());1170 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])11711172 1173 seal_get_storage {1174 let r in 0 .. API_BENCHMARK_BATCHES;1175 let keys = (0 .. r * API_BENCHMARK_BATCH_SIZE)1176 .map(|n| T::Hashing::hash_of(&n).as_ref().to_vec())1177 .collect::<Vec<_>>();1178 let key_len = sp_std::mem::size_of::<<T::Hashing as sp_runtime::traits::Hash>::Output>();1179 let key_bytes = keys.iter().flatten().cloned().collect::<Vec<_>>();1180 let key_bytes_len = key_bytes.len();1181 let code = WasmModule::<T>::from(ModuleDefinition {1182 memory: Some(ImportedMemory::max::<T>()),1183 imported_functions: vec![ImportedFunction {1184 name: "seal_get_storage",1185 params: vec![ValueType::I32, ValueType::I32, ValueType::I32],1186 return_type: Some(ValueType::I32),1187 }],1188 data_segments: vec![1189 DataSegment {1190 offset: 0,1191 value: key_bytes,1192 },1193 ],1194 call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![1195 Counter(0, key_len as u32), 1196 Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), 1197 Regular(Instruction::I32Const(key_bytes_len as i32)), 1198 Regular(Instruction::Call(0)),1199 Regular(Instruction::Drop),1200 ])),1201 .. Default::default()1202 });1203 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1204 let trie_id = instance.alive_info()?.trie_id;1205 for key in keys {1206 Storage::<T>::write(1207 &instance.account_id,1208 &trie_id,1209 key.as_slice().try_into().map_err(|e| "Key has wrong length")?,1210 Some(vec![])1211 )1212 .map_err(|_| "Failed to write to storage during setup.")?;1213 }1214 let origin = RawOrigin::Signed(instance.caller.clone());1215 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])12161217 seal_get_storage_per_kb {1218 let n in 0 .. T::MaxValueSize::get() / 1024;1219 let key = T::Hashing::hash_of(&1u32).as_ref().to_vec();1220 let key_len = key.len();1221 let code = WasmModule::<T>::from(ModuleDefinition {1222 memory: Some(ImportedMemory::max::<T>()),1223 imported_functions: vec![ImportedFunction {1224 name: "seal_get_storage",1225 params: vec![ValueType::I32, ValueType::I32, ValueType::I32],1226 return_type: Some(ValueType::I32),1227 }],1228 data_segments: vec![1229 DataSegment {1230 offset: 0,1231 value: key.clone(),1232 },1233 DataSegment {1234 offset: key_len as u32,1235 value: T::MaxValueSize::get().to_le_bytes().into(),1236 },1237 ],1238 call_body: Some(body::repeated(API_BENCHMARK_BATCH_SIZE, &[1239 1240 Instruction::I32Const(0), 1241 Instruction::I32Const((key_len + 4) as i32), 1242 Instruction::I32Const(key_len as i32), 1243 Instruction::Call(0),1244 Instruction::Drop,1245 ])),1246 .. Default::default()1247 });1248 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1249 let trie_id = instance.alive_info()?.trie_id;1250 Storage::<T>::write(1251 &instance.account_id,1252 &trie_id,1253 key.as_slice().try_into().map_err(|e| "Key has wrong length")?,1254 Some(vec![42u8; (n * 1024) as usize])1255 )1256 .map_err(|_| "Failed to write to storage during setup.")?;1257 let origin = RawOrigin::Signed(instance.caller.clone());1258 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])12591260 1261 seal_transfer {1262 let r in 0 .. API_BENCHMARK_BATCHES;1263 let accounts = (0..r * API_BENCHMARK_BATCH_SIZE)1264 .map(|i| account::<T::AccountId>("receiver", i, 0))1265 .collect::<Vec<_>>();1266 let account_len = accounts.get(0).map(|i| i.encode().len()).unwrap_or(0);1267 let account_bytes = accounts.iter().flat_map(|x| x.encode()).collect();1268 let value = Contracts::<T>::subsistence_threshold();1269 assert!(value > 0u32.into());1270 let value_bytes = value.encode();1271 let value_len = value_bytes.len();1272 let code = WasmModule::<T>::from(ModuleDefinition {1273 memory: Some(ImportedMemory::max::<T>()),1274 imported_functions: vec![ImportedFunction {1275 name: "seal_transfer",1276 params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],1277 return_type: Some(ValueType::I32),1278 }],1279 data_segments: vec![1280 DataSegment {1281 offset: 0,1282 value: value_bytes,1283 },1284 DataSegment {1285 offset: value_len as u32,1286 value: account_bytes,1287 },1288 ],1289 call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![1290 Counter(value_len as u32, account_len as u32), 1291 Regular(Instruction::I32Const(account_len as i32)), 1292 Regular(Instruction::I32Const(0)), 1293 Regular(Instruction::I32Const(value_len as i32)), 1294 Regular(Instruction::Call(0)),1295 Regular(Instruction::Drop),1296 ])),1297 .. Default::default()1298 });1299 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1300 let origin = RawOrigin::Signed(instance.caller.clone());1301 for account in &accounts {1302 assert_eq!(T::Currency::total_balance(account), 0u32.into());1303 }1304 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])1305 verify {1306 for account in &accounts {1307 assert_eq!(T::Currency::total_balance(account), value);1308 }1309 }13101311 1312 seal_call {1313 let r in 0 .. API_BENCHMARK_BATCHES;1314 let dummy_code = WasmModule::<T>::dummy_with_bytes(0);1315 let callees = (0..r * API_BENCHMARK_BATCH_SIZE)1316 .map(|i| Contract::with_index(i + 1, dummy_code.clone(), vec![], Endow::Max))1317 .collect::<Result<Vec<_>, _>>()?;1318 let callee_len = callees.get(0).map(|i| i.account_id.encode().len()).unwrap_or(0);1319 let callee_bytes = callees.iter().flat_map(|x| x.account_id.encode()).collect();1320 let value: BalanceOf<T> = 0u32.into();1321 let value_bytes = value.encode();1322 let value_len = value_bytes.len();1323 let code = WasmModule::<T>::from(ModuleDefinition {1324 memory: Some(ImportedMemory::max::<T>()),1325 imported_functions: vec![ImportedFunction {1326 name: "seal_call",1327 params: vec![1328 ValueType::I32,1329 ValueType::I32,1330 ValueType::I64,1331 ValueType::I32,1332 ValueType::I32,1333 ValueType::I32,1334 ValueType::I32,1335 ValueType::I32,1336 ValueType::I32,1337 ],1338 return_type: Some(ValueType::I32),1339 }],1340 data_segments: vec![1341 DataSegment {1342 offset: 0,1343 value: value_bytes,1344 },1345 DataSegment {1346 offset: value_len as u32,1347 value: callee_bytes,1348 },1349 ],1350 call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![1351 Counter(value_len as u32, callee_len as u32), 1352 Regular(Instruction::I32Const(callee_len as i32)), 1353 Regular(Instruction::I64Const(0)), 1354 Regular(Instruction::I32Const(0)), 1355 Regular(Instruction::I32Const(value_len as i32)), 1356 Regular(Instruction::I32Const(0)), 1357 Regular(Instruction::I32Const(0)), 1358 Regular(Instruction::I32Const(u32::max_value() as i32)), 1359 Regular(Instruction::I32Const(0)), 1360 Regular(Instruction::Call(0)),1361 Regular(Instruction::Drop),1362 ])),1363 .. Default::default()1364 });1365 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1366 let origin = RawOrigin::Signed(instance.caller.clone());1367 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])13681369 seal_call_per_code_transfer_input_output_kb {1370 let c in 0 .. T::MaxCodeSize::get() / 1024;1371 let t in 0 .. 1;1372 let i in 0 .. code::max_pages::<T>() * 64;1373 let o in 0 .. (code::max_pages::<T>() - 1) * 64;1374 let callee_code = WasmModule::<T>::from(ModuleDefinition {1375 memory: Some(ImportedMemory::max::<T>()),1376 imported_functions: vec![ImportedFunction {1377 name: "seal_return",1378 params: vec![1379 ValueType::I32,1380 ValueType::I32,1381 ValueType::I32,1382 ],1383 return_type: None,1384 }],1385 call_body: Some(body::plain(vec![1386 Instruction::I32Const(0), 1387 Instruction::I32Const(0), 1388 Instruction::I32Const((o * 1024) as i32), 1389 Instruction::Call(0),1390 Instruction::End,1391 ])),1392 dummy_section: c * 1024,1393 .. Default::default()1394 });1395 let callees = (0..API_BENCHMARK_BATCH_SIZE)1396 .map(|i| Contract::with_index(i + 1, callee_code.clone(), vec![], Endow::Max))1397 .collect::<Result<Vec<_>, _>>()?;1398 let callee_len = callees.get(0).map(|i| i.account_id.encode().len()).unwrap_or(0);1399 let callee_bytes = callees.iter().flat_map(|x| x.account_id.encode()).collect::<Vec<_>>();1400 let callees_len = callee_bytes.len();1401 let value: BalanceOf<T> = t.into();1402 let value_bytes = value.encode();1403 let value_len = value_bytes.len();1404 let code = WasmModule::<T>::from(ModuleDefinition {1405 memory: Some(ImportedMemory::max::<T>()),1406 imported_functions: vec![ImportedFunction {1407 name: "seal_call",1408 params: vec![1409 ValueType::I32,1410 ValueType::I32,1411 ValueType::I64,1412 ValueType::I32,1413 ValueType::I32,1414 ValueType::I32,1415 ValueType::I32,1416 ValueType::I32,1417 ValueType::I32,1418 ],1419 return_type: Some(ValueType::I32),1420 }],1421 data_segments: vec![1422 DataSegment {1423 offset: 0,1424 value: value_bytes,1425 },1426 DataSegment {1427 offset: value_len as u32,1428 value: callee_bytes,1429 },1430 DataSegment {1431 offset: (value_len + callees_len) as u32,1432 value: (o * 1024).to_le_bytes().into(),1433 },1434 ],1435 call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![1436 Counter(value_len as u32, callee_len as u32), 1437 Regular(Instruction::I32Const(callee_len as i32)), 1438 Regular(Instruction::I64Const(0)), 1439 Regular(Instruction::I32Const(0)), 1440 Regular(Instruction::I32Const(value_len as i32)), 1441 Regular(Instruction::I32Const(0)), 1442 Regular(Instruction::I32Const((i * 1024) as i32)), 1443 Regular(Instruction::I32Const((value_len + callees_len + 4) as i32)), 1444 Regular(Instruction::I32Const((value_len + callees_len) as i32)), 1445 Regular(Instruction::Call(0)),1446 Regular(Instruction::Drop),1447 ])),1448 .. Default::default()1449 });1450 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1451 let origin = RawOrigin::Signed(instance.caller.clone());1452 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])14531454 1455 seal_instantiate {1456 let r in 0 .. API_BENCHMARK_BATCHES;1457 let hashes = (0..r * API_BENCHMARK_BATCH_SIZE)1458 .map(|i| {1459 let code = WasmModule::<T>::from(ModuleDefinition {1460 memory: Some(ImportedMemory::max::<T>()),1461 call_body: Some(body::plain(vec![1462 1463 1464 Instruction::I32Const(i as i32),1465 Instruction::Drop,1466 Instruction::End,1467 ])),1468 .. Default::default()1469 });1470 Contracts::<T>::store_code_raw(code.code)?;1471 Ok(code.hash)1472 })1473 .collect::<Result<Vec<_>, &'static str>>()?;1474 let hash_len = hashes.get(0).map(|x| x.encode().len()).unwrap_or(0);1475 let hashes_bytes = hashes.iter().flat_map(|x| x.encode()).collect::<Vec<_>>();1476 let hashes_len = hashes_bytes.len();1477 let value = Endow::max::<T>() / (r * API_BENCHMARK_BATCH_SIZE + 2).into();1478 assert!(value > 0u32.into());1479 let value_bytes = value.encode();1480 let value_len = value_bytes.len();1481 let addr_len = sp_std::mem::size_of::<T::AccountId>();14821483 1484 let value_offset = 0;1485 let hashes_offset = value_offset + value_len;1486 let addr_len_offset = hashes_offset + hashes_len;1487 let addr_offset = addr_len_offset + addr_len;14881489 let code = WasmModule::<T>::from(ModuleDefinition {1490 memory: Some(ImportedMemory::max::<T>()),1491 imported_functions: vec![ImportedFunction {1492 name: "seal_instantiate",1493 params: vec![1494 ValueType::I32,1495 ValueType::I32,1496 ValueType::I64,1497 ValueType::I32,1498 ValueType::I32,1499 ValueType::I32,1500 ValueType::I32,1501 ValueType::I32,1502 ValueType::I32,1503 ValueType::I32,1504 ValueType::I32,1505 ValueType::I32,1506 ValueType::I32,1507 ],1508 return_type: Some(ValueType::I32),1509 }],1510 data_segments: vec![1511 DataSegment {1512 offset: value_offset as u32,1513 value: value_bytes,1514 },1515 DataSegment {1516 offset: hashes_offset as u32,1517 value: hashes_bytes,1518 },1519 DataSegment {1520 offset: addr_len_offset as u32,1521 value: addr_len.to_le_bytes().into(),1522 },1523 ],1524 call_body: Some(body::repeated_dyn(r * API_BENCHMARK_BATCH_SIZE, vec![1525 Counter(hashes_offset as u32, hash_len as u32), 1526 Regular(Instruction::I32Const(hash_len as i32)), 1527 Regular(Instruction::I64Const(0)), 1528 Regular(Instruction::I32Const(value_offset as i32)), 1529 Regular(Instruction::I32Const(value_len as i32)), 1530 Regular(Instruction::I32Const(0)), 1531 Regular(Instruction::I32Const(0)), 1532 Regular(Instruction::I32Const(addr_offset as i32)), 1533 Regular(Instruction::I32Const(addr_len_offset as i32)), 1534 Regular(Instruction::I32Const(u32::max_value() as i32)), 1535 Regular(Instruction::I32Const(0)), 1536 Regular(Instruction::I32Const(0)), 1537 Regular(Instruction::I32Const(0)), 1538 Regular(Instruction::Call(0)),1539 Regular(Instruction::Drop),1540 ])),1541 .. Default::default()1542 });1543 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1544 let origin = RawOrigin::Signed(instance.caller.clone());1545 let callee = instance.addr.clone();1546 let addresses = hashes1547 .iter()1548 .map(|hash| Contracts::<T>::contract_address(1549 &instance.account_id, hash, &[],1550 ))1551 .collect::<Vec<_>>();15521553 for addr in &addresses {1554 if let Some(_) = ContractInfoOf::<T>::get(&addr) {1555 return Err("Expected that contract does not exist at this point.");1556 }1557 }1558 }: call(origin, callee, 0u32.into(), Weight::max_value(), vec![])1559 verify {1560 for addr in &addresses {1561 ContractInfoOf::<T>::get(&addr).and_then(|c| c.get_alive())1562 .ok_or_else(|| "Contract should have been instantiated")?;1563 }1564 }15651566 seal_instantiate_per_code_input_output_salt_kb {1567 let c in 0 .. T::MaxCodeSize::get() / 1024;1568 let i in 0 .. (code::max_pages::<T>() - 1) * 64;1569 let o in 0 .. (code::max_pages::<T>() - 1) * 64;1570 let s in 0 .. (code::max_pages::<T>() - 1) * 64;1571 let callee_code = WasmModule::<T>::from(ModuleDefinition {1572 memory: Some(ImportedMemory::max::<T>()),1573 imported_functions: vec![ImportedFunction {1574 name: "seal_return",1575 params: vec![1576 ValueType::I32,1577 ValueType::I32,1578 ValueType::I32,1579 ],1580 return_type: None,1581 }],1582 deploy_body: Some(body::plain(vec![1583 Instruction::I32Const(0), 1584 Instruction::I32Const(0), 1585 Instruction::I32Const((o * 1024) as i32), 1586 Instruction::Call(0),1587 Instruction::End,1588 ])),1589 dummy_section: c * 1024,1590 .. Default::default()1591 });1592 let hash = callee_code.hash.clone();1593 let hash_bytes = callee_code.hash.encode();1594 let hash_len = hash_bytes.len();1595 Contracts::<T>::store_code_raw(callee_code.code)?;1596 let inputs = (0..API_BENCHMARK_BATCH_SIZE).map(|x| x.encode()).collect::<Vec<_>>();1597 let input_len = inputs.get(0).map(|x| x.len()).unwrap_or(0);1598 let input_bytes = inputs.iter().cloned().flatten().collect::<Vec<_>>();1599 let inputs_len = input_bytes.len();1600 let value = Endow::max::<T>() / (API_BENCHMARK_BATCH_SIZE + 2).into();1601 assert!(value > 0u32.into());1602 let value_bytes = value.encode();1603 let value_len = value_bytes.len();1604 let addr_len = sp_std::mem::size_of::<T::AccountId>();16051606 1607 let input_offset = 0;1608 let value_offset = inputs_len;1609 let hash_offset = value_offset + value_len;1610 let addr_len_offset = hash_offset + hash_len;1611 let output_len_offset = addr_len_offset + 4;1612 let output_offset = output_len_offset + 4;16131614 let code = WasmModule::<T>::from(ModuleDefinition {1615 memory: Some(ImportedMemory::max::<T>()),1616 imported_functions: vec![ImportedFunction {1617 name: "seal_instantiate",1618 params: vec![1619 ValueType::I32,1620 ValueType::I32,1621 ValueType::I64,1622 ValueType::I32,1623 ValueType::I32,1624 ValueType::I32,1625 ValueType::I32,1626 ValueType::I32,1627 ValueType::I32,1628 ValueType::I32,1629 ValueType::I32,1630 ValueType::I32,1631 ValueType::I32,1632 ],1633 return_type: Some(ValueType::I32),1634 }],1635 data_segments: vec![1636 DataSegment {1637 offset: input_offset as u32,1638 value: input_bytes,1639 },1640 DataSegment {1641 offset: value_offset as u32,1642 value: value_bytes,1643 },1644 DataSegment {1645 offset: hash_offset as u32,1646 value: hash_bytes,1647 },1648 DataSegment {1649 offset: addr_len_offset as u32,1650 value: (addr_len as u32).to_le_bytes().into(),1651 },1652 DataSegment {1653 offset: output_len_offset as u32,1654 value: (o * 1024).to_le_bytes().into(),1655 },1656 ],1657 call_body: Some(body::repeated_dyn(API_BENCHMARK_BATCH_SIZE, vec![1658 Regular(Instruction::I32Const(hash_offset as i32)), 1659 Regular(Instruction::I32Const(hash_len as i32)), 1660 Regular(Instruction::I64Const(0)), 1661 Regular(Instruction::I32Const(value_offset as i32)), 1662 Regular(Instruction::I32Const(value_len as i32)), 1663 Counter(input_offset as u32, input_len as u32), 1664 Regular(Instruction::I32Const((i * 1024).max(input_len as u32) as i32)), 1665 Regular(Instruction::I32Const((addr_len_offset + addr_len) as i32)), 1666 Regular(Instruction::I32Const(addr_len_offset as i32)), 1667 Regular(Instruction::I32Const(output_offset as i32)), 1668 Regular(Instruction::I32Const(output_len_offset as i32)), 1669 Counter(input_offset as u32, input_len as u32), 1670 Regular(Instruction::I32Const((s * 1024).max(input_len as u32) as i32)), 1671 Regular(Instruction::Call(0)),1672 Regular(Instruction::I32Eqz),1673 Regular(Instruction::If(BlockType::NoResult)),1674 Regular(Instruction::Nop),1675 Regular(Instruction::Else),1676 Regular(Instruction::Unreachable),1677 Regular(Instruction::End),1678 ])),1679 .. Default::default()1680 });1681 let instance = Contract::<T>::new(code, vec![], Endow::Max)?;1682 let origin = RawOrigin::Signed(instance.caller.clone());1683 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])16841685 1686 seal_hash_sha2_256 {1687 let r in 0 .. API_BENCHMARK_BATCHES;1688 let instance = Contract::<T>::new(WasmModule::hasher(1689 "seal_hash_sha2_256", r * API_BENCHMARK_BATCH_SIZE, 0,1690 ), vec![], Endow::Max)?;1691 let origin = RawOrigin::Signed(instance.caller.clone());1692 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])16931694 1695 seal_hash_sha2_256_per_kb {1696 let n in 0 .. code::max_pages::<T>() * 64;1697 let instance = Contract::<T>::new(WasmModule::hasher(1698 "seal_hash_sha2_256", API_BENCHMARK_BATCH_SIZE, n * 1024,1699 ), vec![], Endow::Max)?;1700 let origin = RawOrigin::Signed(instance.caller.clone());1701 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])17021703 1704 seal_hash_keccak_256 {1705 let r in 0 .. API_BENCHMARK_BATCHES;1706 let instance = Contract::<T>::new(WasmModule::hasher(1707 "seal_hash_keccak_256", r * API_BENCHMARK_BATCH_SIZE, 0,1708 ), vec![], Endow::Max)?;1709 let origin = RawOrigin::Signed(instance.caller.clone());1710 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])17111712 1713 seal_hash_keccak_256_per_kb {1714 let n in 0 .. code::max_pages::<T>() * 64;1715 let instance = Contract::<T>::new(WasmModule::hasher(1716 "seal_hash_keccak_256", API_BENCHMARK_BATCH_SIZE, n * 1024,1717 ), vec![], Endow::Max)?;1718 let origin = RawOrigin::Signed(instance.caller.clone());1719 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])17201721 1722 seal_hash_blake2_256 {1723 let r in 0 .. API_BENCHMARK_BATCHES;1724 let instance = Contract::<T>::new(WasmModule::hasher(1725 "seal_hash_blake2_256", r * API_BENCHMARK_BATCH_SIZE, 0,1726 ), vec![], Endow::Max)?;1727 let origin = RawOrigin::Signed(instance.caller.clone());1728 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])17291730 1731 seal_hash_blake2_256_per_kb {1732 let n in 0 .. code::max_pages::<T>() * 64;1733 let instance = Contract::<T>::new(WasmModule::hasher(1734 "seal_hash_blake2_256", API_BENCHMARK_BATCH_SIZE, n * 1024,1735 ), vec![], Endow::Max)?;1736 let origin = RawOrigin::Signed(instance.caller.clone());1737 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])17381739 1740 seal_hash_blake2_128 {1741 let r in 0 .. API_BENCHMARK_BATCHES;1742 let instance = Contract::<T>::new(WasmModule::hasher(1743 "seal_hash_blake2_128", r * API_BENCHMARK_BATCH_SIZE, 0,1744 ), vec![], Endow::Max)?;1745 let origin = RawOrigin::Signed(instance.caller.clone());1746 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])17471748 1749 seal_hash_blake2_128_per_kb {1750 let n in 0 .. code::max_pages::<T>() * 64;1751 let instance = Contract::<T>::new(WasmModule::hasher(1752 "seal_hash_blake2_128", API_BENCHMARK_BATCH_SIZE, n * 1024,1753 ), vec![], Endow::Max)?;1754 let origin = RawOrigin::Signed(instance.caller.clone());1755 }: call(origin, instance.addr, 0u32.into(), Weight::max_value(), vec![])17561757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 instr_i64const {1768 let r in 0 .. INSTR_BENCHMARK_BATCHES;1769 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1770 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![1771 RandomI64Repeated(1),1772 Regular(Instruction::Drop),1773 ])),1774 .. Default::default()1775 }));1776 }: {1777 sbox.invoke();1778 }17791780 1781 instr_i64load {1782 let r in 0 .. INSTR_BENCHMARK_BATCHES;1783 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1784 memory: Some(ImportedMemory::max::<T>()),1785 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![1786 RandomUnaligned(0, code::max_pages::<T>() * 64 * 1024 - 8),1787 Regular(Instruction::I64Load(3, 0)),1788 Regular(Instruction::Drop),1789 ])),1790 .. Default::default()1791 }));1792 }: {1793 sbox.invoke();1794 }17951796 1797 instr_i64store {1798 let r in 0 .. INSTR_BENCHMARK_BATCHES;1799 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1800 memory: Some(ImportedMemory::max::<T>()),1801 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![1802 RandomUnaligned(0, code::max_pages::<T>() * 64 * 1024 - 8),1803 RandomI64Repeated(1),1804 Regular(Instruction::I64Store(3, 0)),1805 ])),1806 .. Default::default()1807 }));1808 }: {1809 sbox.invoke();1810 }18111812 1813 instr_select {1814 let r in 0 .. INSTR_BENCHMARK_BATCHES;1815 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1816 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![1817 RandomI64Repeated(1),1818 RandomI64Repeated(1),1819 RandomI32(0, 2),1820 Regular(Instruction::Select),1821 Regular(Instruction::Drop),1822 ])),1823 .. Default::default()1824 }));1825 }: {1826 sbox.invoke();1827 }18281829 1830 instr_if {1831 let r in 0 .. INSTR_BENCHMARK_BATCHES;1832 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1833 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![1834 RandomI32(0, 2),1835 Regular(Instruction::If(BlockType::Value(ValueType::I64))),1836 RandomI64Repeated(1),1837 Regular(Instruction::Else),1838 RandomI64Repeated(1),1839 Regular(Instruction::End),1840 Regular(Instruction::Drop),1841 ])),1842 .. Default::default()1843 }));1844 }: {1845 sbox.invoke();1846 }18471848 1849 instr_br {1850 let r in 0 .. INSTR_BENCHMARK_BATCHES;1851 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1852 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![1853 Regular(Instruction::Block(BlockType::NoResult)),1854 Regular(Instruction::Block(BlockType::NoResult)),1855 Regular(Instruction::Block(BlockType::NoResult)),1856 Regular(Instruction::Br(1)),1857 RandomI64Repeated(1),1858 Regular(Instruction::Drop),1859 Regular(Instruction::End),1860 RandomI64Repeated(1),1861 Regular(Instruction::Drop),1862 Regular(Instruction::End),1863 RandomI64Repeated(1),1864 Regular(Instruction::Drop),1865 Regular(Instruction::End),1866 ])),1867 .. Default::default()1868 }));1869 }: {1870 sbox.invoke();1871 }18721873 1874 1875 1876 instr_br_if {1877 let r in 0 .. INSTR_BENCHMARK_BATCHES;1878 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1879 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![1880 Regular(Instruction::Block(BlockType::NoResult)),1881 Regular(Instruction::Block(BlockType::NoResult)),1882 Regular(Instruction::Block(BlockType::NoResult)),1883 RandomI32(0, 2),1884 Regular(Instruction::BrIf(1)),1885 RandomI64Repeated(1),1886 Regular(Instruction::Drop),1887 Regular(Instruction::End),1888 RandomI64Repeated(1),1889 Regular(Instruction::Drop),1890 Regular(Instruction::End),1891 RandomI64Repeated(1),1892 Regular(Instruction::Drop),1893 Regular(Instruction::End),1894 ])),1895 .. Default::default()1896 }));1897 }: {1898 sbox.invoke();1899 }19001901 1902 1903 instr_br_table {1904 let r in 0 .. INSTR_BENCHMARK_BATCHES;1905 let table = Box::new(parity_wasm::elements::BrTableData {1906 table: Box::new([0, 1, 2]),1907 default: 1,1908 });1909 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1910 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![1911 Regular(Instruction::Block(BlockType::NoResult)),1912 Regular(Instruction::Block(BlockType::NoResult)),1913 Regular(Instruction::Block(BlockType::NoResult)),1914 RandomI32(0, 4),1915 Regular(Instruction::BrTable(table)),1916 RandomI64Repeated(1),1917 Regular(Instruction::Drop),1918 Regular(Instruction::End),1919 RandomI64Repeated(1),1920 Regular(Instruction::Drop),1921 Regular(Instruction::End),1922 RandomI64Repeated(1),1923 Regular(Instruction::Drop),1924 Regular(Instruction::End),1925 ])),1926 .. Default::default()1927 }));1928 }: {1929 sbox.invoke();1930 }19311932 1933 instr_br_table_per_entry {1934 let e in 1 .. <CurrentSchedule<T>>::get().limits.br_table_size;1935 let entry: Vec<u32> = [0, 1].iter()1936 .cloned()1937 .cycle()1938 .take((e / 2) as usize).collect();1939 let table = Box::new(parity_wasm::elements::BrTableData {1940 table: entry.into_boxed_slice(),1941 default: 0,1942 });1943 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1944 call_body: Some(body::repeated_dyn(INSTR_BENCHMARK_BATCH_SIZE, vec![1945 Regular(Instruction::Block(BlockType::NoResult)),1946 Regular(Instruction::Block(BlockType::NoResult)),1947 Regular(Instruction::Block(BlockType::NoResult)),1948 RandomI32(0, (e + 1) as i32), 1949 Regular(Instruction::BrTable(table)),1950 RandomI64Repeated(1),1951 Regular(Instruction::Drop),1952 Regular(Instruction::End),1953 RandomI64Repeated(1),1954 Regular(Instruction::Drop),1955 Regular(Instruction::End),1956 RandomI64Repeated(1),1957 Regular(Instruction::Drop),1958 Regular(Instruction::End),1959 ])),1960 .. Default::default()1961 }));1962 }: {1963 sbox.invoke();1964 }19651966 1967 instr_call {1968 let r in 0 .. INSTR_BENCHMARK_BATCHES;1969 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1970 1971 1972 aux_body: Some(body::plain(vec![1973 Instruction::I64Const(42),1974 Instruction::Drop,1975 Instruction::End,1976 ])),1977 call_body: Some(body::repeated(r * INSTR_BENCHMARK_BATCH_SIZE, &[1978 Instruction::Call(2), 1979 ])),1980 inject_stack_metering: true,1981 .. Default::default()1982 }));1983 }: {1984 sbox.invoke();1985 }19861987 1988 instr_call_indirect {1989 let r in 0 .. INSTR_BENCHMARK_BATCHES;1990 let num_elements = <CurrentSchedule<T>>::get().limits.table_size;1991 use self::code::TableSegment;1992 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1993 1994 1995 aux_body: Some(body::plain(vec![1996 Instruction::I64Const(42),1997 Instruction::Drop,1998 Instruction::End,1999 ])),2000 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![2001 RandomI32(0, num_elements as i32),2002 Regular(Instruction::CallIndirect(0, 0)), 2003 ])),2004 inject_stack_metering: true,2005 table: Some(TableSegment {2006 num_elements,2007 function_index: 2, 2008 }),2009 .. Default::default()2010 }));2011 }: {2012 sbox.invoke();2013 }20142015 2016 2017 2018 2019 instr_call_indirect_per_param {2020 let p in 0 .. <CurrentSchedule<T>>::get().limits.parameters;2021 let num_elements = <CurrentSchedule<T>>::get().limits.table_size;2022 use self::code::TableSegment;2023 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {2024 2025 2026 aux_body: Some(body::plain(vec![2027 Instruction::I64Const(42),2028 Instruction::Drop,2029 Instruction::End,2030 ])),2031 aux_arg_num: p,2032 call_body: Some(body::repeated_dyn(INSTR_BENCHMARK_BATCH_SIZE, vec![2033 RandomI64Repeated(p as usize),2034 RandomI32(0, num_elements as i32),2035 Regular(Instruction::CallIndirect(p.min(1), 0)), 2036 ])),2037 inject_stack_metering: true,2038 table: Some(TableSegment {2039 num_elements,2040 function_index: 2, 2041 }),2042 .. Default::default()2043 }));2044 }: {2045 sbox.invoke();2046 }20472048 2049 instr_local_get {2050 let r in 0 .. INSTR_BENCHMARK_BATCHES;2051 let max_locals = <CurrentSchedule<T>>::get().limits.stack_height;2052 let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![2053 RandomGetLocal(0, max_locals),2054 Regular(Instruction::Drop),2055 ]);2056 body::inject_locals(&mut call_body, max_locals);2057 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {2058 call_body: Some(call_body),2059 .. Default::default()2060 }));2061 }: {2062 sbox.invoke();2063 }20642065 2066 instr_local_set {2067 let r in 0 .. INSTR_BENCHMARK_BATCHES;2068 let max_locals = <CurrentSchedule<T>>::get().limits.stack_height;2069 let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![2070 RandomI64Repeated(1),2071 RandomSetLocal(0, max_locals),2072 ]);2073 body::inject_locals(&mut call_body, max_locals);2074 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {2075 call_body: Some(call_body),2076 .. Default::default()2077 }));2078 }: {2079 sbox.invoke();2080 }20812082 2083 instr_local_tee {2084 let r in 0 .. INSTR_BENCHMARK_BATCHES;2085 let max_locals = <CurrentSchedule<T>>::get().limits.stack_height;2086 let mut call_body = body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![2087 RandomI64Repeated(1),2088 RandomTeeLocal(0, max_locals),2089 Regular(Instruction::Drop),2090 ]);2091 body::inject_locals(&mut call_body, max_locals);2092 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {2093 call_body: Some(call_body),2094 .. Default::default()2095 }));2096 }: {2097 sbox.invoke();2098 }20992100 2101 instr_global_get {2102 let r in 0 .. INSTR_BENCHMARK_BATCHES;2103 let max_globals = <CurrentSchedule<T>>::get().limits.globals;2104 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {2105 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![2106 RandomGetGlobal(0, max_globals),2107 Regular(Instruction::Drop),2108 ])),2109 num_globals: max_globals,2110 .. Default::default()2111 }));2112 }: {2113 sbox.invoke();2114 }21152116 2117 instr_global_set {2118 let r in 0 .. INSTR_BENCHMARK_BATCHES;2119 let max_globals = <CurrentSchedule<T>>::get().limits.globals;2120 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {2121 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![2122 RandomI64Repeated(1),2123 RandomSetGlobal(0, max_globals),2124 ])),2125 num_globals: max_globals,2126 .. Default::default()2127 }));2128 }: {2129 sbox.invoke();2130 }21312132 2133 instr_memory_current {2134 let r in 0 .. INSTR_BENCHMARK_BATCHES;2135 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {2136 memory: Some(ImportedMemory::max::<T>()),2137 call_body: Some(body::repeated(r * INSTR_BENCHMARK_BATCH_SIZE, &[2138 Instruction::CurrentMemory(0),2139 Instruction::Drop2140 ])),2141 .. Default::default()2142 }));2143 }: {2144 sbox.invoke();2145 }21462147 2148 2149 2150 2151 2152 instr_memory_grow {2153 let r in 0 .. 1;2154 let max_pages = ImportedMemory::max::<T>().max_pages;2155 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {2156 memory: Some(ImportedMemory {2157 min_pages: 0,2158 max_pages,2159 }),2160 call_body: Some(body::repeated(r * max_pages, &[2161 Instruction::I32Const(1),2162 Instruction::GrowMemory(0),2163 Instruction::Drop,2164 ])),2165 .. Default::default()2166 }));2167 }: {2168 sbox.invoke();2169 }21702171 2172 21732174 instr_i64clz {2175 let r in 0 .. INSTR_BENCHMARK_BATCHES;2176 let mut sbox = Sandbox::from(&WasmModule::<T>::unary_instr(2177 Instruction::I64Clz,2178 r * INSTR_BENCHMARK_BATCH_SIZE,2179 ));2180 }: {2181 sbox.invoke();2182 }21832184 instr_i64ctz {2185 let r in 0 .. INSTR_BENCHMARK_BATCHES;2186 let mut sbox = Sandbox::from(&WasmModule::<T>::unary_instr(2187 Instruction::I64Ctz,2188 r * INSTR_BENCHMARK_BATCH_SIZE,2189 ));2190 }: {2191 sbox.invoke();2192 }21932194 instr_i64popcnt {2195 let r in 0 .. INSTR_BENCHMARK_BATCHES;2196 let mut sbox = Sandbox::from(&WasmModule::<T>::unary_instr(2197 Instruction::I64Popcnt,2198 r * INSTR_BENCHMARK_BATCH_SIZE,2199 ));2200 }: {2201 sbox.invoke();2202 }22032204 instr_i64eqz {2205 let r in 0 .. INSTR_BENCHMARK_BATCHES;2206 let mut sbox = Sandbox::from(&WasmModule::<T>::unary_instr(2207 Instruction::I64Eqz,2208 r * INSTR_BENCHMARK_BATCH_SIZE,2209 ));2210 }: {2211 sbox.invoke();2212 }22132214 instr_i64extendsi32 {2215 let r in 0 .. INSTR_BENCHMARK_BATCHES;2216 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {2217 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![2218 RandomI32Repeated(1),2219 Regular(Instruction::I64ExtendSI32),2220 Regular(Instruction::Drop),2221 ])),2222 .. Default::default()2223 }));2224 }: {2225 sbox.invoke();2226 }22272228 instr_i64extendui32 {2229 let r in 0 .. INSTR_BENCHMARK_BATCHES;2230 let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {2231 call_body: Some(body::repeated_dyn(r * INSTR_BENCHMARK_BATCH_SIZE, vec![2232 RandomI32Repeated(1),2233 Regular(Instruction::I64ExtendUI32),2234 Regular(Instruction::Drop),2235 ])),2236 .. Default::default()2237 }));2238 }: {2239 sbox.invoke();2240 }22412242 instr_i32wrapi64 {2243 let r in 0 .. INSTR_BENCHMARK_BATCHES;2244 let mut sbox = Sandbox::from(&WasmModule::<T>::unary_instr(2245 Instruction::I32WrapI64,2246 r * INSTR_BENCHMARK_BATCH_SIZE,2247 ));2248 }: {2249 sbox.invoke();2250 }22512252 2253 22542255 instr_i64eq {2256 let r in 0 .. INSTR_BENCHMARK_BATCHES;2257 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2258 Instruction::I64Eq,2259 r * INSTR_BENCHMARK_BATCH_SIZE,2260 ));2261 }: {2262 sbox.invoke();2263 }22642265 instr_i64ne {2266 let r in 0 .. INSTR_BENCHMARK_BATCHES;2267 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2268 Instruction::I64Ne,2269 r * INSTR_BENCHMARK_BATCH_SIZE,2270 ));2271 }: {2272 sbox.invoke();2273 }22742275 instr_i64lts {2276 let r in 0 .. INSTR_BENCHMARK_BATCHES;2277 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2278 Instruction::I64LtS,2279 r * INSTR_BENCHMARK_BATCH_SIZE,2280 ));2281 }: {2282 sbox.invoke();2283 }22842285 instr_i64ltu {2286 let r in 0 .. INSTR_BENCHMARK_BATCHES;2287 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2288 Instruction::I64LtU,2289 r * INSTR_BENCHMARK_BATCH_SIZE,2290 ));2291 }: {2292 sbox.invoke();2293 }22942295 instr_i64gts {2296 let r in 0 .. INSTR_BENCHMARK_BATCHES;2297 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2298 Instruction::I64GtS,2299 r * INSTR_BENCHMARK_BATCH_SIZE,2300 ));2301 }: {2302 sbox.invoke();2303 }23042305 instr_i64gtu {2306 let r in 0 .. INSTR_BENCHMARK_BATCHES;2307 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2308 Instruction::I64GtU,2309 r * INSTR_BENCHMARK_BATCH_SIZE,2310 ));2311 }: {2312 sbox.invoke();2313 }23142315 instr_i64les {2316 let r in 0 .. INSTR_BENCHMARK_BATCHES;2317 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2318 Instruction::I64LeS,2319 r * INSTR_BENCHMARK_BATCH_SIZE,2320 ));2321 }: {2322 sbox.invoke();2323 }23242325 instr_i64leu {2326 let r in 0 .. INSTR_BENCHMARK_BATCHES;2327 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2328 Instruction::I64LeU,2329 r * INSTR_BENCHMARK_BATCH_SIZE,2330 ));2331 }: {2332 sbox.invoke();2333 }23342335 instr_i64ges {2336 let r in 0 .. INSTR_BENCHMARK_BATCHES;2337 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2338 Instruction::I64GeS,2339 r * INSTR_BENCHMARK_BATCH_SIZE,2340 ));2341 }: {2342 sbox.invoke();2343 }23442345 instr_i64geu {2346 let r in 0 .. INSTR_BENCHMARK_BATCHES;2347 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2348 Instruction::I64GeU,2349 r * INSTR_BENCHMARK_BATCH_SIZE,2350 ));2351 }: {2352 sbox.invoke();2353 }23542355 instr_i64add {2356 let r in 0 .. INSTR_BENCHMARK_BATCHES;2357 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2358 Instruction::I64Add,2359 r * INSTR_BENCHMARK_BATCH_SIZE,2360 ));2361 }: {2362 sbox.invoke();2363 }23642365 instr_i64sub {2366 let r in 0 .. INSTR_BENCHMARK_BATCHES;2367 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2368 Instruction::I64Sub,2369 r * INSTR_BENCHMARK_BATCH_SIZE,2370 ));2371 }: {2372 sbox.invoke();2373 }23742375 instr_i64mul {2376 let r in 0 .. INSTR_BENCHMARK_BATCHES;2377 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2378 Instruction::I64Mul,2379 r * INSTR_BENCHMARK_BATCH_SIZE,2380 ));2381 }: {2382 sbox.invoke();2383 }23842385 instr_i64divs {2386 let r in 0 .. INSTR_BENCHMARK_BATCHES;2387 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2388 Instruction::I64DivS,2389 r * INSTR_BENCHMARK_BATCH_SIZE,2390 ));2391 }: {2392 sbox.invoke();2393 }23942395 instr_i64divu {2396 let r in 0 .. INSTR_BENCHMARK_BATCHES;2397 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2398 Instruction::I64DivU,2399 r * INSTR_BENCHMARK_BATCH_SIZE,2400 ));2401 }: {2402 sbox.invoke();2403 }24042405 instr_i64rems {2406 let r in 0 .. INSTR_BENCHMARK_BATCHES;2407 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2408 Instruction::I64RemS,2409 r * INSTR_BENCHMARK_BATCH_SIZE,2410 ));2411 }: {2412 sbox.invoke();2413 }24142415 instr_i64remu {2416 let r in 0 .. INSTR_BENCHMARK_BATCHES;2417 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2418 Instruction::I64RemU,2419 r * INSTR_BENCHMARK_BATCH_SIZE,2420 ));2421 }: {2422 sbox.invoke();2423 }24242425 instr_i64and {2426 let r in 0 .. INSTR_BENCHMARK_BATCHES;2427 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2428 Instruction::I64And,2429 r * INSTR_BENCHMARK_BATCH_SIZE,2430 ));2431 }: {2432 sbox.invoke();2433 }24342435 instr_i64or {2436 let r in 0 .. INSTR_BENCHMARK_BATCHES;2437 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2438 Instruction::I64Or,2439 r * INSTR_BENCHMARK_BATCH_SIZE,2440 ));2441 }: {2442 sbox.invoke();2443 }24442445 instr_i64xor {2446 let r in 0 .. INSTR_BENCHMARK_BATCHES;2447 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2448 Instruction::I64Xor,2449 r * INSTR_BENCHMARK_BATCH_SIZE,2450 ));2451 }: {2452 sbox.invoke();2453 }24542455 instr_i64shl {2456 let r in 0 .. INSTR_BENCHMARK_BATCHES;2457 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2458 Instruction::I64Shl,2459 r * INSTR_BENCHMARK_BATCH_SIZE,2460 ));2461 }: {2462 sbox.invoke();2463 }24642465 instr_i64shrs {2466 let r in 0 .. INSTR_BENCHMARK_BATCHES;2467 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2468 Instruction::I64ShrS,2469 r * INSTR_BENCHMARK_BATCH_SIZE,2470 ));2471 }: {2472 sbox.invoke();2473 }24742475 instr_i64shru {2476 let r in 0 .. INSTR_BENCHMARK_BATCHES;2477 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2478 Instruction::I64ShrU,2479 r * INSTR_BENCHMARK_BATCH_SIZE,2480 ));2481 }: {2482 sbox.invoke();2483 }24842485 instr_i64rotl {2486 let r in 0 .. INSTR_BENCHMARK_BATCHES;2487 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2488 Instruction::I64Rotl,2489 r * INSTR_BENCHMARK_BATCH_SIZE,2490 ));2491 }: {2492 sbox.invoke();2493 }24942495 instr_i64rotr {2496 let r in 0 .. INSTR_BENCHMARK_BATCHES;2497 let mut sbox = Sandbox::from(&WasmModule::<T>::binary_instr(2498 Instruction::I64Rotr,2499 r * INSTR_BENCHMARK_BATCH_SIZE,2500 ));2501 }: {2502 sbox.invoke();2503 }25042505 2506 2507 2508 2509 2510 2511 #[extra]2512 print_schedule {2513 #[cfg(feature = "std")]2514 {2515 let weight_per_key = T::WeightInfo::on_initialize_per_trie_key(1) -2516 T::WeightInfo::on_initialize_per_trie_key(0);2517 let weight_per_queue_item = T::WeightInfo::on_initialize_per_queue_item(1) -2518 T::WeightInfo::on_initialize_per_queue_item(0);2519 let weight_limit = T::DeletionWeightLimit::get();2520 let queue_depth: u64 = T::DeletionQueueDepth::get().into();2521 println!("{:#?}", Schedule::<T>::default());2522 println!("###############################################");2523 println!("Lazy deletion throughput per block (empty queue, full queue): {}, {}",2524 weight_limit / weight_per_key,2525 (weight_limit - weight_per_queue_item * queue_depth) / weight_per_key,2526 );2527 }2528 #[cfg(not(feature = "std"))]2529 return Err("Run this bench with a native runtime in order to see the schedule.");2530 }: {}2531}25322533impl_benchmark_test_suite!(2534 Contracts,2535 crate::tests::ExtBuilder::default().build(),2536 crate::tests::Test,2537);