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