pallet_contracts/
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 core::marker::PhantomData;
25use frame_support::DefaultNoBound;
26use scale_info::TypeInfo;
27#[cfg(feature = "std")]
28use serde::{Deserialize, Serialize};
29
30/// Definition of the cost schedule and other parameterizations for the wasm vm.
31///
32/// Its [`Default`] implementation is the designated way to initialize this type. It uses
33/// the benchmarked information supplied by [`Config::WeightInfo`]. All of its fields are
34/// public and can therefore be modified. For example in order to change some of the limits
35/// and set a custom instruction weight version the following code could be used:
36/// ```rust
37/// use pallet_contracts::{Schedule, Limits, InstructionWeights, Config};
38///
39/// fn create_schedule<T: Config>() -> Schedule<T> {
40///     Schedule {
41///         limits: Limits {
42/// 		        memory_pages: 16,
43/// 		        .. Default::default()
44/// 	        },
45///         instruction_weights: InstructionWeights {
46///             .. Default::default()
47///         },
48/// 	        .. Default::default()
49///     }
50/// }
51/// ```
52#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
53#[cfg_attr(feature = "std", serde(bound(serialize = "", deserialize = "")))]
54#[cfg_attr(feature = "runtime-benchmarks", derive(frame_support::DebugNoBound))]
55#[derive(Clone, Encode, Decode, PartialEq, Eq, DefaultNoBound, TypeInfo)]
56#[scale_info(skip_type_params(T))]
57pub struct Schedule<T: Config> {
58	/// Describes the upper limits on various metrics.
59	pub limits: Limits,
60
61	/// The weights for individual wasm instructions.
62	pub instruction_weights: InstructionWeights<T>,
63}
64
65impl<T: Config> Schedule<T> {
66	/// Returns the reference time per engine fuel.
67	pub fn ref_time_by_fuel(&self) -> u64 {
68		self.instruction_weights.base as u64
69	}
70}
71
72/// Describes the upper limits on various metrics.
73#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
74#[cfg_attr(feature = "runtime-benchmarks", derive(Debug))]
75#[derive(Clone, Encode, Decode, PartialEq, Eq, TypeInfo)]
76pub struct Limits {
77	/// The maximum number of topics supported by an event.
78	pub event_topics: u32,
79
80	/// Maximum number of memory pages allowed for a contract.
81	pub memory_pages: u32,
82
83	/// The maximum length of a subject in bytes used for PRNG generation.
84	pub subject_len: u32,
85
86	/// The maximum size of a storage value and event payload in bytes.
87	pub payload_len: u32,
88
89	/// The maximum node runtime memory. This is for integrity checks only and does not affect the
90	/// real setting.
91	pub runtime_memory: u32,
92
93	/// The maximum validator node runtime memory. This is for integrity checks only and does not
94	/// affect the real setting.
95	pub validator_runtime_memory: u32,
96
97	/// The additional ref_time added to the `deposit_event` host function call per event data
98	/// byte.
99	pub event_ref_time: u64,
100}
101
102impl Limits {
103	/// The maximum memory size in bytes that a contract can occupy.
104	pub fn max_memory_size(&self) -> u32 {
105		self.memory_pages * 64 * 1024
106	}
107}
108
109/// Gas metering of Wasm executed instructions is being done on the engine side.
110/// This struct holds a reference value used to gas units scaling between host and engine.
111#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
112#[cfg_attr(feature = "runtime-benchmarks", derive(frame_support::DebugNoBound))]
113#[derive(Clone, Encode, Decode, PartialEq, Eq, TypeInfo)]
114#[scale_info(skip_type_params(T))]
115pub struct InstructionWeights<T: Config> {
116	/// Base instruction `ref_time` Weight.
117	/// Should match to wasmi's `1` fuel (see <https://github.com/wasmi-labs/wasmi/issues/701>).
118	pub base: u32,
119	/// The type parameter is used in the default implementation.
120	#[codec(skip)]
121	pub _phantom: PhantomData<T>,
122}
123
124impl Default for Limits {
125	fn default() -> Self {
126		Self {
127			event_topics: 4,
128			memory_pages: 16,
129			subject_len: 32,
130			payload_len: 16 * 1024,
131			runtime_memory: 1024 * 1024 * 128,
132			validator_runtime_memory: 1024 * 1024 * 512,
133			event_ref_time: 60_000,
134		}
135	}
136}
137
138impl<T: Config> Default for InstructionWeights<T> {
139	/// We execute 6 different instructions therefore we have to divide the actual
140	/// computed gas costs by 6 to have a rough estimate as to how expensive each
141	/// single executed instruction is going to be.
142	fn default() -> Self {
143		let instr_cost = T::WeightInfo::instr_i64_load_store(1)
144			.saturating_sub(T::WeightInfo::instr_i64_load_store(0))
145			.ref_time() as u32;
146		let base = instr_cost / 6;
147		Self { base, _phantom: PhantomData }
148	}
149}