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
91 /// Max total prepaid gas for all function call actions per receipt.
92 pub max_total_prepaid_gas: Gas,
93
94 /// Max number of actions per receipt.
95 pub max_actions_per_receipt: u64,
96 /// Max total length of all method names (including terminating character) for a function call
97 /// permission access key.
98 pub max_number_bytes_method_names: u64,
99 /// Max length of any method name (without terminating character).
100 pub max_length_method_name: u64,
101 /// Max length of arguments in a function call action.
102 pub max_arguments_length: u64,
103 /// Max length of returned data
104 pub max_length_returned_data: u64,
105 /// Max contract size
106 pub max_contract_size: u64,
107 /// Max transaction size
108 pub max_transaction_size: u64,
109 /// Max receipt size
110 pub max_receipt_size: u64,
111 /// Max storage key size
112 pub max_length_storage_key: u64,
113 /// Max storage value size
114 pub max_length_storage_value: u64,
115 /// Max number of promises that a function call can create
116 pub max_promises_per_function_call_action: u64,
117 /// Max number of input data dependencies
118 pub max_number_input_data_dependencies: u64,
119 /// If present, stores max number of functions in one contract
120 #[serde(skip_serializing_if = "Option::is_none")]
121 pub max_functions_number_per_contract: Option<u64>,
122 /// If present, stores max number of locals declared globally in one contract
123 #[serde(skip_serializing_if = "Option::is_none")]
124 pub max_locals_per_contract: Option<u64>,
125 /// Whether to enforce account_id well-formed-ness where it wasn't enforced
126 /// historically.
127 #[serde(default = "AccountIdValidityRulesVersion::v0")]
128 pub account_id_validity_rules_version: AccountIdValidityRulesVersion,
129 /// Number of blocks after which a yielded promise times out.
130 pub yield_timeout_length_in_blocks: u64,
131 /// Maximum number of bytes for payload passed over a yield resume.
132 pub max_yield_payload_size: u64,
133 /// Hard limit on the size of storage proof generated while executing a single receipt.
134 pub per_receipt_storage_proof_size_limit: usize,
135}
136
137/// Dynamic configuration parameters required for the WASM runtime to
138/// execute a smart contract.
139///
140/// This (`VMConfig`) and `RuntimeFeesConfig` combined are sufficient to define
141/// protocol specific behavior of the contract runtime. The former contains
142/// configuration for the WASM runtime specifically, while the latter contains
143/// configuration for the transaction runtime and WASM runtime.
144#[derive(Clone, Debug, Hash, PartialEq, Eq)]
145pub struct Config {
146 /// Costs for runtime externals
147 pub ext_costs: ExtCostsConfig,
148
149 /// Gas cost of a growing memory by single page.
150 pub grow_mem_cost: u32,
151
152 /// Gas cost of a regular operation.
153 pub regular_op_cost: u32,
154
155 /// The kind of the VM implementation to use
156 pub vm_kind: VMKind,
157
158 /// Set to `StorageGetMode::FlatStorage` in order to enable the `FlatStorageReads` protocol
159 /// feature.
160 pub storage_get_mode: StorageGetMode,
161
162 /// Enable the `FixContractLoadingCost` protocol feature.
163 pub fix_contract_loading_cost: bool,
164
165 /// Enable the `ImplicitAccountCreation` protocol feature.
166 pub implicit_account_creation: bool,
167
168 /// Enable the `EthImplicitAccounts` protocol feature.
169 pub eth_implicit_accounts: bool,
170
171 /// Whether to discard custom sections.
172 pub discard_custom_sections: bool,
173
174 /// Whether to enable saturating float-to-integer wasm operators.
175 pub saturating_float_to_int: bool,
176
177 /// Whether to enable global contract related host functions.
178 pub global_contract_host_fns: bool,
179
180 /// Describes limits for VM and Runtime.
181 pub limit_config: LimitConfig,
182}
183
184impl Config {
185 /// Computes non-cryptographically-proof hash. The computation is fast but not cryptographically
186 /// secure.
187 pub fn non_crypto_hash(&self) -> u64 {
188 let mut s = DefaultHasher::new();
189 self.hash(&mut s);
190 s.finish()
191 }
192
193 pub fn make_free(&mut self) {
194 self.ext_costs = ExtCostsConfig {
195 costs: near_primitives_core::enum_map::enum_map! {
196 _ => ParameterCost { gas: 0, compute: 0 }
197 },
198 };
199 self.grow_mem_cost = 0;
200 self.regular_op_cost = 0;
201 self.limit_config.max_gas_burnt = u64::MAX;
202 }
203
204 pub fn enable_all_features(&mut self) {
205 self.eth_implicit_accounts = true;
206 self.global_contract_host_fns = true;
207 self.implicit_account_creation = true;
208 }
209}
210
211/// Our original code for limiting WASM stack was buggy. We fixed that, but we
212/// still have to use old (`V0`) limiter for old protocol versions.
213///
214/// This struct here exists to enforce that the value in the config is either
215/// `0` or `1`. We could have used a `bool` instead, but there's a chance that
216/// our current impl isn't perfect either and would need further tweaks in the
217/// future.
218#[derive(
219 Debug,
220 Clone,
221 Copy,
222 Hash,
223 PartialEq,
224 Eq,
225 serde_repr::Serialize_repr,
226 serde_repr::Deserialize_repr,
227)]
228#[repr(u8)]
229pub enum ContractPrepareVersion {
230 /// Oldest, buggiest version.
231 ///
232 /// Don't use it unless specifically to support old protocol version.
233 V0,
234 /// Old, slow and buggy version.
235 ///
236 /// Better than V0, but don’t use this nevertheless.
237 V1,
238 /// finite-wasm 0.3.0 based contract preparation code.
239 V2,
240}
241
242impl ContractPrepareVersion {
243 pub fn v0() -> ContractPrepareVersion {
244 ContractPrepareVersion::V0
245 }
246}