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