git.delta.rocks / unique-network / refs/commits / e8fdadb89923

difftreelog

source

pallets/contracts/src/benchmarking/mod.rs84.0 KiBsourcehistory
1// This file is part of Substrate.23// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.4// SPDX-License-Identifier: Apache-2.056// Licensed under the Apache License, Version 2.0 (the "License");7// you may not use this file except in compliance with the License.8// You may obtain a copy of the License at9//10// 	http://www.apache.org/licenses/LICENSE-2.011//12// Unless required by applicable law or agreed to in writing, software13// distributed under the License is distributed on an "AS IS" BASIS,14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.15// See the License for the specific language governing permissions and16// limitations under the License.1718//! Benchmarks for the contracts pallet1920#![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;5253/// How many batches we do per API benchmark.54const API_BENCHMARK_BATCHES: u32 = 20;5556/// How many batches we do per Instruction benchmark.57const INSTR_BENCHMARK_BATCHES: u32 = 1;5859/// An instantiated and deployed contract.60struct 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}6768/// Describes how much balance should be transferred on instantiate from the caller.69enum Endow {70	/// Endow the contract with a maximum amount of balance. This value is described by71	/// `Contract::max_endowment`.72	Max,73	/// Endow so that the amount of balance that is transferred is big but not so big74	/// to offset the rent payment. This is needed in order to test rent collection.75	CollectRent,76}7778impl Endow {79	/// The maximum amount of balance a caller can transfer without being brought below80	/// the existential deposit. This assumes that every caller is funded with the amount81	/// returned by `caller_funding`.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	/// Create new contract and use a default account id as instantiator.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	/// Create new contract and use an account id derived from the supplied index as instantiator.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	/// Create new contract and use the supplied `caller` as instantiator.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				// storage_size cannot be zero because otherwise a contract that is just above121				// the subsistence threshold does not pay rent given a large enough subsistence122				// threshold. But we need rent payments to occur in order to benchmark for worst cases.123				let storage_size = u32::max_value() / 10;124125				// Endowment should be large but not as large to inhibit rent payments.126				// Balance will only cover half the storage127				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		// The default block number is zero. The benchmarking system bumps the block number140		// to one for the benchmarking closure when it is set to zero. In order to prevent this141		// undesired implicit bump (which messes with rent collection), we do the bump ourselves142		// in the setup closure so that both the instantiate and subsequent call are run with the143		// same block number.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	/// Store the supplied storage items into this contracts storage.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	/// Get the `AliveContractInfo` of the `addr` or an error if it is no longer alive.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	/// Get the `AliveContractInfo` of this contract or an error if it is no longer alive.194	fn alive_info(&self) -> Result<AliveContractInfo<T>, &'static str> {195		Self::address_alive_info(&self.account_id)196	}197198	/// Return an error if this contract is no tombstone.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	/// Get the block number when this contract will be evicted. Returns an error when207	/// the rent collection won't happen because the contract has to much endowment.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}217218/// A `Contract` that contains some storage items.219///220/// This is used to benchmark contract destruction and resurection. Those operations'221/// weight depend on the amount of storage accumulated.222struct ContractWithStorage<T: Config> {223	/// The contract that was evicted.224	contract: Contract<T>,225	/// The storage the contract held when it was avicted.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	/// Same as [`Self::with_code`] but with dummy contract code.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	/// Create and evict a new contract with the supplied storage item count and size each.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	/// Increase the system block number so that this contract is eligible for eviction.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	/// Evict this contract.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}265266/// Generate `stor_num` storage items. Each has the size `stor_size`.267fn 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}281282/// The funding that each account that either calls or instantiates contracts is funded with.283fn 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	// The base weight without any actual work performed apart from the setup costs.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	// This benchmarks the additional weight that is charged when a contract is executed the318	// first time after a new schedule was deployed: For every new schedule a contract needs319	// to re-run the instrumentation once.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	// This extrinsic is pretty much constant as it is only a simple setter.331	update_schedule {332		let schedule = Schedule {333			version: 1,334			.. Default::default()335		};336	}: _(RawOrigin::Root, schedule)337338	// This constructs a contract that is maximal expensive to instrument.339	// It creates a maximum number of metering blocks per byte.340	// The size of the salt influences the runtime because is is hashed in order to341	// determine the contract address.342	// `c`: Size of the code in kilobytes.343	// `s`: Size of the salt in kilobytes.344	//345	// # Note346	//347	// We cannot let `c` grow to the maximum code size because the code is not allowed348	// to be larger than the maximum size **after instrumentation**.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		// endowment was removed from the caller362		assert_eq!(T::Currency::free_balance(&caller), caller_funding::<T>() - endowment);363		// contract has the full endowment because no rent collection happended364		assert_eq!(T::Currency::free_balance(&addr), endowment);365		// instantiate should leave a alive contract366		Contract::<T>::address_alive_info(&addr)?;367	}368369	// Instantiate uses a dummy contract constructor to measure the overhead of the instantiate.370	// `c`: Size of the code in kilobytes.371	// `s`: Size of the salt in kilobytes.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		// endowment was removed from the caller386		assert_eq!(T::Currency::free_balance(&caller), caller_funding::<T>() - endowment);387		// contract has the full endowment because no rent collection happended388		assert_eq!(T::Currency::free_balance(&addr), endowment);389		// instantiate should leave a alive contract390		Contract::<T>::address_alive_info(&addr)?;391	}392393	// We just call a dummy contract to measure to overhead of the call extrinsic.394	// The size of the data has no influence on the costs of this extrinsic as long as the contract395	// won't call `seal_input` in its constructor to copy the data to contract memory.396	// The dummy contract used here does not do this. The costs for the data copy is billed as397	// part of `seal_input`.398	// `c`: Size of the code in kilobytes.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		// trigger rent collection for worst case performance of call410		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		// endowment and value transfered via call should be removed from the caller415		assert_eq!(416			T::Currency::free_balance(&instance.caller),417			caller_funding::<T>() - instance.endowment - value,418		);419		// rent should have lowered the amount of balance of the contract420		assert!(T::Currency::free_balance(&instance.account_id) < before + value);421		// but it should not have been evicted by the rent collection422		instance.alive_info()?;423	}424425	// We benchmark the costs for sucessfully evicting an empty contract.426	// The actual costs are depending on how many storage items the evicted contract427	// does have. However, those costs are not to be payed by the sender but428	// will be distributed over multiple blocks using a scheduler. Otherwise there is429	// no incentive to remove large contracts when the removal is more expensive than430	// the reward for removing them.431	// `c`: Size of the code of the contract that should be evicted.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		// instantiate should leave us with an alive contract441		instance.alive_info()?;442443		// generate enough rent so that the contract is evicted444		System::<T>::set_block_number(445			instance.eviction_at()? + T::SignedClaimHandicap::get() + 5u32.into()446		);447	}: _(origin, account_id, None)448	verify {449		// the claim surcharge should have evicted the contract450		instance.ensure_tombstone()?;451452		// the caller should get the reward for being a good snitch453		// this is capped by the maximum amount of rent payed. So we only now that it should454		// have increased by at most the surcharge reward.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	// We cannot call seal_input multiple times. Therefore our weight determination is not599	// as precise as with other APIs. Because this function can only be called once per600	// contract it cannot be used for Dos.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), // ptr where to store output618				Instruction::I32Const(0), // ptr to length619				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), // ptr where to store output646				Instruction::I32Const(0), // ptr to length647				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	// The same argument as for `seal_input` is true here.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), // flags669				Instruction::I32Const(0), // data_ptr670				Instruction::I32Const(0), // data_len671				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), // flags690				Instruction::I32Const(0), // data_ptr691				Instruction::I32Const((n * 1024) as i32), // data_len692				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	// The same argument as for `seal_input` is true here.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), // beneficiary_ptr722				Instruction::I32Const(beneficiary_len as i32), // beneficiary_len723				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), // beneficiary_ptr759				Instruction::I32Const(beneficiary_len as i32), // beneficiary_len760				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		// Restore just moves the trie id from origin to destination and therefore779		// does not depend on the size of the destination contract. However, to not780		// trigger any edge case we won't use an empty contract as destination.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), // delta_ptr833				Instruction::I32Const(0), // delta_count834				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	// `c`: Code size of caller contract854	// `t`: Code size of tombstone contract855	// `d`: Number of supplied delta keys856	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), // delta_ptr921				Instruction::I32Const(delta.len() as i32), // delta_count922				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	// We benchmark only for the maximum subject length. We assume that this is some lowish943	// number (< 1 KB). Therefore we are not overcharging too much in case a smaller subject is944	// used.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), // subject_ptr965				Instruction::I32Const(subject_len as i32), // subject_len966				Instruction::I32Const((subject_len + 4) as i32), // out_ptr967				Instruction::I32Const(0),	// out_len_ptr968				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	// Overhead of calling the function without any topic.977	// We benchmark for the worst case (largest event).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), // topics_ptr989				Instruction::I32Const(0), // topics_len990				Instruction::I32Const(0), // data_ptr991				Instruction::I32Const(0), // data_len992				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	// Benchmark the overhead that topics generate.1001	// `t`: Number of topics1002	// `n`: Size of event payload in kb1003	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), // topics_ptr1026				Regular(Instruction::I32Const(topics_len as i32)), // topics_len1027				Regular(Instruction::I32Const(0)), // data_ptr1028				Regular(Instruction::I32Const((n * 1024) as i32)), // data_len1029				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), // value_ptr1056				Instruction::I32Const(allowance_len as i32), // value_len1057				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	// Only the overhead of calling the function itself with minimal arguments.1066	// The contract is a bit more complex because I needs to use different keys in order1067	// to generate unique storage accesses. However, it is still dominated by the storage1068	// accesses.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), // key_ptr1090				Regular(Instruction::I32Const(0)), // value_ptr1091				Regular(Instruction::I32Const(0)), // value_len1092				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), // key_ptr1119				Instruction::I32Const(0), // value_ptr1120				Instruction::I32Const((n * 1024) as i32), // value_len1121				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	// Similar to seal_set_storage. However, we store all the keys that we are about to1130	// delete beforehand in order to prevent any optimizations that could occur when1131	// deleting a non existing key.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	// We make sure that all storage accesses are to unique keys.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), // key_ptr1196				Regular(Instruction::I32Const((key_bytes_len + 4) as i32)), // out_ptr1197				Regular(Instruction::I32Const(key_bytes_len as i32)), // out_len_ptr1198				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				// call at key_ptr1240				Instruction::I32Const(0), // key_ptr1241				Instruction::I32Const((key_len + 4) as i32), // out_ptr1242				Instruction::I32Const(key_len as i32), // out_len_ptr1243				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	// We transfer to unique accounts.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), // account_ptr1291				Regular(Instruction::I32Const(account_len as i32)), // account_len1292				Regular(Instruction::I32Const(0)), // value_ptr1293				Regular(Instruction::I32Const(value_len as i32)), // value_len1294				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	// We call unique accounts.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), // callee_ptr1352				Regular(Instruction::I32Const(callee_len as i32)), // callee_len1353				Regular(Instruction::I64Const(0)), // gas1354				Regular(Instruction::I32Const(0)), // value_ptr1355				Regular(Instruction::I32Const(value_len as i32)), // value_len1356				Regular(Instruction::I32Const(0)), // input_data_ptr1357				Regular(Instruction::I32Const(0)), // input_data_len1358				Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr1359				Regular(Instruction::I32Const(0)), // output_len_ptr1360				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), // flags1387				Instruction::I32Const(0), // data_ptr1388				Instruction::I32Const((o * 1024) as i32), // data_len1389				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), // callee_ptr1437				Regular(Instruction::I32Const(callee_len as i32)), // callee_len1438				Regular(Instruction::I64Const(0)), // gas1439				Regular(Instruction::I32Const(0)), // value_ptr1440				Regular(Instruction::I32Const(value_len as i32)), // value_len1441				Regular(Instruction::I32Const(0)), // input_data_ptr1442				Regular(Instruction::I32Const((i * 1024) as i32)), // input_data_len1443				Regular(Instruction::I32Const((value_len + callees_len + 4) as i32)), // output_ptr1444				Regular(Instruction::I32Const((value_len + callees_len) as i32)), // output_len_ptr1445				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	// We assume that every instantiate sends at least the subsistence amount.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						// we need to add this in order to make contracts unique1463						// so that they can be deployed from the same sender1464						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		// offsets where to place static data in contract memory1484		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), // code_hash_ptr1526				Regular(Instruction::I32Const(hash_len as i32)), // code_hash_len1527				Regular(Instruction::I64Const(0)), // gas1528				Regular(Instruction::I32Const(value_offset as i32)), // value_ptr1529				Regular(Instruction::I32Const(value_len as i32)), // value_len1530				Regular(Instruction::I32Const(0)), // input_data_ptr1531				Regular(Instruction::I32Const(0)), // input_data_len1532				Regular(Instruction::I32Const(addr_offset as i32)), // address_ptr1533				Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr1534				Regular(Instruction::I32Const(u32::max_value() as i32)), // output_ptr1535				Regular(Instruction::I32Const(0)), // output_len_ptr1536				Regular(Instruction::I32Const(0)), // salt_ptr1537				Regular(Instruction::I32Const(0)), // salt_ptr_len1538				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), // flags1584				Instruction::I32Const(0), // data_ptr1585				Instruction::I32Const((o * 1024) as i32), // data_len1586				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		// offsets where to place static data in contract memory1607		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)), // code_hash_ptr1659				Regular(Instruction::I32Const(hash_len as i32)), // code_hash_len1660				Regular(Instruction::I64Const(0)), // gas1661				Regular(Instruction::I32Const(value_offset as i32)), // value_ptr1662				Regular(Instruction::I32Const(value_len as i32)), // value_len1663				Counter(input_offset as u32, input_len as u32), // input_data_ptr1664				Regular(Instruction::I32Const((i * 1024).max(input_len as u32) as i32)), // input_data_len1665				Regular(Instruction::I32Const((addr_len_offset + addr_len) as i32)), // address_ptr1666				Regular(Instruction::I32Const(addr_len_offset as i32)), // address_len_ptr1667				Regular(Instruction::I32Const(output_offset as i32)), // output_ptr1668				Regular(Instruction::I32Const(output_len_offset as i32)), // output_len_ptr1669				Counter(input_offset as u32, input_len as u32), // salt_ptr1670				Regular(Instruction::I32Const((s * 1024).max(input_len as u32) as i32)), // salt_len1671				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	// Only the overhead of calling the function itself with minimal arguments.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	// `n`: Input to hash in kilobytes1695	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	// Only the overhead of calling the function itself with minimal arguments.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	// `n`: Input to hash in kilobytes1713	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	// Only the overhead of calling the function itself with minimal arguments.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	// `n`: Input to hash in kilobytes1731	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	// Only the overhead of calling the function itself with minimal arguments.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	// `n`: Input to hash in kilobytes1749	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	// We make the assumption that pushing a constant and dropping a value takes roughly1758	// the same amount of time. We follow that `t.load` and `drop` both have the weight1759	// of this benchmark / 2. We need to make this assumption because there is no way1760	// to measure them on their own using a valid wasm module. We need their individual1761	// values to derive the weight of individual instructions (by substraction) from1762	// benchmarks that include those for parameter pushing and return type dropping.1763	// We call the weight of `t.load` and `drop`: `w_param`.1764	// The weight that would result from the respective benchmark we call: `w_bench`.1765	//1766	// w_i{32,64}const = w_drop = w_bench / 21767	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	// w_i{32,64}load = w_bench - 2 * w_param1781	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	// w_i{32,64}store{...} = w_bench - 2 * w_param1797	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	// w_select = w_bench - 4 * w_param1813	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	// w_if = w_bench - 3 * w_param1830	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	// w_br = w_bench - 2 * w_param1849	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	// w_br_if = w_bench - 5 * w_param1874	// The two additional pushes + drop are only executed 50% of the time.1875	// Making it: 3 * w_param + (50% * 4 * w_param)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	// w_br_table = w_bench - 3 * w_param1902	// 1 * w_param + 0.5 * 2 * w_param + 0.25 * 4 * w_param1903	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	// w_br_table_per_entry = w_bench1933	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), // Make sure the default entry is also used1949				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	// w_call = w_bench - 2 * w_param1967	instr_call {1968		let r in 0 .. INSTR_BENCHMARK_BATCHES;1969		let mut sbox = Sandbox::from(&WasmModule::<T>::from(ModuleDefinition {1970			// We need to make use of the stack here in order to trigger stack height1971			// instrumentation.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), // call aux1979			])),1980			inject_stack_metering: true,1981			.. Default::default()1982		}));1983	}: {1984		sbox.invoke();1985	}19861987	// w_call_indrect = w_bench - 3 * w_param1988	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			// We need to make use of the stack here in order to trigger stack height1994			// instrumentation.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)), // we only have one sig: 02003			])),2004			inject_stack_metering: true,2005			table: Some(TableSegment {2006				num_elements,2007				function_index: 2, // aux2008			}),2009			.. Default::default()2010		}));2011	}: {2012		sbox.invoke();2013	}20142015	// w_instr_call_indirect_per_param = w_bench - 1 * w_param2016	// Calling a function indirectly causes it to go through a thunk function whose runtime2017	// linearly depend on the amount of parameters to this function.2018	// Please note that this is not necessary with a direct call.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			// We need to make use of the stack here in order to trigger stack height2025			// instrumentation.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)), // aux signature: 1 or 02036			])),2037			inject_stack_metering: true,2038			table: Some(TableSegment {2039				num_elements,2040				function_index: 2, // aux2041			}),2042			.. Default::default()2043		}));2044	}: {2045		sbox.invoke();2046	}20472048	// w_local_get = w_bench - 1 * w_param2049	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	// w_local_set = w_bench - 1 * w_param2066	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	// w_local_tee = w_bench - 2 * w_param2083	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	// w_global_get = w_bench - 1 * w_param2101	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	// w_global_set = w_bench - 1 * w_param2117	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	// w_memory_get = w_bench - 1 * w_param2133	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	// w_memory_grow = w_bench - 2 * w_param2148	// We can only allow allocate as much memory as it is allowed in a a contract.2149	// Therefore the repeat count is limited by the maximum memory any contract can have.2150	// Using a contract with more memory will skew the benchmark because the runtime of grow2151	// depends on how much memory is already allocated.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	// Unary numeric instructions.2172	// All use w = w_bench - 2 * w_param.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	// Binary numeric instructions.2253	// All use w = w_bench - 3 * w_param.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	// This is no benchmark. It merely exist to have an easy way to pretty print the curently2506	// configured `Schedule` during benchmark development.2507	// It can be outputed using the following command:2508	// cargo run --manifest-path=bin/node/cli/Cargo.toml --release \2509	//     --features runtime-benchmarks -- benchmark --dev --execution=native \2510	//     -p pallet_contracts -e print_schedule --no-median-slopes --no-min-squares2511	#[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);