pallet_contracts_for_drink/
schedule.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
18//! This module contains the cost schedule and supporting code that constructs a
19//! sane default schedule from a `WeightInfo` implementation.
20
21use crate::{weights::WeightInfo, Config};
22
23use codec::{Decode, Encode};
24use frame_support::{weights::Weight, DefaultNoBound};
25use pallet_contracts_proc_macro::{ScheduleDebug, WeightDebug};
26use scale_info::TypeInfo;
27#[cfg(feature = "std")]
28use serde::{Deserialize, Serialize};
29use sp_runtime::RuntimeDebug;
30use sp_std::marker::PhantomData;
31
32/// Definition of the cost schedule and other parameterizations for the wasm vm.
33///
34/// Its [`Default`] implementation is the designated way to initialize this type. It uses
35/// the benchmarked information supplied by [`Config::WeightInfo`]. All of its fields are
36/// public and can therefore be modified. For example in order to change some of the limits
37/// and set a custom instruction weight version the following code could be used:
38/// ```rust
39/// use pallet_contracts::{Schedule, Limits, InstructionWeights, Config};
40///
41/// fn create_schedule<T: Config>() -> Schedule<T> {
42///     Schedule {
43///         limits: Limits {
44/// 		        globals: 3,
45/// 		        parameters: 3,
46/// 		        memory_pages: 16,
47/// 		        table_size: 3,
48/// 		        br_table_size: 3,
49/// 		        .. Default::default()
50/// 	        },
51///         instruction_weights: InstructionWeights {
52///             .. Default::default()
53///         },
54/// 	        .. Default::default()
55///     }
56/// }
57/// ```
58#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
59#[cfg_attr(feature = "std", serde(bound(serialize = "", deserialize = "")))]
60#[derive(Clone, Encode, Decode, PartialEq, Eq, ScheduleDebug, DefaultNoBound, TypeInfo)]
61#[scale_info(skip_type_params(T))]
62pub struct Schedule<T: Config> {
63	/// Describes the upper limits on various metrics.
64	pub limits: Limits,
65
66	/// The weights for individual wasm instructions.
67	pub instruction_weights: InstructionWeights<T>,
68
69	/// The weights for each imported function a contract is allowed to call.
70	pub host_fn_weights: HostFnWeights<T>,
71}
72
73/// Describes the upper limits on various metrics.
74#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
75#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo)]
76pub struct Limits {
77	/// The maximum number of topics supported by an event.
78	pub event_topics: u32,
79
80	/// Maximum number of globals a module is allowed to declare.
81	///
82	/// Globals are not limited through the linear memory limit `memory_pages`.
83	pub globals: u32,
84
85	/// Maximum number of locals a function can have.
86	///
87	/// As wasm engine initializes each of the local, we need to limit their number to confine
88	/// execution costs.
89	pub locals: u32,
90
91	/// Maximum numbers of parameters a function can have.
92	///
93	/// Those need to be limited to prevent a potentially exploitable interaction with
94	/// the stack height instrumentation: The costs of executing the stack height
95	/// instrumentation for an indirectly called function scales linearly with the amount
96	/// of parameters of this function. Because the stack height instrumentation itself is
97	/// is not weight metered its costs must be static (via this limit) and included in
98	/// the costs of the instructions that cause them (call, call_indirect).
99	pub parameters: u32,
100
101	/// Maximum number of memory pages allowed for a contract.
102	pub memory_pages: u32,
103
104	/// Maximum number of elements allowed in a table.
105	///
106	/// Currently, the only type of element that is allowed in a table is funcref.
107	pub table_size: u32,
108
109	/// Maximum number of elements that can appear as immediate value to the br_table instruction.
110	pub br_table_size: u32,
111
112	/// The maximum length of a subject in bytes used for PRNG generation.
113	pub subject_len: u32,
114
115	/// The maximum size of a storage value and event payload in bytes.
116	pub payload_len: u32,
117
118	/// The maximum node runtime memory. This is for integrity checks only and does not affect the
119	/// real setting.
120	pub runtime_memory: u32,
121}
122
123impl Limits {
124	/// The maximum memory size in bytes that a contract can occupy.
125	pub fn max_memory_size(&self) -> u32 {
126		self.memory_pages * 64 * 1024
127	}
128}
129
130/// Gas metering of Wasm executed instructions is being done on the engine side.
131/// This struct holds a reference value used to gas units scaling between host and engine.
132#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
133#[derive(Clone, Encode, Decode, PartialEq, Eq, ScheduleDebug, TypeInfo)]
134#[scale_info(skip_type_params(T))]
135pub struct InstructionWeights<T: Config> {
136	/// Base instruction `ref_time` Weight.
137	/// Should match to wasmi's `1` fuel (see <https://github.com/paritytech/wasmi/issues/701>).
138	pub base: u32,
139	/// The type parameter is used in the default implementation.
140	#[codec(skip)]
141	pub _phantom: PhantomData<T>,
142}
143
144/// Describes the weight for each imported function that a contract is allowed to call.
145#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
146#[derive(Clone, Encode, Decode, PartialEq, Eq, WeightDebug, TypeInfo)]
147#[scale_info(skip_type_params(T))]
148pub struct HostFnWeights<T: Config> {
149	/// Weight of calling `seal_caller`.
150	pub caller: Weight,
151
152	/// Weight of calling `seal_is_contract`.
153	pub is_contract: Weight,
154
155	/// Weight of calling `seal_code_hash`.
156	pub code_hash: Weight,
157
158	/// Weight of calling `seal_own_code_hash`.
159	pub own_code_hash: Weight,
160
161	/// Weight of calling `seal_caller_is_origin`.
162	pub caller_is_origin: Weight,
163
164	/// Weight of calling `seal_caller_is_root`.
165	pub caller_is_root: Weight,
166
167	/// Weight of calling `seal_address`.
168	pub address: Weight,
169
170	/// Weight of calling `seal_gas_left`.
171	pub gas_left: Weight,
172
173	/// Weight of calling `seal_balance`.
174	pub balance: Weight,
175
176	/// Weight of calling `seal_value_transferred`.
177	pub value_transferred: Weight,
178
179	/// Weight of calling `seal_minimum_balance`.
180	pub minimum_balance: Weight,
181
182	/// Weight of calling `seal_block_number`.
183	pub block_number: Weight,
184
185	/// Weight of calling `seal_now`.
186	pub now: Weight,
187
188	/// Weight of calling `seal_weight_to_fee`.
189	pub weight_to_fee: Weight,
190
191	/// Weight of calling `seal_input`.
192	pub input: Weight,
193
194	/// Weight per input byte copied to contract memory by `seal_input`.
195	pub input_per_byte: Weight,
196
197	/// Weight of calling `seal_return`.
198	pub r#return: Weight,
199
200	/// Weight per byte returned through `seal_return`.
201	pub return_per_byte: Weight,
202
203	/// Weight of calling `seal_terminate`.
204	pub terminate: Weight,
205
206	/// Weight of calling `seal_random`.
207	pub random: Weight,
208
209	/// Weight of calling `seal_reposit_event`.
210	pub deposit_event: Weight,
211
212	/// Weight per topic supplied to `seal_deposit_event`.
213	pub deposit_event_per_topic: Weight,
214
215	/// Weight per byte of an event deposited through `seal_deposit_event`.
216	pub deposit_event_per_byte: Weight,
217
218	/// Weight of calling `seal_debug_message`.
219	pub debug_message: Weight,
220
221	/// Weight of calling `seal_debug_message` per byte of the message.
222	pub debug_message_per_byte: Weight,
223
224	/// Weight of calling `seal_set_storage`.
225	pub set_storage: Weight,
226
227	/// Weight per written byten of an item stored with `seal_set_storage`.
228	pub set_storage_per_new_byte: Weight,
229
230	/// Weight per overwritten byte of an item stored with `seal_set_storage`.
231	pub set_storage_per_old_byte: Weight,
232
233	/// Weight of calling `seal_set_code_hash`.
234	pub set_code_hash: Weight,
235
236	/// Weight of calling `seal_clear_storage`.
237	pub clear_storage: Weight,
238
239	/// Weight of calling `seal_clear_storage` per byte of the stored item.
240	pub clear_storage_per_byte: Weight,
241
242	/// Weight of calling `seal_contains_storage`.
243	pub contains_storage: Weight,
244
245	/// Weight of calling `seal_contains_storage` per byte of the stored item.
246	pub contains_storage_per_byte: Weight,
247
248	/// Weight of calling `seal_get_storage`.
249	pub get_storage: Weight,
250
251	/// Weight per byte of an item received via `seal_get_storage`.
252	pub get_storage_per_byte: Weight,
253
254	/// Weight of calling `seal_take_storage`.
255	pub take_storage: Weight,
256
257	/// Weight per byte of an item received via `seal_take_storage`.
258	pub take_storage_per_byte: Weight,
259
260	/// Weight of calling `seal_transfer`.
261	pub transfer: Weight,
262
263	/// Weight of calling `seal_call`.
264	pub call: Weight,
265
266	/// Weight of calling `seal_delegate_call`.
267	pub delegate_call: Weight,
268
269	/// Weight surcharge that is claimed if `seal_call` does a balance transfer.
270	pub call_transfer_surcharge: Weight,
271
272	/// Weight per byte that is cloned by supplying the `CLONE_INPUT` flag.
273	pub call_per_cloned_byte: Weight,
274
275	/// Weight of calling `seal_instantiate`.
276	pub instantiate: Weight,
277
278	/// Weight surcharge that is claimed if `seal_instantiate` does a balance transfer.
279	pub instantiate_transfer_surcharge: Weight,
280
281	/// Weight per input byte supplied to `seal_instantiate`.
282	pub instantiate_per_input_byte: Weight,
283
284	/// Weight per salt byte supplied to `seal_instantiate`.
285	pub instantiate_per_salt_byte: Weight,
286
287	/// Weight of calling `seal_hash_sha_256`.
288	pub hash_sha2_256: Weight,
289
290	/// Weight per byte hashed by `seal_hash_sha_256`.
291	pub hash_sha2_256_per_byte: Weight,
292
293	/// Weight of calling `seal_hash_keccak_256`.
294	pub hash_keccak_256: Weight,
295
296	/// Weight per byte hashed by `seal_hash_keccak_256`.
297	pub hash_keccak_256_per_byte: Weight,
298
299	/// Weight of calling `seal_hash_blake2_256`.
300	pub hash_blake2_256: Weight,
301
302	/// Weight per byte hashed by `seal_hash_blake2_256`.
303	pub hash_blake2_256_per_byte: Weight,
304
305	/// Weight of calling `seal_hash_blake2_128`.
306	pub hash_blake2_128: Weight,
307
308	/// Weight per byte hashed by `seal_hash_blake2_128`.
309	pub hash_blake2_128_per_byte: Weight,
310
311	/// Weight of calling `seal_ecdsa_recover`.
312	pub ecdsa_recover: Weight,
313
314	/// Weight of calling `seal_ecdsa_to_eth_address`.
315	pub ecdsa_to_eth_address: Weight,
316
317	/// Weight of calling `sr25519_verify`.
318	pub sr25519_verify: Weight,
319
320	/// Weight per byte of calling `sr25519_verify`.
321	pub sr25519_verify_per_byte: Weight,
322
323	/// Weight of calling `reentrance_count`.
324	pub reentrance_count: Weight,
325
326	/// Weight of calling `account_reentrance_count`.
327	pub account_reentrance_count: Weight,
328
329	/// Weight of calling `instantiation_nonce`.
330	pub instantiation_nonce: Weight,
331
332	/// Weight of calling `add_delegate_dependency`.
333	pub add_delegate_dependency: Weight,
334
335	/// Weight of calling `remove_delegate_dependency`.
336	pub remove_delegate_dependency: Weight,
337
338	/// The type parameter is used in the default implementation.
339	#[codec(skip)]
340	pub _phantom: PhantomData<T>,
341}
342
343macro_rules! replace_token {
344	($_in:tt $replacement:tt) => {
345		$replacement
346	};
347}
348
349macro_rules! call_zero {
350	($name:ident, $( $arg:expr ),*) => {
351		T::WeightInfo::$name($( replace_token!($arg 0) ),*)
352	};
353}
354
355macro_rules! cost_args {
356	($name:ident, $( $arg: expr ),+) => {
357		(T::WeightInfo::$name($( $arg ),+).saturating_sub(call_zero!($name, $( $arg ),+)))
358	}
359}
360
361macro_rules! cost_instr_no_params {
362	($name:ident) => {
363		cost_args!($name, 1).ref_time() as u32
364	};
365}
366
367macro_rules! cost {
368	($name:ident) => {
369		cost_args!($name, 1)
370	};
371}
372
373macro_rules! cost_instr {
374	($name:ident, $num_params:expr) => {
375		cost_instr_no_params!($name)
376			.saturating_sub((cost_instr_no_params!(instr_i64const) / 2).saturating_mul($num_params))
377	};
378}
379
380impl Default for Limits {
381	fn default() -> Self {
382		Self {
383			event_topics: 4,
384			globals: 256,
385			locals: 1024,
386			parameters: 128,
387			memory_pages: 16,
388			// 4k function pointers (This is in count not bytes).
389			table_size: 4096,
390			br_table_size: 256,
391			subject_len: 32,
392			payload_len: 16 * 1024,
393			runtime_memory: 1024 * 1024 * 128,
394		}
395	}
396}
397
398impl<T: Config> Default for InstructionWeights<T> {
399	/// We price both `i64.const` and `drop` as `instr_i64const / 2`. The reason
400	/// for that is that we cannot benchmark either of them on its own.
401	fn default() -> Self {
402		Self { base: cost_instr!(instr_i64const, 1), _phantom: PhantomData }
403	}
404}
405
406impl<T: Config> Default for HostFnWeights<T> {
407	fn default() -> Self {
408		Self {
409			caller: cost!(seal_caller),
410			is_contract: cost!(seal_is_contract),
411			code_hash: cost!(seal_code_hash),
412			own_code_hash: cost!(seal_own_code_hash),
413			caller_is_origin: cost!(seal_caller_is_origin),
414			caller_is_root: cost!(seal_caller_is_root),
415			address: cost!(seal_address),
416			gas_left: cost!(seal_gas_left),
417			balance: cost!(seal_balance),
418			value_transferred: cost!(seal_value_transferred),
419			minimum_balance: cost!(seal_minimum_balance),
420			block_number: cost!(seal_block_number),
421			now: cost!(seal_now),
422			weight_to_fee: cost!(seal_weight_to_fee),
423			input: cost!(seal_input),
424			input_per_byte: cost!(seal_input_per_byte),
425			r#return: cost!(seal_return),
426			return_per_byte: cost!(seal_return_per_byte),
427			terminate: cost!(seal_terminate),
428			random: cost!(seal_random),
429			deposit_event: cost!(seal_deposit_event),
430			deposit_event_per_topic: cost_args!(seal_deposit_event_per_topic_and_byte, 1, 0),
431			deposit_event_per_byte: cost_args!(seal_deposit_event_per_topic_and_byte, 0, 1),
432			debug_message: cost!(seal_debug_message),
433			debug_message_per_byte: cost!(seal_debug_message_per_byte),
434			set_storage: cost!(seal_set_storage),
435			set_code_hash: cost!(seal_set_code_hash),
436			set_storage_per_new_byte: cost!(seal_set_storage_per_new_byte),
437			set_storage_per_old_byte: cost!(seal_set_storage_per_old_byte),
438			clear_storage: cost!(seal_clear_storage),
439			clear_storage_per_byte: cost!(seal_clear_storage_per_byte),
440			contains_storage: cost!(seal_contains_storage),
441			contains_storage_per_byte: cost!(seal_contains_storage_per_byte),
442			get_storage: cost!(seal_get_storage),
443			get_storage_per_byte: cost!(seal_get_storage_per_byte),
444			take_storage: cost!(seal_take_storage),
445			take_storage_per_byte: cost!(seal_take_storage_per_byte),
446			transfer: cost!(seal_transfer),
447			call: cost!(seal_call),
448			delegate_call: cost!(seal_delegate_call),
449			call_transfer_surcharge: cost_args!(seal_call_per_transfer_clone_byte, 1, 0),
450			call_per_cloned_byte: cost_args!(seal_call_per_transfer_clone_byte, 0, 1),
451			instantiate: cost!(seal_instantiate),
452			instantiate_transfer_surcharge: cost_args!(
453				seal_instantiate_per_transfer_input_salt_byte,
454				1,
455				0,
456				0
457			),
458			instantiate_per_input_byte: cost_args!(
459				seal_instantiate_per_transfer_input_salt_byte,
460				0,
461				1,
462				0
463			),
464			instantiate_per_salt_byte: cost_args!(
465				seal_instantiate_per_transfer_input_salt_byte,
466				0,
467				0,
468				1
469			),
470			hash_sha2_256: cost!(seal_hash_sha2_256),
471			hash_sha2_256_per_byte: cost!(seal_hash_sha2_256_per_byte),
472			hash_keccak_256: cost!(seal_hash_keccak_256),
473			hash_keccak_256_per_byte: cost!(seal_hash_keccak_256_per_byte),
474			hash_blake2_256: cost!(seal_hash_blake2_256),
475			hash_blake2_256_per_byte: cost!(seal_hash_blake2_256_per_byte),
476			hash_blake2_128: cost!(seal_hash_blake2_128),
477			hash_blake2_128_per_byte: cost!(seal_hash_blake2_128_per_byte),
478			ecdsa_recover: cost!(seal_ecdsa_recover),
479			sr25519_verify: cost!(seal_sr25519_verify),
480			sr25519_verify_per_byte: cost!(seal_sr25519_verify_per_byte),
481			ecdsa_to_eth_address: cost!(seal_ecdsa_to_eth_address),
482			reentrance_count: cost!(seal_reentrance_count),
483			account_reentrance_count: cost!(seal_account_reentrance_count),
484			instantiation_nonce: cost!(seal_instantiation_nonce),
485			add_delegate_dependency: cost!(add_delegate_dependency),
486			remove_delegate_dependency: cost!(remove_delegate_dependency),
487			_phantom: PhantomData,
488		}
489	}
490}
491
492#[cfg(test)]
493mod test {
494	use super::*;
495	use crate::tests::Test;
496
497	#[test]
498	fn print_test_schedule() {
499		let schedule = Schedule::<Test>::default();
500		println!("{:#?}", schedule);
501	}
502}