referrerpolicy=no-referrer-when-downgrade

pallet_revive/vm/
runtime_costs.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// 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 at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// 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 and
16// limitations under the License.
17
18use crate::{
19	limits, metering::Token, weightinfo_extension::OnFinalizeBlockParts, weights::WeightInfo,
20	Config,
21};
22use frame_support::weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight};
23
24/// Current approximation of the gas/s consumption considering
25/// EVM execution over compiled WASM (on 4.4Ghz CPU).
26/// Given the 2000ms Weight, from which 75% only are used for transactions,
27/// the total EVM execution gas limit is: GAS_PER_SECOND * 2 * 0.75 ~= 60_000_000.
28const GAS_PER_SECOND: u64 = 40_000_000;
29
30/// Approximate ratio of the amount of Weight per Gas.
31/// u64 works for approximations because Weight is a very small unit compared to
32/// gas.
33const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND / GAS_PER_SECOND;
34
35#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
36#[derive(Copy, Clone)]
37pub enum RuntimeCosts {
38	/// Base Weight of calling a host function.
39	HostFn,
40	/// Weight charged for executing the extcodecopy instruction.
41	ExtCodeCopy(u32),
42	/// Weight charged for copying data from the sandbox.
43	CopyFromContract(u32),
44	/// Weight charged for copying data to the sandbox.
45	CopyToContract(u32),
46	/// Weight of calling `seal_call_data_load``.
47	CallDataLoad,
48	/// Weight of calling `seal_call_data_copy`.
49	CallDataCopy(u32),
50	/// Weight of calling `seal_caller`.
51	Caller,
52	/// Weight of calling `seal_call_data_size`.
53	CallDataSize,
54	/// Weight of calling `seal_return_data_size`.
55	ReturnDataSize,
56	/// Weight of calling `toAccountId` on the `System` pre-compile.
57	ToAccountId,
58	/// Weight of calling `seal_origin`.
59	Origin,
60	/// Weight of calling `seal_code_hash`.
61	CodeHash,
62	/// Weight of calling `ownCodeHash` on the `System` pre-compile.
63	OwnCodeHash,
64	/// Weight of calling `seal_code_size`.
65	CodeSize,
66	/// Weight of calling `callerIsOrigin` on the `System` pre-compile.
67	CallerIsOrigin,
68	/// Weight of calling `callerIsRoot` on the `System` pre-compile.
69	CallerIsRoot,
70	/// Weight of calling `seal_address`.
71	Address,
72	/// Weight of calling `seal_ref_time_left`.
73	RefTimeLeft,
74	/// Weight of calling `weightLeft` on the `System` pre-compile.
75	WeightLeft,
76	/// Weight of calling `seal_balance`.
77	Balance,
78	/// Weight of calling `seal_balance_of`.
79	BalanceOf,
80	/// Weight of calling `seal_value_transferred`.
81	ValueTransferred,
82	/// Weight of calling `minimumBalance` on the `System` pre-compile.
83	MinimumBalance,
84	/// Weight of calling `seal_block_number`.
85	BlockNumber,
86	/// Weight of calling `seal_block_hash`.
87	BlockHash,
88	/// Weight of calling `seal_block_author`.
89	BlockAuthor,
90	/// Weight of calling `seal_gas_price`.
91	GasPrice,
92	/// Weight of calling `seal_base_fee`.
93	BaseFee,
94	/// Weight of calling `seal_now`.
95	Now,
96	/// Weight of calling `seal_gas_limit`.
97	GasLimit,
98	/// Weight of calling `seal_terminate`.
99	Terminate { code_removed: bool },
100	/// Weight of calling `seal_deposit_event` with the given number of topics and event size.
101	DepositEvent { num_topic: u32, len: u32 },
102	/// Weight of calling `seal_set_storage` for the given storage item sizes.
103	SetStorage { old_bytes: u32, new_bytes: u32 },
104	/// Weight of calling the `clearStorage` function of the `Storage` pre-compile
105	/// per cleared byte.
106	ClearStorage(u32),
107	/// Weight of calling the `containsStorage` function of the `Storage` pre-compile
108	/// per byte of the checked item.
109	ContainsStorage(u32),
110	/// Weight of calling `seal_get_storage` with the specified size in storage.
111	GetStorage(u32),
112	/// Weight of calling the `takeStorage` function of the `Storage` pre-compile
113	/// for the given size.
114	TakeStorage(u32),
115	/// Weight of calling `seal_set_transient_storage` for the given storage item sizes.
116	SetTransientStorage { old_bytes: u32, new_bytes: u32 },
117	/// Weight of calling `seal_clear_transient_storage` per cleared byte.
118	ClearTransientStorage(u32),
119	/// Weight of calling `seal_contains_transient_storage` per byte of the checked item.
120	ContainsTransientStorage(u32),
121	/// Weight of calling `seal_get_transient_storage` with the specified size in storage.
122	GetTransientStorage(u32),
123	/// Weight of calling `seal_take_transient_storage` for the given size.
124	TakeTransientStorage(u32),
125	/// Base weight of calling `seal_call`.
126	CallBase,
127	/// Weight of calling `seal_delegate_call` for the given input size.
128	DelegateCallBase,
129	/// Weight of calling a precompile.
130	PrecompileBase,
131	/// Weight of calling a precompile that has a contract info.
132	PrecompileWithInfoBase,
133	/// Weight of reading and decoding the input to a precompile.
134	PrecompileDecode(u32),
135	/// Weight of the transfer performed during a call.
136	/// parameter `dust_transfer` indicates whether the transfer has a `dust` value.
137	CallTransferSurcharge { dust_transfer: bool },
138	/// Weight per byte that is cloned by supplying the `CLONE_INPUT` flag.
139	CallInputCloned(u32),
140	/// Weight of calling `seal_instantiate`.
141	Instantiate { input_data_len: u32, balance_transfer: bool, dust_transfer: bool },
142	/// Weight of calling `Create` opcode.
143	Create { init_code_len: u32, balance_transfer: bool, dust_transfer: bool },
144	/// Weight of calling `Ripemd160` precompile for the given input size.
145	Ripemd160(u32),
146	/// Weight of calling `Sha256` precompile for the given input size.
147	HashSha256(u32),
148	/// Weight of calling the `System::hashBlake256` precompile function for the given input
149	HashKeccak256(u32),
150	/// Weight of calling the `System::hash_blake2_256` precompile function for the given input
151	/// size.
152	HashBlake256(u32),
153	/// Weight of calling `System::hashBlake128` precompile function for the given input size.
154	HashBlake128(u32),
155	/// Weight of calling `ECERecover` precompile.
156	EcdsaRecovery,
157	/// Weight of calling `P256Verify` precompile.
158	P256Verify,
159	/// Weight of calling `seal_sr25519_verify` for the given input size.
160	Sr25519Verify(u32),
161	/// Weight charged by a precompile.
162	Precompile(Weight),
163	/// Weight of calling `ecdsa_to_eth_address`
164	EcdsaToEthAddress,
165	/// Weight of calling `get_immutable_dependency`
166	GetImmutableData(u32),
167	/// Weight of calling `set_immutable_dependency`
168	SetImmutableData(u32),
169	/// Weight of calling `Bn128Add` precompile
170	Bn128Add,
171	/// Weight of calling `Bn128Add` precompile
172	Bn128Mul,
173	/// Weight of calling `Bn128Pairing` precompile for the given number of input pairs.
174	Bn128Pairing(u32),
175	/// Weight of calling `Identity` precompile for the given number of input length.
176	Identity(u32),
177	/// Weight of calling `Blake2F` precompile for the given number of rounds.
178	Blake2F(u32),
179	/// Weight of calling `Modexp` precompile
180	Modexp(u64),
181}
182
183/// For functions that modify storage, benchmarks are performed with one item in the
184/// storage. To account for the worst-case scenario, the weight of the overhead of
185/// writing to or reading from full storage is included. For transient storage writes,
186/// the rollback weight is added to reflect the worst-case scenario for this operation.
187macro_rules! cost_storage {
188    (write_transient, $name:ident $(, $arg:expr )*) => {
189        T::WeightInfo::$name($( $arg ),*)
190            .saturating_add(T::WeightInfo::rollback_transient_storage())
191            .saturating_add(T::WeightInfo::set_transient_storage_full()
192            .saturating_sub(T::WeightInfo::set_transient_storage_empty()))
193    };
194
195    (read_transient, $name:ident $(, $arg:expr )*) => {
196        T::WeightInfo::$name($( $arg ),*)
197            .saturating_add(T::WeightInfo::get_transient_storage_full()
198            .saturating_sub(T::WeightInfo::get_transient_storage_empty()))
199    };
200
201    (write, $name:ident $(, $arg:expr )*) => {
202        T::WeightInfo::$name($( $arg ),*)
203            .saturating_add(T::WeightInfo::set_storage_full()
204            .saturating_sub(T::WeightInfo::set_storage_empty()))
205    };
206
207    (read, $name:ident $(, $arg:expr )*) => {
208        T::WeightInfo::$name($( $arg ),*)
209            .saturating_add(T::WeightInfo::get_storage_full()
210            .saturating_sub(T::WeightInfo::get_storage_empty()))
211    };
212}
213
214macro_rules! cost_args {
215	// cost_args!(name, a, b, c) -> T::WeightInfo::name(a, b, c).saturating_sub(T::WeightInfo::name(0, 0, 0))
216	($name:ident, $( $arg: expr ),+) => {
217		(T::WeightInfo::$name($( $arg ),+).saturating_sub(cost_args!(@call_zero $name, $( $arg ),+)))
218	};
219	// Transform T::WeightInfo::name(a, b, c) into T::WeightInfo::name(0, 0, 0)
220	(@call_zero $name:ident, $( $arg:expr ),*) => {
221		T::WeightInfo::$name($( cost_args!(@replace_token $arg) ),*)
222	};
223	// Replace the token with 0.
224	(@replace_token $_in:tt) => { 0 };
225}
226
227impl<T: Config> Token<T> for RuntimeCosts {
228	fn influence_lowest_weight_limit(&self) -> bool {
229		true
230	}
231
232	fn weight(&self) -> Weight {
233		use self::RuntimeCosts::*;
234		match *self {
235			HostFn => cost_args!(noop_host_fn, 1),
236			ExtCodeCopy(len) => T::WeightInfo::extcodecopy(len),
237			CopyToContract(len) => T::WeightInfo::seal_copy_to_contract(len),
238			CopyFromContract(len) => T::WeightInfo::seal_return(len),
239			CallDataSize => T::WeightInfo::seal_call_data_size(),
240			ReturnDataSize => T::WeightInfo::seal_return_data_size(),
241			CallDataLoad => T::WeightInfo::seal_call_data_load(),
242			CallDataCopy(len) => T::WeightInfo::seal_call_data_copy(len),
243			Caller => T::WeightInfo::seal_caller(),
244			Origin => T::WeightInfo::seal_origin(),
245			ToAccountId => T::WeightInfo::to_account_id(),
246			CodeHash => T::WeightInfo::seal_code_hash(),
247			CodeSize => T::WeightInfo::seal_code_size(),
248			OwnCodeHash => T::WeightInfo::own_code_hash(),
249			CallerIsOrigin => T::WeightInfo::caller_is_origin(),
250			CallerIsRoot => T::WeightInfo::caller_is_root(),
251			Address => T::WeightInfo::seal_address(),
252			RefTimeLeft => T::WeightInfo::seal_ref_time_left(),
253			WeightLeft => T::WeightInfo::weight_left(),
254			Balance => T::WeightInfo::seal_balance(),
255			BalanceOf => T::WeightInfo::seal_balance_of(),
256			ValueTransferred => T::WeightInfo::seal_value_transferred(),
257			MinimumBalance => T::WeightInfo::minimum_balance(),
258			BlockNumber => T::WeightInfo::seal_block_number(),
259			BlockHash => T::WeightInfo::seal_block_hash(),
260			BlockAuthor => T::WeightInfo::seal_block_author(),
261			GasPrice => T::WeightInfo::seal_gas_price(),
262			BaseFee => T::WeightInfo::seal_base_fee(),
263			Now => T::WeightInfo::seal_now(),
264			GasLimit => T::WeightInfo::seal_gas_limit(),
265			Terminate { code_removed } => {
266				// logic only runs if code is removed
267				if code_removed {
268					T::WeightInfo::seal_terminate(code_removed.into())
269						.saturating_add(T::WeightInfo::seal_terminate_logic())
270				} else {
271					T::WeightInfo::seal_terminate(code_removed.into())
272				}
273			},
274			DepositEvent { num_topic, len } => T::WeightInfo::seal_deposit_event(num_topic, len)
275				.saturating_add(T::WeightInfo::on_finalize_block_per_event(len))
276				.saturating_add(Weight::from_parts(
277					limits::EXTRA_EVENT_CHARGE_PER_BYTE.saturating_mul(len.into()).into(),
278					0,
279				)),
280			SetStorage { new_bytes, old_bytes } => {
281				cost_storage!(write, seal_set_storage, new_bytes, old_bytes)
282			},
283			ClearStorage(len) => cost_storage!(write, clear_storage, len),
284			ContainsStorage(len) => cost_storage!(read, contains_storage, len),
285			GetStorage(len) => cost_storage!(read, seal_get_storage, len),
286			TakeStorage(len) => cost_storage!(write, take_storage, len),
287			SetTransientStorage { new_bytes, old_bytes } => {
288				cost_storage!(write_transient, seal_set_transient_storage, new_bytes, old_bytes)
289			},
290			ClearTransientStorage(len) => {
291				cost_storage!(write_transient, seal_clear_transient_storage, len)
292			},
293			ContainsTransientStorage(len) => {
294				cost_storage!(read_transient, seal_contains_transient_storage, len)
295			},
296			GetTransientStorage(len) => {
297				cost_storage!(read_transient, seal_get_transient_storage, len)
298			},
299			TakeTransientStorage(len) => {
300				cost_storage!(write_transient, seal_take_transient_storage, len)
301			},
302			CallBase => T::WeightInfo::seal_call(0, 0, 0),
303			DelegateCallBase => T::WeightInfo::seal_delegate_call(),
304			PrecompileBase => T::WeightInfo::seal_call_precompile(0, 0),
305			PrecompileWithInfoBase => T::WeightInfo::seal_call_precompile(1, 0),
306			PrecompileDecode(len) => cost_args!(seal_call_precompile, 0, len),
307			CallTransferSurcharge { dust_transfer } =>
308				cost_args!(seal_call, 1, dust_transfer.into(), 0),
309			CallInputCloned(len) => cost_args!(seal_call, 0, 0, len),
310			Instantiate { input_data_len, balance_transfer, dust_transfer } =>
311				T::WeightInfo::seal_instantiate(
312					balance_transfer.into(),
313					dust_transfer.into(),
314					input_data_len,
315				),
316			Create { init_code_len, balance_transfer, dust_transfer } =>
317				T::WeightInfo::evm_instantiate(
318					balance_transfer.into(),
319					dust_transfer.into(),
320					init_code_len,
321				),
322			HashSha256(len) => T::WeightInfo::sha2_256(len),
323			Ripemd160(len) => T::WeightInfo::ripemd_160(len),
324			HashKeccak256(len) => T::WeightInfo::seal_hash_keccak_256(len),
325			HashBlake256(len) => T::WeightInfo::hash_blake2_256(len),
326			HashBlake128(len) => T::WeightInfo::hash_blake2_128(len),
327			EcdsaRecovery => T::WeightInfo::ecdsa_recover(),
328			P256Verify => T::WeightInfo::p256_verify(),
329			Sr25519Verify(len) => T::WeightInfo::seal_sr25519_verify(len),
330			Precompile(weight) => weight,
331			EcdsaToEthAddress => T::WeightInfo::seal_ecdsa_to_eth_address(),
332			GetImmutableData(len) => T::WeightInfo::seal_get_immutable_data(len),
333			SetImmutableData(len) => T::WeightInfo::seal_set_immutable_data(len),
334			Bn128Add => T::WeightInfo::bn128_add(),
335			Bn128Mul => T::WeightInfo::bn128_mul(),
336			Bn128Pairing(len) => T::WeightInfo::bn128_pairing(len),
337			Identity(len) => T::WeightInfo::identity(len),
338			Blake2F(rounds) => T::WeightInfo::blake2f(rounds),
339			Modexp(gas) => Weight::from_parts(gas.saturating_mul(WEIGHT_PER_GAS), 0),
340		}
341	}
342}