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