near_parameters/
vm.rs

1use crate::cost::{ExtCostsConfig, ParameterCost};
2use borsh::BorshSerialize;
3use near_primitives_core::config::AccountIdValidityRulesVersion;
4use near_primitives_core::types::Gas;
5use near_schema_checker_lib::ProtocolSchema;
6use std::collections::hash_map::DefaultHasher;
7use std::hash::{Hash, Hasher};
8
9// NOTE that VMKind is part of serialization protocol, so we cannot remove entries from this list
10// if particular VM reached publicly visible networks.
11//
12// Additionally, this is public only for the purposes of internal tools like the estimator. This
13// API should otherwise be considered a private configuration of the `near-vm-runner`
14// crate.
15#[derive(
16    Clone,
17    Copy,
18    Debug,
19    Hash,
20    BorshSerialize,
21    PartialEq,
22    Eq,
23    strum::EnumString,
24    serde::Serialize,
25    serde::Deserialize,
26    ProtocolSchema,
27)]
28#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
29pub enum VMKind {
30    /// Wasmer 0.17.x VM.
31    Wasmer0,
32    /// Wasmtime VM.
33    Wasmtime,
34    /// Wasmer 2.x VM.
35    Wasmer2,
36    /// NearVM.
37    NearVm,
38}
39
40impl VMKind {
41    pub fn replace_with_wasmtime_if_unsupported(self) -> Self {
42        if cfg!(not(target_arch = "x86_64")) {
43            Self::Wasmtime
44        } else {
45            self
46        }
47    }
48}
49
50/// This enum represents if a storage_get call will be performed through flat storage or trie
51#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
52pub enum StorageGetMode {
53    FlatStorage,
54    Trie,
55}
56
57/// Describes limits for VM and Runtime.
58/// TODO #4139: consider switching to strongly-typed wrappers instead of raw quantities
59#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Hash, PartialEq, Eq)]
60pub struct LimitConfig {
61    /// Max amount of gas that can be used, excluding gas attached to promises.
62    pub max_gas_burnt: Gas,
63
64    /// How tall the stack is allowed to grow?
65    ///
66    /// See <https://wiki.parity.io/WebAssembly-StackHeight> to find out how the stack frame cost
67    /// is calculated.
68    pub max_stack_height: u32,
69    /// Whether a legacy version of stack limiting should be used, see
70    /// [`ContractPrepareVersion`].
71    #[serde(default = "ContractPrepareVersion::v0")]
72    pub contract_prepare_version: ContractPrepareVersion,
73
74    /// The initial number of memory pages.
75    /// NOTE: It's not a limiter itself, but it's a value we use for initial_memory_pages.
76    pub initial_memory_pages: u32,
77    /// What is the maximal memory pages amount is allowed to have for a contract.
78    pub max_memory_pages: u32,
79
80    /// Limit of memory used by registers.
81    pub registers_memory_limit: u64,
82    /// Maximum number of bytes that can be stored in a single register.
83    pub max_register_size: u64,
84    /// Maximum number of registers that can be used simultaneously.
85    ///
86    /// Note that due to an implementation quirk [read: a bug] in VMLogic, if we
87    /// have this number of registers, no subsequent writes to the registers
88    /// will succeed even if they replace an existing register.
89    pub max_number_registers: u64,
90
91    /// Maximum number of log entries.
92    pub max_number_logs: u64,
93    /// Maximum total length in bytes of all log messages.
94    pub max_total_log_length: u64,
95
96    /// Max total prepaid gas for all function call actions per receipt.
97    pub max_total_prepaid_gas: Gas,
98
99    /// Max number of actions per receipt.
100    pub max_actions_per_receipt: u64,
101    /// Max total length of all method names (including terminating character) for a function call
102    /// permission access key.
103    pub max_number_bytes_method_names: u64,
104    /// Max length of any method name (without terminating character).
105    pub max_length_method_name: u64,
106    /// Max length of arguments in a function call action.
107    pub max_arguments_length: u64,
108    /// Max length of returned data
109    pub max_length_returned_data: u64,
110    /// Max contract size
111    pub max_contract_size: u64,
112    /// Max transaction size
113    pub max_transaction_size: u64,
114    /// Max receipt size
115    pub max_receipt_size: u64,
116    /// Max storage key size
117    pub max_length_storage_key: u64,
118    /// Max storage value size
119    pub max_length_storage_value: u64,
120    /// Max number of promises that a function call can create
121    pub max_promises_per_function_call_action: u64,
122    /// Max number of input data dependencies
123    pub max_number_input_data_dependencies: u64,
124    /// If present, stores max number of functions in one contract
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub max_functions_number_per_contract: Option<u64>,
127    /// If present, stores the secondary stack limit as implemented by wasmer2.
128    ///
129    /// This limit should never be hit normally.
130    #[serde(default = "wasmer2_stack_limit_default")]
131    pub wasmer2_stack_limit: i32,
132    /// If present, stores max number of locals declared globally in one contract
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub max_locals_per_contract: Option<u64>,
135    /// Whether to enforce account_id well-formed-ness where it wasn't enforced
136    /// historically.
137    #[serde(default = "AccountIdValidityRulesVersion::v0")]
138    pub account_id_validity_rules_version: AccountIdValidityRulesVersion,
139    /// Number of blocks after which a yielded promise times out.
140    pub yield_timeout_length_in_blocks: u64,
141    /// Maximum number of bytes for payload passed over a yield resume.
142    pub max_yield_payload_size: u64,
143    /// Hard limit on the size of storage proof generated while executing a single receipt.
144    pub per_receipt_storage_proof_size_limit: usize,
145}
146
147/// Dynamic configuration parameters required for the WASM runtime to
148/// execute a smart contract.
149///
150/// This (`VMConfig`) and `RuntimeFeesConfig` combined are sufficient to define
151/// protocol specific behavior of the contract runtime. The former contains
152/// configuration for the WASM runtime specifically, while the latter contains
153/// configuration for the transaction runtime and WASM runtime.
154#[derive(Clone, Debug, Hash, PartialEq, Eq)]
155pub struct Config {
156    /// Costs for runtime externals
157    pub ext_costs: ExtCostsConfig,
158
159    /// Gas cost of a growing memory by single page.
160    pub grow_mem_cost: u32,
161
162    /// Gas cost of a regular operation.
163    pub regular_op_cost: u32,
164
165    /// The kind of the VM implementation to use
166    pub vm_kind: VMKind,
167
168    /// Disable the fix for the #9393 issue in near-vm-runner.
169    pub disable_9393_fix: bool,
170
171    /// Set to `StorageGetMode::FlatStorage` in order to enable the `FlatStorageReads` protocol
172    /// feature.
173    pub storage_get_mode: StorageGetMode,
174
175    /// Enable the `FixContractLoadingCost` protocol feature.
176    pub fix_contract_loading_cost: bool,
177
178    /// Enable the `ImplicitAccountCreation` protocol feature.
179    pub implicit_account_creation: bool,
180
181    /// Enable the host functions added by the `MathExtension` protocol feature.
182    pub math_extension: bool,
183
184    /// Enable the host functions added by the `Ed25519Verify` protocol feature.
185    pub ed25519_verify: bool,
186
187    /// Enable the host functions added by the `AltBn128` protocol feature.
188    pub alt_bn128: bool,
189
190    /// Enable the `FunctionCallWeight` protocol feature.
191    pub function_call_weight: bool,
192
193    /// Enable the `EthImplicitAccounts` protocol feature.
194    pub eth_implicit_accounts: bool,
195
196    /// Enable the `promise_yield_create` and `promise_yield_resume` host functions.
197    pub yield_resume_host_functions: bool,
198
199    /// Whether to discard custom sections.
200    pub discard_custom_sections: bool,
201
202    /// Describes limits for VM and Runtime.
203    pub limit_config: LimitConfig,
204}
205
206impl Config {
207    /// Computes non-cryptographically-proof hash. The computation is fast but not cryptographically
208    /// secure.
209    pub fn non_crypto_hash(&self) -> u64 {
210        let mut s = DefaultHasher::new();
211        self.hash(&mut s);
212        s.finish()
213    }
214
215    pub fn make_free(&mut self) {
216        self.ext_costs = ExtCostsConfig {
217            costs: near_primitives_core::enum_map::enum_map! {
218                _ => ParameterCost { gas: 0, compute: 0 }
219            },
220        };
221        self.grow_mem_cost = 0;
222        self.regular_op_cost = 0;
223        self.limit_config.max_gas_burnt = u64::MAX;
224    }
225
226    pub fn enable_all_features(&mut self) {
227        self.yield_resume_host_functions = true;
228        self.eth_implicit_accounts = true;
229        self.function_call_weight = true;
230        self.alt_bn128 = true;
231        self.ed25519_verify = true;
232        self.math_extension = true;
233        self.implicit_account_creation = true;
234    }
235}
236
237fn wasmer2_stack_limit_default() -> i32 {
238    100 * 1024
239}
240
241/// Our original code for limiting WASM stack was buggy. We fixed that, but we
242/// still have to use old (`V0`) limiter for old protocol versions.
243///
244/// This struct here exists to enforce that the value in the config is either
245/// `0` or `1`. We could have used a `bool` instead, but there's a chance that
246/// our current impl isn't perfect either and would need further tweaks in the
247/// future.
248#[derive(
249    Debug,
250    Clone,
251    Copy,
252    Hash,
253    PartialEq,
254    Eq,
255    serde_repr::Serialize_repr,
256    serde_repr::Deserialize_repr,
257)]
258#[repr(u8)]
259pub enum ContractPrepareVersion {
260    /// Oldest, buggiest version.
261    ///
262    /// Don't use it unless specifically to support old protocol version.
263    V0,
264    /// Old, slow and buggy version.
265    ///
266    /// Better than V0, but don’t use this nevertheless.
267    V1,
268    /// finite-wasm 0.3.0 based contract preparation code.
269    V2,
270}
271
272impl ContractPrepareVersion {
273    pub fn v0() -> ContractPrepareVersion {
274        ContractPrepareVersion::V0
275    }
276}