/__w/smoldot/smoldot/repo/lib/src/executor/host.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Smoldot |
2 | | // Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. |
3 | | // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 |
4 | | |
5 | | // This program is free software: you can redistribute it and/or modify |
6 | | // it under the terms of the GNU General Public License as published by |
7 | | // the Free Software Foundation, either version 3 of the License, or |
8 | | // (at your option) any later version. |
9 | | |
10 | | // This program is distributed in the hope that it will be useful, |
11 | | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | // GNU General Public License for more details. |
14 | | |
15 | | // You should have received a copy of the GNU General Public License |
16 | | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | | |
18 | | //! Wasm virtual machine specific to the Substrate/Polkadot Runtime Environment. |
19 | | //! |
20 | | //! Contrary to [`VirtualMachine`](super::vm::VirtualMachine), this code is not just a generic |
21 | | //! Wasm virtual machine, but is aware of the Substrate/Polkadot runtime environment. The host |
22 | | //! functions that the Wasm code calls are automatically resolved and either handled or notified |
23 | | //! to the user of this module. |
24 | | //! |
25 | | //! Any host function that requires pure CPU computations (for example building or verifying |
26 | | //! a cryptographic signature) is directly handled by the code in this module. Other host |
27 | | //! functions (for example accessing the state or printing a message) are instead handled by |
28 | | //! interrupting the virtual machine and waiting for the user of this module to handle the call. |
29 | | //! |
30 | | //! > **Note**: The `ext_offchain_random_seed_version_1` and `ext_offchain_timestamp_version_1` |
31 | | //! > functions, which requires the host to respectively produce a random seed and |
32 | | //! > return the current time, must also be handled by the user. While these functions |
33 | | //! > could theoretically be handled directly by this module, it might be useful for |
34 | | //! > testing purposes to have the possibility to return a deterministic value. |
35 | | //! |
36 | | //! Contrary to most programs, runtime code doesn't have a singe `main` or `start` function. |
37 | | //! Instead, it exposes several entry points. Which one to call indicates which action it has to |
38 | | //! perform. Not all entry points are necessarily available on all runtimes. |
39 | | //! |
40 | | //! # Runtime requirements |
41 | | //! |
42 | | //! See the [documentation of the `vm` module](super::vm) for details about the requirements a |
43 | | //! runtime must adhere to. |
44 | | //! |
45 | | //! In addition to the requirements described there, the WebAssembly runtime code can also be |
46 | | //! zstandard-compressed and must also export a global symbol named `__heap_base`. |
47 | | //! More details below. |
48 | | //! |
49 | | //! ## `Zstandard` compression |
50 | | //! |
51 | | //! The runtime code passed as parameter to [`HostVmPrototype::new`] can be compressed using the |
52 | | //! [`zstd`](https://en.wikipedia.org/wiki/Zstandard) algorithm. |
53 | | //! |
54 | | //! If the code starts with the magic bytes `[82, 188, 83, 118, 70, 219, 142, 5]`, then it is |
55 | | //! assumed that the rest of the data is a zstandard-compressed WebAssembly module. |
56 | | //! |
57 | | //! ## Runtime version |
58 | | //! |
59 | | //! Wasm files can contain so-called custom sections. A runtime can contain two custom sections |
60 | | //! whose names are `"runtime_version"` and `"runtime_apis"`, in which case they must contain a |
61 | | //! so-called runtime version. |
62 | | //! |
63 | | //! The runtime version contains important field that identifies a runtime. |
64 | | //! |
65 | | //! If no `"runtime_version"` and `"runtime_apis"` custom sections can be found, the |
66 | | //! `Core_version` entry point is used as a fallback in order to obtain the runtime version. This |
67 | | //! fallback mechanism is maintained for backwards compatibility purposes, but is considered |
68 | | //! deprecated. |
69 | | //! |
70 | | //! ## Memory allocations |
71 | | //! |
72 | | //! One of the instructions available in WebAssembly code is |
73 | | //! [the `memory.grow` instruction](https://webassembly.github.io/spec/core/bikeshed/#-hrefsyntax-instr-memorymathsfmemorygrow), |
74 | | //! which allows increasing the size of the memory. |
75 | | //! |
76 | | //! WebAssembly code is normally intended to perform its own heap-management logic internally, and |
77 | | //! use the `memory.grow` instruction if more memory is needed. |
78 | | //! |
79 | | //! In order to minimize the size of the runtime binary, and in order to accommodate for the API of |
80 | | //! the host functions that return a buffer of variable length, the Substrate/Polkadot runtimes, |
81 | | //! however, do not perform their heap management internally. Instead, they use the |
82 | | //! `ext_allocator_malloc_version_1` and `ext_allocator_free_version_1` host functions for this |
83 | | //! purpose. Calling `memory.grow` is forbidden. |
84 | | //! |
85 | | //! The runtime code must export a global symbol named `__heap_base` of type `i32`. Any memory |
86 | | //! whose offset is below the value of `__heap_base` can be used at will by the program, while |
87 | | //! any memory above `__heap_base` but below `__heap_base + heap_pages` (where `heap_pages` is |
88 | | //! the value passed as parameter to [`HostVmPrototype::new`]) is available for use by the |
89 | | //! implementation of `ext_allocator_malloc_version_1`. |
90 | | //! |
91 | | //! ## Entry points |
92 | | //! |
93 | | //! All entry points that can be called from the host (using, for example, |
94 | | //! [`HostVmPrototype::run`]) have the same signature: |
95 | | //! |
96 | | //! ```ignore |
97 | | //! (func $runtime_entry(param $data i32) (param $len i32) (result i64)) |
98 | | //! ``` |
99 | | //! |
100 | | //! In order to call into the runtime, one must write a buffer of data containing the input |
101 | | //! parameters into the Wasm virtual machine's memory, then pass a pointer and length of this |
102 | | //! buffer as the parameters of the entry point. |
103 | | //! |
104 | | //! The function returns a 64 bits number. The 32 less significant bits represent a pointer to the |
105 | | //! Wasm virtual machine's memory, and the 32 most significant bits a length. This pointer and |
106 | | //! length designate a buffer containing the actual return value. |
107 | | //! |
108 | | //! ## Host functions |
109 | | //! |
110 | | //! The list of host functions available to the runtime is long and isn't documented here. See |
111 | | //! the official specification for details. |
112 | | //! |
113 | | //! # Usage |
114 | | //! |
115 | | //! The first step is to create a [`HostVmPrototype`] object from the WebAssembly code. Creating |
116 | | //! this object performs some initial steps, such as parsing and compiling the WebAssembly code. |
117 | | //! You are encouraged to maintain a cache of [`HostVmPrototype`] objects (one instance per |
118 | | //! WebAssembly byte code) in order to avoid performing these operations too often. |
119 | | //! |
120 | | //! To start calling the runtime, create a [`HostVm`] by calling [`HostVmPrototype::run`]. |
121 | | //! |
122 | | //! While the Wasm runtime code has side-effects (such as storing values in the storage), the |
123 | | //! [`HostVm`] itself is a pure state machine with no side effects. |
124 | | //! |
125 | | //! At any given point, you can examine the [`HostVm`] in order to know in which state the |
126 | | //! execution currently is. |
127 | | //! In case of a [`HostVm::ReadyToRun`] (which initially is the case when you create the |
128 | | //! [`HostVm`]), you can execute the Wasm code by calling [`ReadyToRun::run`]. |
129 | | //! No background thread of any kind is used, and calling [`ReadyToRun::run`] directly performs |
130 | | //! the execution of the Wasm code. If you need parallelism, you are encouraged to spawn a |
131 | | //! background thread yourself and call this function from there. |
132 | | //! [`ReadyToRun::run`] tries to make the execution progress as much as possible, and returns |
133 | | //! the new state of the virtual machine once that is done. |
134 | | //! |
135 | | //! If the runtime has finished, or has crashed, or wants to perform an operation with side |
136 | | //! effects, then the [`HostVm`] determines what to do next. For example, for |
137 | | //! [`HostVm::ExternalStorageGet`], you must load a value from the storage and pass it back by |
138 | | //! calling [`ExternalStorageGet::resume`]. |
139 | | //! |
140 | | //! The Wasm execution is fully deterministic, and the outcome of the execution only depends on |
141 | | //! the inputs. There is, for example, no implicit injection of randomness or of the current time. |
142 | | //! |
143 | | //! ## Example |
144 | | //! |
145 | | //! ``` |
146 | | //! use smoldot::executor::host::{ |
147 | | //! Config, HeapPages, HostVm, HostVmPrototype, StorageProofSizeBehavior |
148 | | //! }; |
149 | | //! |
150 | | //! # let wasm_binary_code: &[u8] = return; |
151 | | //! |
152 | | //! // Start executing a function on the runtime. |
153 | | //! let mut vm: HostVm = { |
154 | | //! let prototype = HostVmPrototype::new(Config { |
155 | | //! module: &wasm_binary_code, |
156 | | //! heap_pages: HeapPages::from(2048), |
157 | | //! exec_hint: smoldot::executor::vm::ExecHint::ValidateAndExecuteOnce, |
158 | | //! allow_unresolved_imports: false |
159 | | //! }).unwrap(); |
160 | | //! prototype.run_no_param( |
161 | | //! "Core_version", |
162 | | //! StorageProofSizeBehavior::proof_recording_disabled() |
163 | | //! ).unwrap().into() |
164 | | //! }; |
165 | | //! |
166 | | //! // We need to answer the calls that the runtime might perform. |
167 | | //! loop { |
168 | | //! match vm { |
169 | | //! // Calling `runner.run()` is what actually executes WebAssembly code and updates |
170 | | //! // the state. |
171 | | //! HostVm::ReadyToRun(runner) => vm = runner.run(), |
172 | | //! |
173 | | //! HostVm::Finished(finished) => { |
174 | | //! // `finished.value()` here is an opaque blob of bytes returned by the runtime. |
175 | | //! // In the case of a call to `"Core_version"`, we know that it must be empty. |
176 | | //! assert!(finished.value().as_ref().is_empty()); |
177 | | //! println!("Success!"); |
178 | | //! break; |
179 | | //! }, |
180 | | //! |
181 | | //! // Errors can happen if the WebAssembly code panics or does something wrong. |
182 | | //! // In a real-life situation, the host should obviously not panic in these situations. |
183 | | //! HostVm::Error { .. } => { |
184 | | //! panic!("Error while executing code") |
185 | | //! }, |
186 | | //! |
187 | | //! // All the other variants correspond to function calls that the runtime might perform. |
188 | | //! // `ExternalStorageGet` is shown here as an example. |
189 | | //! HostVm::ExternalStorageGet(req) => { |
190 | | //! println!("Runtime requires the storage value at {:?}", req.key().as_ref()); |
191 | | //! // Injects the value into the virtual machine and updates the state. |
192 | | //! vm = req.resume(None); // Just a stub |
193 | | //! } |
194 | | //! _ => unimplemented!() |
195 | | //! } |
196 | | //! } |
197 | | //! ``` |
198 | | |
199 | | use super::{allocator, vm}; |
200 | | use crate::{trie, util}; |
201 | | |
202 | | use alloc::{borrow::ToOwned as _, boxed::Box, string::String, sync::Arc, vec, vec::Vec}; |
203 | | use core::{fmt, hash::Hasher as _, iter, str}; |
204 | | use functions::HostFunction; |
205 | | |
206 | | pub mod runtime_version; |
207 | | |
208 | | pub use runtime_version::{ |
209 | | CoreVersion, CoreVersionApisFromSliceErr, CoreVersionError, CoreVersionRef, |
210 | | FindEncodedEmbeddedRuntimeVersionApisError, |
211 | | }; |
212 | | pub use trie::TrieEntryVersion; |
213 | | pub use vm::HeapPages; |
214 | | pub use zstd::Error as ModuleFormatError; |
215 | | |
216 | | mod functions; |
217 | | mod tests; |
218 | | mod zstd; |
219 | | |
220 | | /// Configuration for [`HostVmPrototype::new`]. |
221 | | pub struct Config<TModule> { |
222 | | /// Bytes of the WebAssembly module. |
223 | | /// |
224 | | /// The module can be either directly Wasm bytecode, or zstandard-compressed. |
225 | | pub module: TModule, |
226 | | |
227 | | /// Number of pages of heap available to the virtual machine. |
228 | | /// |
229 | | /// See the module-level documentation for an explanation. |
230 | | pub heap_pages: HeapPages, |
231 | | |
232 | | /// Hint used by the implementation to decide which kind of virtual machine to use. |
233 | | pub exec_hint: vm::ExecHint, |
234 | | |
235 | | /// If `true`, no [`vm::NewErr::UnresolvedFunctionImport`] error will be returned if the |
236 | | /// module trying to import functions that aren't recognized by the implementation. Instead, |
237 | | /// a [`Error::UnresolvedFunctionCalled`] error will be generated if the module tries to call |
238 | | /// an unresolved function. |
239 | | pub allow_unresolved_imports: bool, |
240 | | } |
241 | | |
242 | | /// Behavior if the `ext_storage_proof_size_storage_proof_size_version_1` host function is called. |
243 | | /// |
244 | | /// When authoring a block or executing a block, this host function is expected to return the |
245 | | /// current size of the proof. Smoldot unfortunately can't implement this due to the fact that |
246 | | /// the proof generation algorithm is completely unspecified. For this reason, you should |
247 | | /// use [`StorageProofSizeBehavior::Unimplemented`]. However, for testing purposes, using |
248 | | /// `StorageProofSizeBehavior::ConstantReturnValue(0)` is acceptable. |
249 | | /// |
250 | | /// In situations other than authoring or executing a block, use the value returned by |
251 | | /// [`StorageProofSizeBehavior::proof_recording_disabled`]. |
252 | | /// |
253 | | #[derive(Debug, Clone, PartialEq, Eq)] |
254 | | pub enum StorageProofSizeBehavior { |
255 | | /// The host function is unimplemented. An error is returned if it is called. |
256 | | Unimplemented, |
257 | | /// The host function returns the given value. |
258 | | ConstantReturnValue(u64), |
259 | | } |
260 | | |
261 | | impl StorageProofSizeBehavior { |
262 | | /// Returns the behavior to employ when proof recording is disabled, as defined in the |
263 | | /// specification. |
264 | 171 | pub fn proof_recording_disabled() -> Self { |
265 | 171 | StorageProofSizeBehavior::ConstantReturnValue(u64::MAX) |
266 | 171 | } _RNvMNtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB2_24StorageProofSizeBehavior24proof_recording_disabled Line | Count | Source | 264 | 44 | pub fn proof_recording_disabled() -> Self { | 265 | 44 | StorageProofSizeBehavior::ConstantReturnValue(u64::MAX) | 266 | 44 | } |
_RNvMNtNtCseuYC0Zibziv_7smoldot8executor4hostNtB2_24StorageProofSizeBehavior24proof_recording_disabled Line | Count | Source | 264 | 127 | pub fn proof_recording_disabled() -> Self { | 265 | 127 | StorageProofSizeBehavior::ConstantReturnValue(u64::MAX) | 266 | 127 | } |
|
267 | | } |
268 | | |
269 | | /// Prototype for an [`HostVm`]. |
270 | | /// |
271 | | /// > **Note**: This struct implements `Clone`. Cloning a [`HostVmPrototype`] allocates memory |
272 | | /// > necessary for the clone to run. |
273 | | #[derive(Clone)] |
274 | | pub struct HostVmPrototype { |
275 | | /// Fields that are kept as is even during the execution. |
276 | | common: Box<VmCommon>, |
277 | | |
278 | | /// Inner virtual machine prototype. |
279 | | vm_proto: vm::VirtualMachinePrototype, |
280 | | } |
281 | | |
282 | | /// Fields that are kept as is even during the execution. |
283 | | #[derive(Clone)] |
284 | | struct VmCommon { |
285 | | /// Runtime version of this runtime. |
286 | | /// |
287 | | /// Always `Some`, except at initialization. |
288 | | runtime_version: Option<CoreVersion>, |
289 | | |
290 | | /// Initial value of the `__heap_base` global in the Wasm module. Used to initialize the memory |
291 | | /// allocator. |
292 | | heap_base: u32, |
293 | | |
294 | | /// List of functions that the Wasm code imports. |
295 | | /// |
296 | | /// The keys of this list (i.e. the `usize` indices) have been passed to the virtual machine |
297 | | /// executor. Whenever the Wasm code invokes a host function, we obtain its index, and look |
298 | | /// within this list to know what to do. |
299 | | registered_functions: Arc<[FunctionImport]>, |
300 | | |
301 | | /// Value of `heap_pages` passed to [`HostVmPrototype::new`]. |
302 | | heap_pages: HeapPages, |
303 | | |
304 | | /// Total number of pages of Wasm memory. This is equal to `heap_base / 64k` (rounded up) plus |
305 | | /// `heap_pages`. |
306 | | memory_total_pages: HeapPages, |
307 | | } |
308 | | |
309 | | impl HostVmPrototype { |
310 | | /// Creates a new [`HostVmPrototype`]. Parses and potentially JITs the module. |
311 | 154 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { |
312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst |
313 | | // all implementations. |
314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. |
315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. |
316 | 154 | let module_bytes152 = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) |
317 | 154 | .map_err(NewErr::BadFormat)?2 ; |
318 | | |
319 | | // Try to find the runtime version as Wasm custom sections. |
320 | | // An error is returned if the sections have a wrong format, in which case we fail the |
321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are |
322 | | // missing, and we will instead try to retrieve the version through a runtime call later |
323 | | // down this function. |
324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present |
325 | | // but not the other, we must ignore the custom sections. This is necessary due to some |
326 | | // historical accidents. |
327 | 152 | let runtime_version150 = match runtime_version::find_embedded_runtime_version(&module_bytes) { |
328 | 147 | Ok(Some(r)) => Some(r), |
329 | 1 | Ok(None) => None, |
330 | | Err( |
331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, |
332 | 2 | ) => None, |
333 | 2 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { |
334 | 2 | return Err(NewErr::RuntimeVersion( |
335 | 2 | FindEmbeddedRuntimeVersionError::FindSections(err), |
336 | 2 | )) |
337 | | } |
338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { |
339 | 0 | return Err(NewErr::RuntimeVersion( |
340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), |
341 | 0 | )) |
342 | | } |
343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { |
344 | 0 | return Err(NewErr::RuntimeVersion( |
345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, |
346 | 0 | )) |
347 | | } |
348 | | }; |
349 | | |
350 | | // Initialize the virtual machine. |
351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, |
352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that |
353 | | // array. |
354 | 144 | let (mut vm_proto, registered_functions) = { |
355 | 150 | let mut registered_functions = Vec::new(); |
356 | 150 | let vm_proto144 = vm::VirtualMachinePrototype::new(vm::Config { |
357 | 150 | module_bytes: &module_bytes[..], |
358 | 150 | exec_hint: config.exec_hint, |
359 | 150 | // This closure is called back for each function that the runtime imports. |
360 | 2.95k | symbols: &mut |mod_name, f_name, signature| { |
361 | 2.95k | if mod_name != "env" { |
362 | 0 | return Err(()); |
363 | 2.95k | } |
364 | 2.95k | |
365 | 2.95k | let id = registered_functions.len(); |
366 | 2.95k | registered_functions.push(match HostFunction::by_name(f_name) { |
367 | 2.94k | Some(f2.93k ) if f.signature() == *signature => FunctionImport::Resolved(f)2.93k , |
368 | 6 | Some(_) | None if !config.allow_unresolved_imports => { |
369 | | // TODO: return a better error if there is a signature mismatch |
370 | 6 | return Err(()); |
371 | | } |
372 | 13 | Some(_) | None => FunctionImport::Unresolved { |
373 | 13 | name: f_name.to_owned(), |
374 | 13 | module: mod_name.to_owned(), |
375 | 13 | }, |
376 | | }); |
377 | 2.94k | Ok(id) |
378 | 2.95k | }, Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtB9_2vm11interpreterNtB1R_11Interpreter11read_memory12AccessOffsetB1F_EEE0Bb_ _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEE0Bb_ Line | Count | Source | 360 | 46 | symbols: &mut |mod_name, f_name, signature| { | 361 | 46 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 46 | } | 364 | 46 | | 365 | 46 | let id = registered_functions.len(); | 366 | 46 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 46 | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | 0 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 0 | return Err(()); | 371 | | } | 372 | 0 | Some(_) | None => FunctionImport::Unresolved { | 373 | 0 | name: f_name.to_owned(), | 374 | 0 | module: mod_name.to_owned(), | 375 | 0 | }, | 376 | | }); | 377 | 46 | Ok(id) | 378 | 46 | }, |
_RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEE0Bb_ Line | Count | Source | 360 | 170 | symbols: &mut |mod_name, f_name, signature| { | 361 | 170 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 170 | } | 364 | 170 | | 365 | 170 | let id = registered_functions.len(); | 366 | 170 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 162 | Some(f158 ) if f.signature() == *signature => FunctionImport::Resolved(f)158 , | 368 | 6 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 6 | return Err(()); | 371 | | } | 372 | 6 | Some(_) | None => FunctionImport::Unresolved { | 373 | 6 | name: f_name.to_owned(), | 374 | 6 | module: mod_name.to_owned(), | 375 | 6 | }, | 376 | | }); | 377 | 164 | Ok(id) | 378 | 170 | }, |
Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRAhj6_E0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRAhj6b_E0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRAhjd_E0Bb_ _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShE0Bb_ Line | Count | Source | 360 | 149 | symbols: &mut |mod_name, f_name, signature| { | 361 | 149 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 149 | } | 364 | 149 | | 365 | 149 | let id = registered_functions.len(); | 366 | 149 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 142 | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | 0 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 0 | return Err(()); | 371 | | } | 372 | 7 | Some(_) | None => FunctionImport::Unresolved { | 373 | 7 | name: f_name.to_owned(), | 374 | 7 | module: mod_name.to_owned(), | 375 | 7 | }, | 376 | | }); | 377 | 149 | Ok(id) | 378 | 149 | }, |
_RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShE0Bb_ Line | Count | Source | 360 | 96 | symbols: &mut |mod_name, f_name, signature| { | 361 | 96 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 96 | } | 364 | 96 | | 365 | 96 | let id = registered_functions.len(); | 366 | 96 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 96 | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | 0 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 0 | return Err(()); | 371 | | } | 372 | 0 | Some(_) | None => FunctionImport::Unresolved { | 373 | 0 | name: f_name.to_owned(), | 374 | 0 | module: mod_name.to_owned(), | 375 | 0 | }, | 376 | | }); | 377 | 96 | Ok(id) | 378 | 96 | }, |
Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEE0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShE0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtB9_2vm11interpreterNtB1S_11Interpreter11read_memory12AccessOffsetB1G_EEE0Bb_ _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEE0Bb_ Line | Count | Source | 360 | 609 | symbols: &mut |mod_name, f_name, signature| { | 361 | 609 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 609 | } | 364 | 609 | | 365 | 609 | let id = registered_functions.len(); | 366 | 609 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 609 | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | 0 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 0 | return Err(()); | 371 | | } | 372 | 0 | Some(_) | None => FunctionImport::Unresolved { | 373 | 0 | name: f_name.to_owned(), | 374 | 0 | module: mod_name.to_owned(), | 375 | 0 | }, | 376 | | }); | 377 | 609 | Ok(id) | 378 | 609 | }, |
_RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShE0Bb_ Line | Count | Source | 360 | 609 | symbols: &mut |mod_name, f_name, signature| { | 361 | 609 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 609 | } | 364 | 609 | | 365 | 609 | let id = registered_functions.len(); | 366 | 609 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 609 | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | 0 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 0 | return Err(()); | 371 | | } | 372 | 0 | Some(_) | None => FunctionImport::Unresolved { | 373 | 0 | name: f_name.to_owned(), | 374 | 0 | module: mod_name.to_owned(), | 375 | 0 | }, | 376 | | }); | 377 | 609 | Ok(id) | 378 | 609 | }, |
_RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEE0CsiLzmwikkc22_14json_rpc_basic Line | Count | Source | 360 | 58 | symbols: &mut |mod_name, f_name, signature| { | 361 | 58 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 58 | } | 364 | 58 | | 365 | 58 | let id = registered_functions.len(); | 366 | 58 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 58 | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | 0 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 0 | return Err(()); | 371 | | } | 372 | 0 | Some(_) | None => FunctionImport::Unresolved { | 373 | 0 | name: f_name.to_owned(), | 374 | 0 | module: mod_name.to_owned(), | 375 | 0 | }, | 376 | | }); | 377 | 58 | Ok(id) | 378 | 58 | }, |
Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEE0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShE0CsiLzmwikkc22_14json_rpc_basic _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShE0CsiLzmwikkc22_14json_rpc_basic Line | Count | Source | 360 | 58 | symbols: &mut |mod_name, f_name, signature| { | 361 | 58 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 58 | } | 364 | 58 | | 365 | 58 | let id = registered_functions.len(); | 366 | 58 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 58 | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | 0 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 0 | return Err(()); | 371 | | } | 372 | 0 | Some(_) | None => FunctionImport::Unresolved { | 373 | 0 | name: f_name.to_owned(), | 374 | 0 | module: mod_name.to_owned(), | 375 | 0 | }, | 376 | | }); | 377 | 58 | Ok(id) | 378 | 58 | }, |
_RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEE0CsiUjFBJteJ7x_17smoldot_full_node Line | Count | Source | 360 | 58 | symbols: &mut |mod_name, f_name, signature| { | 361 | 58 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 58 | } | 364 | 58 | | 365 | 58 | let id = registered_functions.len(); | 366 | 58 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 58 | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | 0 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 0 | return Err(()); | 371 | | } | 372 | 0 | Some(_) | None => FunctionImport::Unresolved { | 373 | 0 | name: f_name.to_owned(), | 374 | 0 | module: mod_name.to_owned(), | 375 | 0 | }, | 376 | | }); | 377 | 58 | Ok(id) | 378 | 58 | }, |
Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEE0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEE0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShE0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShE0CscDgN54JpMGG_6author _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEE0CsibGXYHQB8Ea_25json_rpc_general_requests Line | Count | Source | 360 | 551 | symbols: &mut |mod_name, f_name, signature| { | 361 | 551 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 551 | } | 364 | 551 | | 365 | 551 | let id = registered_functions.len(); | 366 | 551 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 551 | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | 0 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 0 | return Err(()); | 371 | | } | 372 | 0 | Some(_) | None => FunctionImport::Unresolved { | 373 | 0 | name: f_name.to_owned(), | 374 | 0 | module: mod_name.to_owned(), | 375 | 0 | }, | 376 | | }); | 377 | 551 | Ok(id) | 378 | 551 | }, |
Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEE0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShE0CsibGXYHQB8Ea_25json_rpc_general_requests _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShE0CsibGXYHQB8Ea_25json_rpc_general_requests Line | Count | Source | 360 | 551 | symbols: &mut |mod_name, f_name, signature| { | 361 | 551 | if mod_name != "env" { | 362 | 0 | return Err(()); | 363 | 551 | } | 364 | 551 | | 365 | 551 | let id = registered_functions.len(); | 366 | 551 | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | 551 | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | 0 | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | 0 | return Err(()); | 371 | | } | 372 | 0 | Some(_) | None => FunctionImport::Unresolved { | 373 | 0 | name: f_name.to_owned(), | 374 | 0 | module: mod_name.to_owned(), | 375 | 0 | }, | 376 | | }); | 377 | 551 | Ok(id) | 378 | 551 | }, |
|
379 | 150 | })?6 ; |
380 | 144 | (vm_proto, registered_functions.into()) |
381 | | }; |
382 | | |
383 | | // In the runtime environment, Wasm blobs must export a global symbol named |
384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. |
385 | 144 | let heap_base142 = vm_proto |
386 | 144 | .global_value("__heap_base") |
387 | 144 | .map_err(|_| NewErr::HeapBaseNotFound2 )?2 ; Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtB9_2vm11interpreterNtB1R_11Interpreter11read_memory12AccessOffsetB1F_EEEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEs_0Bb_ _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEEs_0Bb_ Line | Count | Source | 387 | 2 | .map_err(|_| NewErr::HeapBaseNotFound)?; |
Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRAhj6_Es_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRAhj6b_Es_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRAhjd_Es_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEEs_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtB9_2vm11interpreterNtB1S_11Interpreter11read_memory12AccessOffsetB1G_EEEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEs_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEEs_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShEs_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEEs_0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEs_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEEs_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShEs_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEs_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEEs_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShEs_0CsibGXYHQB8Ea_25json_rpc_general_requests |
388 | | |
389 | 142 | let memory_total_pages = if heap_base == 0 { |
390 | 14 | config.heap_pages |
391 | | } else { |
392 | 128 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) |
393 | | }; |
394 | | |
395 | 142 | if vm_proto |
396 | 142 | .memory_max_pages() |
397 | 142 | .map_or(false, |max| max < memory_total_pages2 ) Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtB9_2vm11interpreterNtB1R_11Interpreter11read_memory12AccessOffsetB1F_EEEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEs0_0Bb_ _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEEs0_0Bb_ Line | Count | Source | 397 | 2 | .map_or(false, |max| max < memory_total_pages) |
Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRAhj6_Es0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRAhj6b_Es0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRAhjd_Es0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEEs0_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs0_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtB9_2vm11interpreterNtB1S_11Interpreter11read_memory12AccessOffsetB1G_EEEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEs0_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEEs0_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs0_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShEs0_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEEs0_0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEs0_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEEs0_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs0_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShEs0_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEs0_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEEs0_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRRShEs0_0CsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype3newRShEs0_0CsibGXYHQB8Ea_25json_rpc_general_requests |
398 | | { |
399 | 2 | return Err(NewErr::MemoryMaxSizeTooLow); |
400 | 140 | } |
401 | 140 | |
402 | 140 | let mut host_vm_prototype = HostVmPrototype { |
403 | 140 | vm_proto, |
404 | 140 | common: Box::new(VmCommon { |
405 | 140 | runtime_version, |
406 | 140 | heap_base, |
407 | 140 | registered_functions, |
408 | 140 | heap_pages: config.heap_pages, |
409 | 140 | memory_total_pages, |
410 | 140 | }), |
411 | 140 | }; |
412 | 140 | |
413 | 140 | // Call `Core_version` if no runtime version is known yet. |
414 | 140 | if host_vm_prototype.common.runtime_version.is_none() { |
415 | 3 | let mut vm: HostVm = match host_vm_prototype.run_no_param( |
416 | 3 | "Core_version", |
417 | 3 | StorageProofSizeBehavior::proof_recording_disabled(), |
418 | 3 | ) { |
419 | 3 | Ok(vm) => vm.into(), |
420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), |
421 | | }; |
422 | | |
423 | 10 | loop { |
424 | 10 | match vm { |
425 | 5 | HostVm::ReadyToRun(r) => vm = r.run(), |
426 | 3 | HostVm::Finished(finished) => { |
427 | 3 | let version = |
428 | 3 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { |
429 | 3 | Ok(v) => v, |
430 | | Err(_) => { |
431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) |
432 | | } |
433 | | }; |
434 | | |
435 | 3 | host_vm_prototype = finished.into_prototype(); |
436 | 3 | host_vm_prototype.common.runtime_version = Some(version); |
437 | 3 | break; |
438 | | } |
439 | | |
440 | | // Emitted log lines are ignored. |
441 | 2 | HostVm::GetMaxLogLevel(resume) => { |
442 | 2 | vm = resume.resume(0); // Off |
443 | 2 | } |
444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), |
445 | | |
446 | 0 | HostVm::Error { error, .. } => { |
447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) |
448 | | } |
449 | | |
450 | | // Getting the runtime version is a very core operation, and very few |
451 | | // external calls are allowed. |
452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), |
453 | | } |
454 | | } |
455 | 137 | } |
456 | | |
457 | | // Success! |
458 | 140 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); |
459 | 140 | Ok(host_vm_prototype) |
460 | 154 | } Unexecuted instantiation: _RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype3newINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtB7_2vm11interpreterNtB1P_11Interpreter11read_memory12AccessOffsetB1D_EEEB9_ _RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEB9_ Line | Count | Source | 311 | 1 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 1 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 1 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 1 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 1 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 1 | let (mut vm_proto, registered_functions) = { | 355 | 1 | let mut registered_functions = Vec::new(); | 356 | 1 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 1 | module_bytes: &module_bytes[..], | 358 | 1 | exec_hint: config.exec_hint, | 359 | 1 | // This closure is called back for each function that the runtime imports. | 360 | 1 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 1 | }, | 379 | 1 | })?0 ; | 380 | 1 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 1 | let heap_base = vm_proto | 386 | 1 | .global_value("__heap_base") | 387 | 1 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 1 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 1 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 1 | if vm_proto | 396 | 1 | .memory_max_pages() | 397 | 1 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 1 | } | 401 | 1 | | 402 | 1 | let mut host_vm_prototype = HostVmPrototype { | 403 | 1 | vm_proto, | 404 | 1 | common: Box::new(VmCommon { | 405 | 1 | runtime_version, | 406 | 1 | heap_base, | 407 | 1 | registered_functions, | 408 | 1 | heap_pages: config.heap_pages, | 409 | 1 | memory_total_pages, | 410 | 1 | }), | 411 | 1 | }; | 412 | 1 | | 413 | 1 | // Call `Core_version` if no runtime version is known yet. | 414 | 1 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 1 | } | 456 | | | 457 | | // Success! | 458 | 1 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 1 | Ok(host_vm_prototype) | 460 | 1 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEEB9_ Line | Count | Source | 311 | 56 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 56 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 56 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 56 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 56 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 50 | let (mut vm_proto, registered_functions) = { | 355 | 56 | let mut registered_functions = Vec::new(); | 356 | 56 | let vm_proto50 = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 56 | module_bytes: &module_bytes[..], | 358 | 56 | exec_hint: config.exec_hint, | 359 | 56 | // This closure is called back for each function that the runtime imports. | 360 | 56 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 56 | }, | 379 | 56 | })?6 ; | 380 | 50 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 50 | let heap_base48 = vm_proto | 386 | 50 | .global_value("__heap_base") | 387 | 50 | .map_err(|_| NewErr::HeapBaseNotFound)?2 ; | 388 | | | 389 | 48 | let memory_total_pages = if heap_base == 0 { | 390 | 12 | config.heap_pages | 391 | | } else { | 392 | 36 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 48 | if vm_proto | 396 | 48 | .memory_max_pages() | 397 | 48 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 2 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 46 | } | 401 | 46 | | 402 | 46 | let mut host_vm_prototype = HostVmPrototype { | 403 | 46 | vm_proto, | 404 | 46 | common: Box::new(VmCommon { | 405 | 46 | runtime_version, | 406 | 46 | heap_base, | 407 | 46 | registered_functions, | 408 | 46 | heap_pages: config.heap_pages, | 409 | 46 | memory_total_pages, | 410 | 46 | }), | 411 | 46 | }; | 412 | 46 | | 413 | 46 | // Call `Core_version` if no runtime version is known yet. | 414 | 46 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 46 | } | 456 | | | 457 | | // Success! | 458 | 46 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 46 | Ok(host_vm_prototype) | 460 | 56 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype3newRRAhj6_EB9_ Line | Count | Source | 311 | 2 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 2 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 2 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 2 | let runtime_version0 = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 0 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 2 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 2 | return Err(NewErr::RuntimeVersion( | 335 | 2 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 2 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 0 | let (mut vm_proto, registered_functions) = { | 355 | 0 | let mut registered_functions = Vec::new(); | 356 | 0 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 0 | module_bytes: &module_bytes[..], | 358 | 0 | exec_hint: config.exec_hint, | 359 | 0 | // This closure is called back for each function that the runtime imports. | 360 | 0 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 0 | }, | 379 | 0 | })?; | 380 | 0 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 0 | let heap_base = vm_proto | 386 | 0 | .global_value("__heap_base") | 387 | 0 | .map_err(|_| NewErr::HeapBaseNotFound)?; | 388 | | | 389 | 0 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 0 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 0 | if vm_proto | 396 | 0 | .memory_max_pages() | 397 | 0 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 0 | } | 401 | 0 |
| 402 | 0 | let mut host_vm_prototype = HostVmPrototype { | 403 | 0 | vm_proto, | 404 | 0 | common: Box::new(VmCommon { | 405 | 0 | runtime_version, | 406 | 0 | heap_base, | 407 | 0 | registered_functions, | 408 | 0 | heap_pages: config.heap_pages, | 409 | 0 | memory_total_pages, | 410 | 0 | }), | 411 | 0 | }; | 412 | 0 |
| 413 | 0 | // Call `Core_version` if no runtime version is known yet. | 414 | 0 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 0 | } | 456 | | | 457 | | // Success! | 458 | 0 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 0 | Ok(host_vm_prototype) | 460 | 2 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype3newRRAhj6b_EB9_ Line | Count | Source | 311 | 2 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 2 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 2 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 2 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 2 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 2 | let (mut vm_proto, registered_functions) = { | 355 | 2 | let mut registered_functions = Vec::new(); | 356 | 2 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 2 | module_bytes: &module_bytes[..], | 358 | 2 | exec_hint: config.exec_hint, | 359 | 2 | // This closure is called back for each function that the runtime imports. | 360 | 2 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 2 | }, | 379 | 2 | })?0 ; | 380 | 2 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 2 | let heap_base = vm_proto | 386 | 2 | .global_value("__heap_base") | 387 | 2 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 2 | let memory_total_pages = if heap_base == 0 { | 390 | 2 | config.heap_pages | 391 | | } else { | 392 | 0 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 2 | if vm_proto | 396 | 2 | .memory_max_pages() | 397 | 2 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 2 | } | 401 | 2 | | 402 | 2 | let mut host_vm_prototype = HostVmPrototype { | 403 | 2 | vm_proto, | 404 | 2 | common: Box::new(VmCommon { | 405 | 2 | runtime_version, | 406 | 2 | heap_base, | 407 | 2 | registered_functions, | 408 | 2 | heap_pages: config.heap_pages, | 409 | 2 | memory_total_pages, | 410 | 2 | }), | 411 | 2 | }; | 412 | 2 | | 413 | 2 | // Call `Core_version` if no runtime version is known yet. | 414 | 2 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 2 | } | 456 | | | 457 | | // Success! | 458 | 2 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 2 | Ok(host_vm_prototype) | 460 | 2 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype3newRRAhjd_EB9_ Line | Count | Source | 311 | 2 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 2 | let module_bytes0 = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 2 | .map_err(NewErr::BadFormat)?; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 0 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 0 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 0 | let (mut vm_proto, registered_functions) = { | 355 | 0 | let mut registered_functions = Vec::new(); | 356 | 0 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 0 | module_bytes: &module_bytes[..], | 358 | 0 | exec_hint: config.exec_hint, | 359 | 0 | // This closure is called back for each function that the runtime imports. | 360 | 0 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 0 | }, | 379 | 0 | })?; | 380 | 0 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 0 | let heap_base = vm_proto | 386 | 0 | .global_value("__heap_base") | 387 | 0 | .map_err(|_| NewErr::HeapBaseNotFound)?; | 388 | | | 389 | 0 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 0 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 0 | if vm_proto | 396 | 0 | .memory_max_pages() | 397 | 0 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 0 | } | 401 | 0 |
| 402 | 0 | let mut host_vm_prototype = HostVmPrototype { | 403 | 0 | vm_proto, | 404 | 0 | common: Box::new(VmCommon { | 405 | 0 | runtime_version, | 406 | 0 | heap_base, | 407 | 0 | registered_functions, | 408 | 0 | heap_pages: config.heap_pages, | 409 | 0 | memory_total_pages, | 410 | 0 | }), | 411 | 0 | }; | 412 | 0 |
| 413 | 0 | // Call `Core_version` if no runtime version is known yet. | 414 | 0 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 0 | } | 456 | | | 457 | | // Success! | 458 | 0 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 0 | Ok(host_vm_prototype) | 460 | 2 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype3newRRShEB9_ Line | Count | Source | 311 | 3 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 3 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 3 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 3 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 0 | Ok(Some(r)) => Some(r), | 329 | 1 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 2 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 3 | let (mut vm_proto, registered_functions) = { | 355 | 3 | let mut registered_functions = Vec::new(); | 356 | 3 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 3 | module_bytes: &module_bytes[..], | 358 | 3 | exec_hint: config.exec_hint, | 359 | 3 | // This closure is called back for each function that the runtime imports. | 360 | 3 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 3 | }, | 379 | 3 | })?0 ; | 380 | 3 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 3 | let heap_base = vm_proto | 386 | 3 | .global_value("__heap_base") | 387 | 3 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 3 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 3 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 3 | if vm_proto | 396 | 3 | .memory_max_pages() | 397 | 3 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 3 | } | 401 | 3 | | 402 | 3 | let mut host_vm_prototype = HostVmPrototype { | 403 | 3 | vm_proto, | 404 | 3 | common: Box::new(VmCommon { | 405 | 3 | runtime_version, | 406 | 3 | heap_base, | 407 | 3 | registered_functions, | 408 | 3 | heap_pages: config.heap_pages, | 409 | 3 | memory_total_pages, | 410 | 3 | }), | 411 | 3 | }; | 412 | 3 | | 413 | 3 | // Call `Core_version` if no runtime version is known yet. | 414 | 3 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 3 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 3 | "Core_version", | 417 | 3 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 3 | ) { | 419 | 3 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 10 | loop { | 424 | 10 | match vm { | 425 | 5 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 3 | HostVm::Finished(finished) => { | 427 | 3 | let version = | 428 | 3 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 3 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 3 | host_vm_prototype = finished.into_prototype(); | 436 | 3 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 3 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 2 | HostVm::GetMaxLogLevel(resume) => { | 442 | 2 | vm = resume.resume(0); // Off | 443 | 2 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 0 | } | 456 | | | 457 | | // Success! | 458 | 3 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 3 | Ok(host_vm_prototype) | 460 | 3 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype3newRShEB9_ Line | Count | Source | 311 | 2 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 2 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 2 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 2 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 2 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 2 | let (mut vm_proto, registered_functions) = { | 355 | 2 | let mut registered_functions = Vec::new(); | 356 | 2 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 2 | module_bytes: &module_bytes[..], | 358 | 2 | exec_hint: config.exec_hint, | 359 | 2 | // This closure is called back for each function that the runtime imports. | 360 | 2 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 2 | }, | 379 | 2 | })?0 ; | 380 | 2 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 2 | let heap_base = vm_proto | 386 | 2 | .global_value("__heap_base") | 387 | 2 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 2 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 2 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 2 | if vm_proto | 396 | 2 | .memory_max_pages() | 397 | 2 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 2 | } | 401 | 2 | | 402 | 2 | let mut host_vm_prototype = HostVmPrototype { | 403 | 2 | vm_proto, | 404 | 2 | common: Box::new(VmCommon { | 405 | 2 | runtime_version, | 406 | 2 | heap_base, | 407 | 2 | registered_functions, | 408 | 2 | heap_pages: config.heap_pages, | 409 | 2 | memory_total_pages, | 410 | 2 | }), | 411 | 2 | }; | 412 | 2 | | 413 | 2 | // Call `Core_version` if no runtime version is known yet. | 414 | 2 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 2 | } | 456 | | | 457 | | // Success! | 458 | 2 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 2 | Ok(host_vm_prototype) | 460 | 2 | } |
Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEECsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRRShECsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newINtCs1qmLyiTSqYF_6either6EitherRShINtNvMs5_NtNtB7_2vm11interpreterNtB1Q_11Interpreter11read_memory12AccessOffsetB1E_EEEB9_ _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEEB9_ Line | Count | Source | 311 | 21 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 21 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 21 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 21 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 21 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 21 | let (mut vm_proto, registered_functions) = { | 355 | 21 | let mut registered_functions = Vec::new(); | 356 | 21 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 21 | module_bytes: &module_bytes[..], | 358 | 21 | exec_hint: config.exec_hint, | 359 | 21 | // This closure is called back for each function that the runtime imports. | 360 | 21 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 21 | }, | 379 | 21 | })?0 ; | 380 | 21 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 21 | let heap_base = vm_proto | 386 | 21 | .global_value("__heap_base") | 387 | 21 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 21 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 21 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 21 | if vm_proto | 396 | 21 | .memory_max_pages() | 397 | 21 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 21 | } | 401 | 21 | | 402 | 21 | let mut host_vm_prototype = HostVmPrototype { | 403 | 21 | vm_proto, | 404 | 21 | common: Box::new(VmCommon { | 405 | 21 | runtime_version, | 406 | 21 | heap_base, | 407 | 21 | registered_functions, | 408 | 21 | heap_pages: config.heap_pages, | 409 | 21 | memory_total_pages, | 410 | 21 | }), | 411 | 21 | }; | 412 | 21 | | 413 | 21 | // Call `Core_version` if no runtime version is known yet. | 414 | 21 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 21 | } | 456 | | | 457 | | // Success! | 458 | 21 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 21 | Ok(host_vm_prototype) | 460 | 21 | } |
_RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRRShEB9_ Line | Count | Source | 311 | 21 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 21 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 21 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 21 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 21 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 21 | let (mut vm_proto, registered_functions) = { | 355 | 21 | let mut registered_functions = Vec::new(); | 356 | 21 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 21 | module_bytes: &module_bytes[..], | 358 | 21 | exec_hint: config.exec_hint, | 359 | 21 | // This closure is called back for each function that the runtime imports. | 360 | 21 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 21 | }, | 379 | 21 | })?0 ; | 380 | 21 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 21 | let heap_base = vm_proto | 386 | 21 | .global_value("__heap_base") | 387 | 21 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 21 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 21 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 21 | if vm_proto | 396 | 21 | .memory_max_pages() | 397 | 21 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 21 | } | 401 | 21 | | 402 | 21 | let mut host_vm_prototype = HostVmPrototype { | 403 | 21 | vm_proto, | 404 | 21 | common: Box::new(VmCommon { | 405 | 21 | runtime_version, | 406 | 21 | heap_base, | 407 | 21 | registered_functions, | 408 | 21 | heap_pages: config.heap_pages, | 409 | 21 | memory_total_pages, | 410 | 21 | }), | 411 | 21 | }; | 412 | 21 | | 413 | 21 | // Call `Core_version` if no runtime version is known yet. | 414 | 21 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 21 | } | 456 | | | 457 | | // Success! | 458 | 21 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 21 | Ok(host_vm_prototype) | 460 | 21 | } |
_RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEECsiLzmwikkc22_14json_rpc_basic Line | Count | Source | 311 | 2 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 2 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 2 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 2 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 2 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 2 | let (mut vm_proto, registered_functions) = { | 355 | 2 | let mut registered_functions = Vec::new(); | 356 | 2 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 2 | module_bytes: &module_bytes[..], | 358 | 2 | exec_hint: config.exec_hint, | 359 | 2 | // This closure is called back for each function that the runtime imports. | 360 | 2 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 2 | }, | 379 | 2 | })?0 ; | 380 | 2 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 2 | let heap_base = vm_proto | 386 | 2 | .global_value("__heap_base") | 387 | 2 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 2 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 2 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 2 | if vm_proto | 396 | 2 | .memory_max_pages() | 397 | 2 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 2 | } | 401 | 2 | | 402 | 2 | let mut host_vm_prototype = HostVmPrototype { | 403 | 2 | vm_proto, | 404 | 2 | common: Box::new(VmCommon { | 405 | 2 | runtime_version, | 406 | 2 | heap_base, | 407 | 2 | registered_functions, | 408 | 2 | heap_pages: config.heap_pages, | 409 | 2 | memory_total_pages, | 410 | 2 | }), | 411 | 2 | }; | 412 | 2 | | 413 | 2 | // Call `Core_version` if no runtime version is known yet. | 414 | 2 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 2 | } | 456 | | | 457 | | // Success! | 458 | 2 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 2 | Ok(host_vm_prototype) | 460 | 2 | } |
Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEECsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRRShECsiLzmwikkc22_14json_rpc_basic _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRShECsiLzmwikkc22_14json_rpc_basic Line | Count | Source | 311 | 2 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 2 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 2 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 2 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 2 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 2 | let (mut vm_proto, registered_functions) = { | 355 | 2 | let mut registered_functions = Vec::new(); | 356 | 2 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 2 | module_bytes: &module_bytes[..], | 358 | 2 | exec_hint: config.exec_hint, | 359 | 2 | // This closure is called back for each function that the runtime imports. | 360 | 2 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 2 | }, | 379 | 2 | })?0 ; | 380 | 2 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 2 | let heap_base = vm_proto | 386 | 2 | .global_value("__heap_base") | 387 | 2 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 2 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 2 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 2 | if vm_proto | 396 | 2 | .memory_max_pages() | 397 | 2 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 2 | } | 401 | 2 | | 402 | 2 | let mut host_vm_prototype = HostVmPrototype { | 403 | 2 | vm_proto, | 404 | 2 | common: Box::new(VmCommon { | 405 | 2 | runtime_version, | 406 | 2 | heap_base, | 407 | 2 | registered_functions, | 408 | 2 | heap_pages: config.heap_pages, | 409 | 2 | memory_total_pages, | 410 | 2 | }), | 411 | 2 | }; | 412 | 2 | | 413 | 2 | // Call `Core_version` if no runtime version is known yet. | 414 | 2 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 2 | } | 456 | | | 457 | | // Success! | 458 | 2 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 2 | Ok(host_vm_prototype) | 460 | 2 | } |
_RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc3vec3VechEECsiUjFBJteJ7x_17smoldot_full_node Line | Count | Source | 311 | 2 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 2 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 2 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 2 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 2 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 2 | let (mut vm_proto, registered_functions) = { | 355 | 2 | let mut registered_functions = Vec::new(); | 356 | 2 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 2 | module_bytes: &module_bytes[..], | 358 | 2 | exec_hint: config.exec_hint, | 359 | 2 | // This closure is called back for each function that the runtime imports. | 360 | 2 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 2 | }, | 379 | 2 | })?0 ; | 380 | 2 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 2 | let heap_base = vm_proto | 386 | 2 | .global_value("__heap_base") | 387 | 2 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 2 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 2 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 2 | if vm_proto | 396 | 2 | .memory_max_pages() | 397 | 2 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 2 | } | 401 | 2 | | 402 | 2 | let mut host_vm_prototype = HostVmPrototype { | 403 | 2 | vm_proto, | 404 | 2 | common: Box::new(VmCommon { | 405 | 2 | runtime_version, | 406 | 2 | heap_base, | 407 | 2 | registered_functions, | 408 | 2 | heap_pages: config.heap_pages, | 409 | 2 | memory_total_pages, | 410 | 2 | }), | 411 | 2 | }; | 412 | 2 | | 413 | 2 | // Call `Core_version` if no runtime version is known yet. | 414 | 2 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 2 | } | 456 | | | 457 | | // Success! | 458 | 2 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 2 | Ok(host_vm_prototype) | 460 | 2 | } |
Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRRShECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRShECscDgN54JpMGG_6author _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newINtNtCsdZExvAaxgia_5alloc3vec3VechEECsibGXYHQB8Ea_25json_rpc_general_requests Line | Count | Source | 311 | 19 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 19 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 19 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 19 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 19 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 19 | let (mut vm_proto, registered_functions) = { | 355 | 19 | let mut registered_functions = Vec::new(); | 356 | 19 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 19 | module_bytes: &module_bytes[..], | 358 | 19 | exec_hint: config.exec_hint, | 359 | 19 | // This closure is called back for each function that the runtime imports. | 360 | 19 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 19 | }, | 379 | 19 | })?0 ; | 380 | 19 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 19 | let heap_base = vm_proto | 386 | 19 | .global_value("__heap_base") | 387 | 19 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 19 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 19 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 19 | if vm_proto | 396 | 19 | .memory_max_pages() | 397 | 19 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 19 | } | 401 | 19 | | 402 | 19 | let mut host_vm_prototype = HostVmPrototype { | 403 | 19 | vm_proto, | 404 | 19 | common: Box::new(VmCommon { | 405 | 19 | runtime_version, | 406 | 19 | heap_base, | 407 | 19 | registered_functions, | 408 | 19 | heap_pages: config.heap_pages, | 409 | 19 | memory_total_pages, | 410 | 19 | }), | 411 | 19 | }; | 412 | 19 | | 413 | 19 | // Call `Core_version` if no runtime version is known yet. | 414 | 19 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 19 | } | 456 | | | 457 | | // Success! | 458 | 19 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 19 | Ok(host_vm_prototype) | 460 | 19 | } |
Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRINtNtCsdZExvAaxgia_5alloc6borrow3CowShEECsibGXYHQB8Ea_25json_rpc_general_requests Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRRShECsibGXYHQB8Ea_25json_rpc_general_requests _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype3newRShECsibGXYHQB8Ea_25json_rpc_general_requests Line | Count | Source | 311 | 19 | pub fn new(config: Config<impl AsRef<[u8]>>) -> Result<Self, NewErr> { | 312 | | // The maximum allowed size for the decompressed Wasm code needs to be the same amongst | 313 | | // all implementations. | 314 | | // See <https://github.com/paritytech/substrate/blob/f9d10fabe04d598d68f8b097cc4905adbb1ad630/primitives/maybe-compressed-blob/src/lib.rs#L37>. | 315 | | // Hopefully, this value doesn't get changed without the Substrate team informing everyone. | 316 | 19 | let module_bytes = zstd::zstd_decode_if_necessary(config.module.as_ref(), 50 * 1024 * 1024) | 317 | 19 | .map_err(NewErr::BadFormat)?0 ; | 318 | | | 319 | | // Try to find the runtime version as Wasm custom sections. | 320 | | // An error is returned if the sections have a wrong format, in which case we fail the | 321 | | // initialization. `Ok(None)` can also be returned, in which case the sections are | 322 | | // missing, and we will instead try to retrieve the version through a runtime call later | 323 | | // down this function. | 324 | | // In the case of `CustomSectionsPresenceMismatch`, indicating that one section is present | 325 | | // but not the other, we must ignore the custom sections. This is necessary due to some | 326 | | // historical accidents. | 327 | 19 | let runtime_version = match runtime_version::find_embedded_runtime_version(&module_bytes) { | 328 | 19 | Ok(Some(r)) => Some(r), | 329 | 0 | Ok(None) => None, | 330 | | Err( | 331 | | runtime_version::FindEmbeddedRuntimeVersionError::CustomSectionsPresenceMismatch, | 332 | 0 | ) => None, | 333 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::FindSections(err)) => { | 334 | 0 | return Err(NewErr::RuntimeVersion( | 335 | 0 | FindEmbeddedRuntimeVersionError::FindSections(err), | 336 | 0 | )) | 337 | | } | 338 | 0 | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err)) => { | 339 | 0 | return Err(NewErr::RuntimeVersion( | 340 | 0 | FindEmbeddedRuntimeVersionError::RuntimeApisDecode(err), | 341 | 0 | )) | 342 | | } | 343 | | Err(runtime_version::FindEmbeddedRuntimeVersionError::RuntimeVersionDecode) => { | 344 | 0 | return Err(NewErr::RuntimeVersion( | 345 | 0 | FindEmbeddedRuntimeVersionError::RuntimeVersionDecode, | 346 | 0 | )) | 347 | | } | 348 | | }; | 349 | | | 350 | | // Initialize the virtual machine. | 351 | | // Each symbol requested by the Wasm runtime will be put in `registered_functions`. Later, | 352 | | // when a function is invoked, the Wasm virtual machine will pass indices within that | 353 | | // array. | 354 | 19 | let (mut vm_proto, registered_functions) = { | 355 | 19 | let mut registered_functions = Vec::new(); | 356 | 19 | let vm_proto = vm::VirtualMachinePrototype::new(vm::Config { | 357 | 19 | module_bytes: &module_bytes[..], | 358 | 19 | exec_hint: config.exec_hint, | 359 | 19 | // This closure is called back for each function that the runtime imports. | 360 | 19 | symbols: &mut |mod_name, f_name, signature| { | 361 | | if mod_name != "env" { | 362 | | return Err(()); | 363 | | } | 364 | | | 365 | | let id = registered_functions.len(); | 366 | | registered_functions.push(match HostFunction::by_name(f_name) { | 367 | | Some(f) if f.signature() == *signature => FunctionImport::Resolved(f), | 368 | | Some(_) | None if !config.allow_unresolved_imports => { | 369 | | // TODO: return a better error if there is a signature mismatch | 370 | | return Err(()); | 371 | | } | 372 | | Some(_) | None => FunctionImport::Unresolved { | 373 | | name: f_name.to_owned(), | 374 | | module: mod_name.to_owned(), | 375 | | }, | 376 | | }); | 377 | | Ok(id) | 378 | 19 | }, | 379 | 19 | })?0 ; | 380 | 19 | (vm_proto, registered_functions.into()) | 381 | | }; | 382 | | | 383 | | // In the runtime environment, Wasm blobs must export a global symbol named | 384 | | // `__heap_base` indicating where the memory allocator is allowed to allocate memory. | 385 | 19 | let heap_base = vm_proto | 386 | 19 | .global_value("__heap_base") | 387 | 19 | .map_err(|_| NewErr::HeapBaseNotFound)?0 ; | 388 | | | 389 | 19 | let memory_total_pages = if heap_base == 0 { | 390 | 0 | config.heap_pages | 391 | | } else { | 392 | 19 | HeapPages::new((heap_base - 1) / (64 * 1024)) + config.heap_pages + HeapPages::new(1) | 393 | | }; | 394 | | | 395 | 19 | if vm_proto | 396 | 19 | .memory_max_pages() | 397 | 19 | .map_or(false, |max| max < memory_total_pages) | 398 | | { | 399 | 0 | return Err(NewErr::MemoryMaxSizeTooLow); | 400 | 19 | } | 401 | 19 | | 402 | 19 | let mut host_vm_prototype = HostVmPrototype { | 403 | 19 | vm_proto, | 404 | 19 | common: Box::new(VmCommon { | 405 | 19 | runtime_version, | 406 | 19 | heap_base, | 407 | 19 | registered_functions, | 408 | 19 | heap_pages: config.heap_pages, | 409 | 19 | memory_total_pages, | 410 | 19 | }), | 411 | 19 | }; | 412 | 19 | | 413 | 19 | // Call `Core_version` if no runtime version is known yet. | 414 | 19 | if host_vm_prototype.common.runtime_version.is_none() { | 415 | 0 | let mut vm: HostVm = match host_vm_prototype.run_no_param( | 416 | 0 | "Core_version", | 417 | 0 | StorageProofSizeBehavior::proof_recording_disabled(), | 418 | 0 | ) { | 419 | 0 | Ok(vm) => vm.into(), | 420 | 0 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))), | 421 | | }; | 422 | | | 423 | 0 | loop { | 424 | 0 | match vm { | 425 | 0 | HostVm::ReadyToRun(r) => vm = r.run(), | 426 | 0 | HostVm::Finished(finished) => { | 427 | 0 | let version = | 428 | 0 | match CoreVersion::from_slice(finished.value().as_ref().to_vec()) { | 429 | 0 | Ok(v) => v, | 430 | | Err(_) => { | 431 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Decode)) | 432 | | } | 433 | | }; | 434 | | | 435 | 0 | host_vm_prototype = finished.into_prototype(); | 436 | 0 | host_vm_prototype.common.runtime_version = Some(version); | 437 | 0 | break; | 438 | | } | 439 | | | 440 | | // Emitted log lines are ignored. | 441 | 0 | HostVm::GetMaxLogLevel(resume) => { | 442 | 0 | vm = resume.resume(0); // Off | 443 | 0 | } | 444 | 0 | HostVm::LogEmit(log) => vm = log.resume(), | 445 | | | 446 | 0 | HostVm::Error { error, .. } => { | 447 | 0 | return Err(NewErr::CoreVersion(CoreVersionError::Run(error))) | 448 | | } | 449 | | | 450 | | // Getting the runtime version is a very core operation, and very few | 451 | | // external calls are allowed. | 452 | 0 | _ => return Err(NewErr::CoreVersion(CoreVersionError::ForbiddenHostFunction)), | 453 | | } | 454 | | } | 455 | 19 | } | 456 | | | 457 | | // Success! | 458 | 19 | debug_assert!(host_vm_prototype.common.runtime_version.is_some()); | 459 | 19 | Ok(host_vm_prototype) | 460 | 19 | } |
|
461 | | |
462 | | /// Returns the number of heap pages that were passed to [`HostVmPrototype::new`]. |
463 | 0 | pub fn heap_pages(&self) -> HeapPages { |
464 | 0 | self.common.heap_pages |
465 | 0 | } Unexecuted instantiation: _RNvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB4_15HostVmPrototype10heap_pages Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB4_15HostVmPrototype10heap_pages |
466 | | |
467 | | /// Returns the runtime version found in the module. |
468 | 229 | pub fn runtime_version(&self) -> &CoreVersion { |
469 | 229 | self.common |
470 | 229 | .runtime_version |
471 | 229 | .as_ref() |
472 | 229 | .unwrap_or_else(|| unreachable!()0 ) Unexecuted instantiation: _RNCNvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_15HostVmPrototype15runtime_version0Ba_ Unexecuted instantiation: _RNCNvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_15HostVmPrototype15runtime_version0Ba_ |
473 | 229 | } _RNvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB4_15HostVmPrototype15runtime_version Line | Count | Source | 468 | 17 | pub fn runtime_version(&self) -> &CoreVersion { | 469 | 17 | self.common | 470 | 17 | .runtime_version | 471 | 17 | .as_ref() | 472 | 17 | .unwrap_or_else(|| unreachable!()) | 473 | 17 | } |
_RNvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB4_15HostVmPrototype15runtime_version Line | Count | Source | 468 | 212 | pub fn runtime_version(&self) -> &CoreVersion { | 469 | 212 | self.common | 470 | 212 | .runtime_version | 471 | 212 | .as_ref() | 472 | 212 | .unwrap_or_else(|| unreachable!()) | 473 | 212 | } |
|
474 | | |
475 | | /// Starts the VM, calling the function passed as parameter. |
476 | | /// |
477 | | /// See the documentation of [`StorageProofSizeBehavior`] for an explanation of |
478 | | /// the `storage_proof_size_behavior` parameter. |
479 | 30 | pub fn run( |
480 | 30 | self, |
481 | 30 | function_to_call: &str, |
482 | 30 | storage_proof_size_behavior: StorageProofSizeBehavior, |
483 | 30 | data: &[u8], |
484 | 30 | ) -> Result<ReadyToRun, (StartErr, Self)> { |
485 | 30 | self.run_vectored( |
486 | 30 | function_to_call, |
487 | 30 | storage_proof_size_behavior, |
488 | 30 | iter::once(data), |
489 | 30 | ) |
490 | 30 | } _RNvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB4_15HostVmPrototype3run Line | Count | Source | 479 | 30 | pub fn run( | 480 | 30 | self, | 481 | 30 | function_to_call: &str, | 482 | 30 | storage_proof_size_behavior: StorageProofSizeBehavior, | 483 | 30 | data: &[u8], | 484 | 30 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 485 | 30 | self.run_vectored( | 486 | 30 | function_to_call, | 487 | 30 | storage_proof_size_behavior, | 488 | 30 | iter::once(data), | 489 | 30 | ) | 490 | 30 | } |
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB4_15HostVmPrototype3run |
491 | | |
492 | | /// Same as [`HostVmPrototype::run`], except that the function doesn't need any parameter. |
493 | | /// |
494 | | /// See the documentation of [`StorageProofSizeBehavior`] for an explanation of |
495 | | /// the `storage_proof_size_behavior` parameter. |
496 | 9 | pub fn run_no_param( |
497 | 9 | self, |
498 | 9 | function_to_call: &str, |
499 | 9 | storage_proof_size_behavior: StorageProofSizeBehavior, |
500 | 9 | ) -> Result<ReadyToRun, (StartErr, Self)> { |
501 | 9 | self.run_vectored( |
502 | 9 | function_to_call, |
503 | 9 | storage_proof_size_behavior, |
504 | 9 | iter::empty::<Vec<u8>>(), |
505 | 9 | ) |
506 | 9 | } _RNvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB4_15HostVmPrototype12run_no_param Line | Count | Source | 496 | 9 | pub fn run_no_param( | 497 | 9 | self, | 498 | 9 | function_to_call: &str, | 499 | 9 | storage_proof_size_behavior: StorageProofSizeBehavior, | 500 | 9 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 501 | 9 | self.run_vectored( | 502 | 9 | function_to_call, | 503 | 9 | storage_proof_size_behavior, | 504 | 9 | iter::empty::<Vec<u8>>(), | 505 | 9 | ) | 506 | 9 | } |
Unexecuted instantiation: _RNvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB4_15HostVmPrototype12run_no_param |
507 | | |
508 | | /// Same as [`HostVmPrototype::run`], except that the function parameter can be passed as |
509 | | /// a list of buffers. All the buffers will be concatenated in memory. |
510 | | /// |
511 | | /// See the documentation of [`StorageProofSizeBehavior`] for an explanation of |
512 | | /// the `storage_proof_size_behavior` parameter. |
513 | 179 | pub fn run_vectored( |
514 | 179 | mut self, |
515 | 179 | function_to_call: &str, |
516 | 179 | storage_proof_size_behavior: StorageProofSizeBehavior, |
517 | 179 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, |
518 | 179 | ) -> Result<ReadyToRun, (StartErr, Self)> { |
519 | 179 | // Determine the total length of `data`. |
520 | 179 | let mut data_len_u32: u32 = 0; |
521 | 179 | for data66 in data.clone() { |
522 | 66 | let len = match u32::try_from(data.as_ref().len()) { |
523 | 66 | Ok(v) => v, |
524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), |
525 | | }; |
526 | 66 | data_len_u32 = match data_len_u32.checked_add(len) { |
527 | 66 | Some(v) => v, |
528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), |
529 | | }; |
530 | | } |
531 | | |
532 | | // Initialize the state of the memory allocator. This is the allocator that is used in |
533 | | // order to allocate space for the input data, and also later used when the Wasm code |
534 | | // requests variable-length data. |
535 | 179 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); |
536 | 179 | |
537 | 179 | // Prepare the virtual machine for execution. |
538 | 179 | let mut vm = self.vm_proto.prepare(); |
539 | | |
540 | | // Write the input data in the VM's memory using the allocator. |
541 | 179 | let data_ptr = match allocator.allocate( |
542 | 179 | &mut MemAccess { |
543 | 179 | vm: MemAccessVm::Prepare(&mut vm), |
544 | 179 | memory_total_pages: self.common.memory_total_pages, |
545 | 179 | }, |
546 | 179 | data_len_u32, |
547 | 179 | ) { |
548 | 179 | Ok(p) => p, |
549 | | Err(_) => { |
550 | 0 | self.vm_proto = vm.into_prototype(); |
551 | 0 | return Err((StartErr::DataSizeOverflow, self)); |
552 | | } |
553 | | }; |
554 | | |
555 | | // While the allocator has reserved memory, it might have reserved more memory than its |
556 | | // current size. |
557 | 179 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) |
558 | 179 | .checked_sub(u32::from(vm.memory_size())) |
559 | 179 | { |
560 | 179 | // If the memory can't be grown, it indicates a bug in the allocator. |
561 | 179 | vm.grow_memory(HeapPages::from(to_grow)) |
562 | 179 | .unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherIB1l_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIB1l_B1X_IB1l_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1U_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3N_3map3MapIB3J_IB3J_IB3J_INtNtNtB3P_7sources4once4OnceB1P_EB56_EB56_EB56_ENcNtB1k_4Left0EIB4B_IB3J_IB57_B2O_EINtNtB3N_7flatten7FlatMapNtNtBb_6header8LogsIterIB4B_INtNtNtB3R_5array4iter8IntoIterB2X_Kj2_ENcNtB2O_5Right0ENCNvMs2_B6T_NtB6T_9DigestRef14scale_encoding0EENcNtB1k_5Right0EEE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIB1l_Ahj8_IB1l_B1P_B2K_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3a_3map3MapINtNtNtB3c_7sources4once4OnceB1P_ENcNtB1k_4Left0EIB3Y_INtNtB3a_7flatten7FlatMapINtNtNtB3e_5array4iter8IntoIterTB2K_B2K_EKj1_EIB36_IB3Y_IB4f_B2K_ENcNtB2F_4Left0EIB3Y_IB36_IB3Y_B4e_NcNtB2P_4Left0EIB3Y_B6p_NcNtB2P_5Right0EENcNtB2F_5Right0EENCINvMs_NtNtBb_6author7runtimeNtB8b_18InherentExtrinsics25inject_raw_inherents_listB2K_B5v_E0ENcNtB1k_5Right0EEE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherRAhj1_IB1l_RShRINtNtCsdZExvAaxgia_5alloc3vec3VechEEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB2G_INtNtB2K_3map3MapINtNtNtB2M_7sources4once4OnceB1P_ENcNtB1k_4Left0EIB3D_IB3D_IB3U_B23_ENcNtB1V_5Right0ENcNtB1k_5Right0EEIB3D_IB3D_IB3U_B20_ENcNtB1V_4Left0EB5g_EEE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherRINtNtCsdZExvAaxgia_5alloc3vec3VechEIB1l_B1P_INtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB3r_INtNtNtB3x_7sources4once4OnceB1k_EB4n_EINtNtB3v_3map3MapINtNtNtB3z_5slice4iter4IterNtNtNtB9_12runtime_call5tests9HexStringENCNvB5K_s_14execute_blockss0_0EEE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1k_EE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1k_EE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1k_Kj2_EE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1k_EE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1k_EE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EE0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherIB1m_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIB1m_B1Y_IB1m_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1V_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3O_3map3MapIB3K_IB3K_IB3K_INtNtNtB3Q_7sources4once4OnceB1Q_EB57_EB57_EB57_ENcNtB1l_4Left0EIB4C_IB3K_IB58_B2P_EINtNtB3O_7flatten7FlatMapNtNtBb_6header8LogsIterIB4C_INtNtNtB3S_5array4iter8IntoIterB2Y_Kj2_ENcNtB2P_5Right0ENCNvMs2_B6U_NtB6U_9DigestRef14scale_encoding0EENcNtB1l_5Right0EEE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIB1m_Ahj8_IB1m_B1Q_B2L_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3b_3map3MapINtNtNtB3d_7sources4once4OnceB1Q_ENcNtB1l_4Left0EIB3Z_INtNtB3b_7flatten7FlatMapINtNtNtB3f_5array4iter8IntoIterTB2L_B2L_EKj1_EIB37_IB3Z_IB4g_B2L_ENcNtB2G_4Left0EIB3Z_IB37_IB3Z_B4f_NcNtB2Q_4Left0EIB3Z_B6q_NcNtB2Q_5Right0EENcNtB2G_5Right0EENCINvMs_NtNtBb_6author7runtimeNtB8c_18InherentExtrinsics25inject_raw_inherents_listB2L_B5w_E0ENcNtB1l_5Right0EEE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EE0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EE0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EE0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EE0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EE0CsibGXYHQB8Ea_25json_rpc_general_requests |
563 | 179 | }0 |
564 | | |
565 | | // Writing the input data into the VM. |
566 | 179 | let mut data_ptr_iter = data_ptr; |
567 | 245 | for data66 in data { |
568 | 66 | let data = data.as_ref(); |
569 | 66 | vm.write_memory(data_ptr_iter, data) |
570 | 66 | .unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherIB1l_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIB1l_B1X_IB1l_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1U_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3N_3map3MapIB3J_IB3J_IB3J_INtNtNtB3P_7sources4once4OnceB1P_EB56_EB56_EB56_ENcNtB1k_4Left0EIB4B_IB3J_IB57_B2O_EINtNtB3N_7flatten7FlatMapNtNtBb_6header8LogsIterIB4B_INtNtNtB3R_5array4iter8IntoIterB2X_Kj2_ENcNtB2O_5Right0ENCNvMs2_B6T_NtB6T_9DigestRef14scale_encoding0EENcNtB1k_5Right0EEEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIB1l_Ahj8_IB1l_B1P_B2K_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3a_3map3MapINtNtNtB3c_7sources4once4OnceB1P_ENcNtB1k_4Left0EIB3Y_INtNtB3a_7flatten7FlatMapINtNtNtB3e_5array4iter8IntoIterTB2K_B2K_EKj1_EIB36_IB3Y_IB4f_B2K_ENcNtB2F_4Left0EIB3Y_IB36_IB3Y_B4e_NcNtB2P_4Left0EIB3Y_B6p_NcNtB2P_5Right0EENcNtB2F_5Right0EENCINvMs_NtNtBb_6author7runtimeNtB8b_18InherentExtrinsics25inject_raw_inherents_listB2K_B5v_E0ENcNtB1k_5Right0EEEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherRAhj1_IB1l_RShRINtNtCsdZExvAaxgia_5alloc3vec3VechEEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB2G_INtNtB2K_3map3MapINtNtNtB2M_7sources4once4OnceB1P_ENcNtB1k_4Left0EIB3D_IB3D_IB3U_B23_ENcNtB1V_5Right0ENcNtB1k_5Right0EEIB3D_IB3D_IB3U_B20_ENcNtB1V_4Left0EB5g_EEEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherRINtNtCsdZExvAaxgia_5alloc3vec3VechEIB1l_B1P_INtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB3r_INtNtNtB3x_7sources4once4OnceB1k_EB4n_EINtNtB3v_3map3MapINtNtNtB3z_5slice4iter4IterNtNtNtB9_12runtime_call5tests9HexStringENCNvB5K_s_14execute_blockss0_0EEEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1k_EEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1k_EEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1k_Kj2_EEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1k_EEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1k_EEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherIB1m_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIB1m_B1Y_IB1m_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1V_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3O_3map3MapIB3K_IB3K_IB3K_INtNtNtB3Q_7sources4once4OnceB1Q_EB57_EB57_EB57_ENcNtB1l_4Left0EIB4C_IB3K_IB58_B2P_EINtNtB3O_7flatten7FlatMapNtNtBb_6header8LogsIterIB4C_INtNtNtB3S_5array4iter8IntoIterB2Y_Kj2_ENcNtB2P_5Right0ENCNvMs2_B6U_NtB6U_9DigestRef14scale_encoding0EENcNtB1l_5Right0EEEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIB1m_Ahj8_IB1m_B1Q_B2L_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3b_3map3MapINtNtNtB3d_7sources4once4OnceB1Q_ENcNtB1l_4Left0EIB3Z_INtNtB3b_7flatten7FlatMapINtNtNtB3f_5array4iter8IntoIterTB2L_B2L_EKj1_EIB37_IB3Z_IB4g_B2L_ENcNtB2G_4Left0EIB3Z_IB37_IB3Z_B4f_NcNtB2Q_4Left0EIB3Z_B6q_NcNtB2Q_5Right0EENcNtB2G_5Right0EENCINvMs_NtNtBb_6author7runtimeNtB8c_18InherentExtrinsics25inject_raw_inherents_listB2L_B5w_E0ENcNtB1l_5Right0EEEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EEs_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EEs_0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs_0CsibGXYHQB8Ea_25json_rpc_general_requests |
571 | 66 | data_ptr_iter = data_ptr_iter |
572 | 66 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!()0 )) Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherIB1l_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIB1l_B1X_IB1l_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1U_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3N_3map3MapIB3J_IB3J_IB3J_INtNtNtB3P_7sources4once4OnceB1P_EB56_EB56_EB56_ENcNtB1k_4Left0EIB4B_IB3J_IB57_B2O_EINtNtB3N_7flatten7FlatMapNtNtBb_6header8LogsIterIB4B_INtNtNtB3R_5array4iter8IntoIterB2X_Kj2_ENcNtB2O_5Right0ENCNvMs2_B6T_NtB6T_9DigestRef14scale_encoding0EENcNtB1k_5Right0EEEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIB1l_Ahj8_IB1l_B1P_B2K_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3a_3map3MapINtNtNtB3c_7sources4once4OnceB1P_ENcNtB1k_4Left0EIB3Y_INtNtB3a_7flatten7FlatMapINtNtNtB3e_5array4iter8IntoIterTB2K_B2K_EKj1_EIB36_IB3Y_IB4f_B2K_ENcNtB2F_4Left0EIB3Y_IB36_IB3Y_B4e_NcNtB2P_4Left0EIB3Y_B6p_NcNtB2P_5Right0EENcNtB2F_5Right0EENCINvMs_NtNtBb_6author7runtimeNtB8b_18InherentExtrinsics25inject_raw_inherents_listB2K_B5v_E0ENcNtB1k_5Right0EEEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherRAhj1_IB1l_RShRINtNtCsdZExvAaxgia_5alloc3vec3VechEEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB2G_INtNtB2K_3map3MapINtNtNtB2M_7sources4once4OnceB1P_ENcNtB1k_4Left0EIB3D_IB3D_IB3U_B23_ENcNtB1V_5Right0ENcNtB1k_5Right0EEIB3D_IB3D_IB3U_B20_ENcNtB1V_4Left0EB5g_EEEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherRINtNtCsdZExvAaxgia_5alloc3vec3VechEIB1l_B1P_INtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB3r_INtNtNtB3x_7sources4once4OnceB1k_EB4n_EINtNtB3v_3map3MapINtNtNtB3z_5slice4iter4IterNtNtNtB9_12runtime_call5tests9HexStringENCNvB5K_s_14execute_blockss0_0EEEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1k_EEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1k_EEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1k_Kj2_EEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1k_EEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1k_EEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs0_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherIB1m_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIB1m_B1Y_IB1m_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1V_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3O_3map3MapIB3K_IB3K_IB3K_INtNtNtB3Q_7sources4once4OnceB1Q_EB57_EB57_EB57_ENcNtB1l_4Left0EIB4C_IB3K_IB58_B2P_EINtNtB3O_7flatten7FlatMapNtNtBb_6header8LogsIterIB4C_INtNtNtB3S_5array4iter8IntoIterB2Y_Kj2_ENcNtB2P_5Right0ENCNvMs2_B6U_NtB6U_9DigestRef14scale_encoding0EENcNtB1l_5Right0EEEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIB1m_Ahj8_IB1m_B1Q_B2L_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3b_3map3MapINtNtNtB3d_7sources4once4OnceB1Q_ENcNtB1l_4Left0EIB3Z_INtNtB3b_7flatten7FlatMapINtNtNtB3f_5array4iter8IntoIterTB2L_B2L_EKj1_EIB37_IB3Z_IB4g_B2L_ENcNtB2G_4Left0EIB3Z_IB37_IB3Z_B4f_NcNtB2Q_4Left0EIB3Z_B6q_NcNtB2Q_5Right0EENcNtB2G_5Right0EENCINvMs_NtNtBb_6author7runtimeNtB8c_18InherentExtrinsics25inject_raw_inherents_listB2L_B5w_E0ENcNtB1l_5Right0EEEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EEs0_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs0_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EEs0_0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs0_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs0_0CsibGXYHQB8Ea_25json_rpc_general_requests |
573 | 66 | .unwrap_or_else(|| unreachable!()0 ); Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherIB1l_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIB1l_B1X_IB1l_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1U_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3N_3map3MapIB3J_IB3J_IB3J_INtNtNtB3P_7sources4once4OnceB1P_EB56_EB56_EB56_ENcNtB1k_4Left0EIB4B_IB3J_IB57_B2O_EINtNtB3N_7flatten7FlatMapNtNtBb_6header8LogsIterIB4B_INtNtNtB3R_5array4iter8IntoIterB2X_Kj2_ENcNtB2O_5Right0ENCNvMs2_B6T_NtB6T_9DigestRef14scale_encoding0EENcNtB1k_5Right0EEEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIB1l_Ahj8_IB1l_B1P_B2K_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3a_3map3MapINtNtNtB3c_7sources4once4OnceB1P_ENcNtB1k_4Left0EIB3Y_INtNtB3a_7flatten7FlatMapINtNtNtB3e_5array4iter8IntoIterTB2K_B2K_EKj1_EIB36_IB3Y_IB4f_B2K_ENcNtB2F_4Left0EIB3Y_IB36_IB3Y_B4e_NcNtB2P_4Left0EIB3Y_B6p_NcNtB2P_5Right0EENcNtB2F_5Right0EENCINvMs_NtNtBb_6author7runtimeNtB8b_18InherentExtrinsics25inject_raw_inherents_listB2K_B5v_E0ENcNtB1k_5Right0EEEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherRAhj1_IB1l_RShRINtNtCsdZExvAaxgia_5alloc3vec3VechEEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB2G_INtNtB2K_3map3MapINtNtNtB2M_7sources4once4OnceB1P_ENcNtB1k_4Left0EIB3D_IB3D_IB3U_B23_ENcNtB1V_5Right0ENcNtB1k_5Right0EEIB3D_IB3D_IB3U_B20_ENcNtB1V_4Left0EB5g_EEEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherRINtNtCsdZExvAaxgia_5alloc3vec3VechEIB1l_B1P_INtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB3r_INtNtNtB3x_7sources4once4OnceB1k_EB4n_EINtNtB3v_3map3MapINtNtNtB3z_5slice4iter4IterNtNtNtB9_12runtime_call5tests9HexStringENCNvB5K_s_14execute_blockss0_0EEEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1k_EEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1k_EEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1k_Kj2_EEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1k_EEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1k_EEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs1_0CsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherIB1m_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIB1m_B1Y_IB1m_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1V_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3O_3map3MapIB3K_IB3K_IB3K_INtNtNtB3Q_7sources4once4OnceB1Q_EB57_EB57_EB57_ENcNtB1l_4Left0EIB4C_IB3K_IB58_B2P_EINtNtB3O_7flatten7FlatMapNtNtBb_6header8LogsIterIB4C_INtNtNtB3S_5array4iter8IntoIterB2Y_Kj2_ENcNtB2P_5Right0ENCNvMs2_B6U_NtB6U_9DigestRef14scale_encoding0EENcNtB1l_5Right0EEEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIB1m_Ahj8_IB1m_B1Q_B2L_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3b_3map3MapINtNtNtB3d_7sources4once4OnceB1Q_ENcNtB1l_4Left0EIB3Z_INtNtB3b_7flatten7FlatMapINtNtNtB3f_5array4iter8IntoIterTB2L_B2L_EKj1_EIB37_IB3Z_IB4g_B2L_ENcNtB2G_4Left0EIB3Z_IB37_IB3Z_B4f_NcNtB2Q_4Left0EIB3Z_B6q_NcNtB2Q_5Right0EENcNtB2G_5Right0EENCINvMs_NtNtBb_6author7runtimeNtB8c_18InherentExtrinsics25inject_raw_inherents_listB2L_B5w_E0ENcNtB1l_5Right0EEEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EEs1_0Bb_ Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs1_0CsiLzmwikkc22_14json_rpc_basic Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1l_EEs1_0CsiUjFBJteJ7x_17smoldot_full_node Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs1_0CscDgN54JpMGG_6author Unexecuted instantiation: _RNCINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1l_EEs1_0CsibGXYHQB8Ea_25json_rpc_general_requests |
574 | 66 | } |
575 | | |
576 | | // Now start executing the function. We pass as parameter the location and size of the |
577 | | // input data. |
578 | 179 | let vm175 = match vm.start( |
579 | 179 | function_to_call, |
580 | 179 | &[ |
581 | 179 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), |
582 | 179 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), |
583 | 179 | ], |
584 | 179 | ) { |
585 | 175 | Ok(vm) => vm, |
586 | 4 | Err((error, vm_proto)) => { |
587 | 4 | self.vm_proto = vm_proto; |
588 | 4 | return Err((error.into(), self)); |
589 | | } |
590 | | }; |
591 | | |
592 | 175 | Ok(ReadyToRun { |
593 | 175 | resume_value: None, |
594 | 175 | inner: Box::new(Inner { |
595 | 175 | common: self.common, |
596 | 175 | vm, |
597 | 175 | storage_transaction_depth: 0, |
598 | 175 | signatures_batch_verification: None, |
599 | 175 | allocator, |
600 | 175 | storage_proof_size_behavior, |
601 | 175 | }), |
602 | 175 | }) |
603 | 179 | } _RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherIB1j_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIB1j_B1V_IB1j_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1S_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3L_3map3MapIB3H_IB3H_IB3H_INtNtNtB3N_7sources4once4OnceB1N_EB54_EB54_EB54_ENcNtB1i_4Left0EIB4z_IB3H_IB55_B2M_EINtNtB3L_7flatten7FlatMapNtNtB9_6header8LogsIterIB4z_INtNtNtB3P_5array4iter8IntoIterB2V_Kj2_ENcNtB2M_5Right0ENCNvMs2_B6R_NtB6R_9DigestRef14scale_encoding0EENcNtB1i_5Right0EEEB9_ Line | Count | Source | 513 | 1 | pub fn run_vectored( | 514 | 1 | mut self, | 515 | 1 | function_to_call: &str, | 516 | 1 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 1 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 1 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 1 | // Determine the total length of `data`. | 520 | 1 | let mut data_len_u32: u32 = 0; | 521 | 7 | for data in data.clone()1 { | 522 | 7 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 7 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 7 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 7 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 1 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 1 | | 537 | 1 | // Prepare the virtual machine for execution. | 538 | 1 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 1 | let data_ptr = match allocator.allocate( | 542 | 1 | &mut MemAccess { | 543 | 1 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 1 | memory_total_pages: self.common.memory_total_pages, | 545 | 1 | }, | 546 | 1 | data_len_u32, | 547 | 1 | ) { | 548 | 1 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 1 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 1 | .checked_sub(u32::from(vm.memory_size())) | 559 | 1 | { | 560 | 1 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 1 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 1 | .unwrap_or_else(|_| unreachable!()); | 563 | 1 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 1 | let mut data_ptr_iter = data_ptr; | 567 | 8 | for data7 in data { | 568 | 7 | let data = data.as_ref(); | 569 | 7 | vm.write_memory(data_ptr_iter, data) | 570 | 7 | .unwrap_or_else(|_| unreachable!()); | 571 | 7 | data_ptr_iter = data_ptr_iter | 572 | 7 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 7 | .unwrap_or_else(|| unreachable!()); | 574 | 7 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 1 | let vm = match vm.start( | 579 | 1 | function_to_call, | 580 | 1 | &[ | 581 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 1 | ], | 584 | 1 | ) { | 585 | 1 | Ok(vm) => vm, | 586 | 0 | Err((error, vm_proto)) => { | 587 | 0 | self.vm_proto = vm_proto; | 588 | 0 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 1 | Ok(ReadyToRun { | 593 | 1 | resume_value: None, | 594 | 1 | inner: Box::new(Inner { | 595 | 1 | common: self.common, | 596 | 1 | vm, | 597 | 1 | storage_transaction_depth: 0, | 598 | 1 | signatures_batch_verification: None, | 599 | 1 | allocator, | 600 | 1 | storage_proof_size_behavior, | 601 | 1 | }), | 602 | 1 | }) | 603 | 1 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIB1j_Ahj8_IB1j_B1N_B2I_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB38_3map3MapINtNtNtB3a_7sources4once4OnceB1N_ENcNtB1i_4Left0EIB3W_INtNtB38_7flatten7FlatMapINtNtNtB3c_5array4iter8IntoIterTB2I_B2I_EKj1_EIB34_IB3W_IB4d_B2I_ENcNtB2D_4Left0EIB3W_IB34_IB3W_B4c_NcNtB2N_4Left0EIB3W_B6n_NcNtB2N_5Right0EENcNtB2D_5Right0EENCINvMs_NtNtB9_6author7runtimeNtB89_18InherentExtrinsics25inject_raw_inherents_listB2I_B5t_E0ENcNtB1i_5Right0EEEB9_ Line | Count | Source | 513 | 1 | pub fn run_vectored( | 514 | 1 | mut self, | 515 | 1 | function_to_call: &str, | 516 | 1 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 1 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 1 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 1 | // Determine the total length of `data`. | 520 | 1 | let mut data_len_u32: u32 = 0; | 521 | 4 | for data in data.clone()1 { | 522 | 4 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 4 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 4 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 4 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 1 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 1 | | 537 | 1 | // Prepare the virtual machine for execution. | 538 | 1 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 1 | let data_ptr = match allocator.allocate( | 542 | 1 | &mut MemAccess { | 543 | 1 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 1 | memory_total_pages: self.common.memory_total_pages, | 545 | 1 | }, | 546 | 1 | data_len_u32, | 547 | 1 | ) { | 548 | 1 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 1 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 1 | .checked_sub(u32::from(vm.memory_size())) | 559 | 1 | { | 560 | 1 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 1 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 1 | .unwrap_or_else(|_| unreachable!()); | 563 | 1 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 1 | let mut data_ptr_iter = data_ptr; | 567 | 5 | for data4 in data { | 568 | 4 | let data = data.as_ref(); | 569 | 4 | vm.write_memory(data_ptr_iter, data) | 570 | 4 | .unwrap_or_else(|_| unreachable!()); | 571 | 4 | data_ptr_iter = data_ptr_iter | 572 | 4 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 4 | .unwrap_or_else(|| unreachable!()); | 574 | 4 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 1 | let vm = match vm.start( | 579 | 1 | function_to_call, | 580 | 1 | &[ | 581 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 1 | ], | 584 | 1 | ) { | 585 | 1 | Ok(vm) => vm, | 586 | 0 | Err((error, vm_proto)) => { | 587 | 0 | self.vm_proto = vm_proto; | 588 | 0 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 1 | Ok(ReadyToRun { | 593 | 1 | resume_value: None, | 594 | 1 | inner: Box::new(Inner { | 595 | 1 | common: self.common, | 596 | 1 | vm, | 597 | 1 | storage_transaction_depth: 0, | 598 | 1 | signatures_batch_verification: None, | 599 | 1 | allocator, | 600 | 1 | storage_proof_size_behavior, | 601 | 1 | }), | 602 | 1 | }) | 603 | 1 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherRAhj1_IB1j_RShRINtNtCsdZExvAaxgia_5alloc3vec3VechEEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB2E_INtNtB2I_3map3MapINtNtNtB2K_7sources4once4OnceB1N_ENcNtB1i_4Left0EIB3B_IB3B_IB3S_B21_ENcNtB1T_5Right0ENcNtB1i_5Right0EEIB3B_IB3B_IB3S_B1Y_ENcNtB1T_4Left0EB5e_EEEB9_ Line | Count | Source | 513 | 1 | pub fn run_vectored( | 514 | 1 | mut self, | 515 | 1 | function_to_call: &str, | 516 | 1 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 1 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 1 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 1 | // Determine the total length of `data`. | 520 | 1 | let mut data_len_u32: u32 = 0; | 521 | 3 | for data in data.clone()1 { | 522 | 3 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 3 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 3 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 3 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 1 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 1 | | 537 | 1 | // Prepare the virtual machine for execution. | 538 | 1 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 1 | let data_ptr = match allocator.allocate( | 542 | 1 | &mut MemAccess { | 543 | 1 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 1 | memory_total_pages: self.common.memory_total_pages, | 545 | 1 | }, | 546 | 1 | data_len_u32, | 547 | 1 | ) { | 548 | 1 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 1 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 1 | .checked_sub(u32::from(vm.memory_size())) | 559 | 1 | { | 560 | 1 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 1 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 1 | .unwrap_or_else(|_| unreachable!()); | 563 | 1 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 1 | let mut data_ptr_iter = data_ptr; | 567 | 4 | for data3 in data { | 568 | 3 | let data = data.as_ref(); | 569 | 3 | vm.write_memory(data_ptr_iter, data) | 570 | 3 | .unwrap_or_else(|_| unreachable!()); | 571 | 3 | data_ptr_iter = data_ptr_iter | 572 | 3 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 3 | .unwrap_or_else(|| unreachable!()); | 574 | 3 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 1 | let vm = match vm.start( | 579 | 1 | function_to_call, | 580 | 1 | &[ | 581 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 1 | ], | 584 | 1 | ) { | 585 | 1 | Ok(vm) => vm, | 586 | 0 | Err((error, vm_proto)) => { | 587 | 0 | self.vm_proto = vm_proto; | 588 | 0 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 1 | Ok(ReadyToRun { | 593 | 1 | resume_value: None, | 594 | 1 | inner: Box::new(Inner { | 595 | 1 | common: self.common, | 596 | 1 | vm, | 597 | 1 | storage_transaction_depth: 0, | 598 | 1 | signatures_batch_verification: None, | 599 | 1 | allocator, | 600 | 1 | storage_proof_size_behavior, | 601 | 1 | }), | 602 | 1 | }) | 603 | 1 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherRINtNtCsdZExvAaxgia_5alloc3vec3VechEIB1j_B1N_INtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB3p_INtNtNtB3v_7sources4once4OnceB1i_EB4l_EINtNtB3t_3map3MapINtNtNtB3x_5slice4iter4IterNtNtNtB7_12runtime_call5tests9HexStringENCNvB5I_s_14execute_blockss0_0EEEB9_ Line | Count | Source | 513 | 4 | pub fn run_vectored( | 514 | 4 | mut self, | 515 | 4 | function_to_call: &str, | 516 | 4 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 4 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 4 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 4 | // Determine the total length of `data`. | 520 | 4 | let mut data_len_u32: u32 = 0; | 521 | 17 | for data in data.clone()4 { | 522 | 17 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 17 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 17 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 17 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 4 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 4 | | 537 | 4 | // Prepare the virtual machine for execution. | 538 | 4 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 4 | let data_ptr = match allocator.allocate( | 542 | 4 | &mut MemAccess { | 543 | 4 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 4 | memory_total_pages: self.common.memory_total_pages, | 545 | 4 | }, | 546 | 4 | data_len_u32, | 547 | 4 | ) { | 548 | 4 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 4 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 4 | .checked_sub(u32::from(vm.memory_size())) | 559 | 4 | { | 560 | 4 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 4 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 4 | .unwrap_or_else(|_| unreachable!()); | 563 | 4 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 4 | let mut data_ptr_iter = data_ptr; | 567 | 21 | for data17 in data { | 568 | 17 | let data = data.as_ref(); | 569 | 17 | vm.write_memory(data_ptr_iter, data) | 570 | 17 | .unwrap_or_else(|_| unreachable!()); | 571 | 17 | data_ptr_iter = data_ptr_iter | 572 | 17 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 17 | .unwrap_or_else(|| unreachable!()); | 574 | 17 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 4 | let vm = match vm.start( | 579 | 4 | function_to_call, | 580 | 4 | &[ | 581 | 4 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 4 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 4 | ], | 584 | 4 | ) { | 585 | 4 | Ok(vm) => vm, | 586 | 0 | Err((error, vm_proto)) => { | 587 | 0 | self.vm_proto = vm_proto; | 588 | 0 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 4 | Ok(ReadyToRun { | 593 | 4 | resume_value: None, | 594 | 4 | inner: Box::new(Inner { | 595 | 4 | common: self.common, | 596 | 4 | vm, | 597 | 4 | storage_transaction_depth: 0, | 598 | 4 | signatures_batch_verification: None, | 599 | 4 | allocator, | 600 | 4 | storage_proof_size_behavior, | 601 | 4 | }), | 602 | 4 | }) | 603 | 4 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1i_EEB9_ Line | Count | Source | 513 | 11 | pub fn run_vectored( | 514 | 11 | mut self, | 515 | 11 | function_to_call: &str, | 516 | 11 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 11 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 11 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 11 | // Determine the total length of `data`. | 520 | 11 | let mut data_len_u32: u32 = 0; | 521 | 11 | for data0 in data.clone() { | 522 | 0 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 0 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 0 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 0 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 11 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 11 | | 537 | 11 | // Prepare the virtual machine for execution. | 538 | 11 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 11 | let data_ptr = match allocator.allocate( | 542 | 11 | &mut MemAccess { | 543 | 11 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 11 | memory_total_pages: self.common.memory_total_pages, | 545 | 11 | }, | 546 | 11 | data_len_u32, | 547 | 11 | ) { | 548 | 11 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 11 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 11 | .checked_sub(u32::from(vm.memory_size())) | 559 | 11 | { | 560 | 11 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 11 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 11 | .unwrap_or_else(|_| unreachable!()); | 563 | 11 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 11 | let mut data_ptr_iter = data_ptr; | 567 | 11 | for data0 in data { | 568 | 0 | let data = data.as_ref(); | 569 | 0 | vm.write_memory(data_ptr_iter, data) | 570 | 0 | .unwrap_or_else(|_| unreachable!()); | 571 | 0 | data_ptr_iter = data_ptr_iter | 572 | 0 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 0 | .unwrap_or_else(|| unreachable!()); | 574 | 0 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 11 | let vm7 = match vm.start( | 579 | 11 | function_to_call, | 580 | 11 | &[ | 581 | 11 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 11 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 11 | ], | 584 | 11 | ) { | 585 | 7 | Ok(vm) => vm, | 586 | 4 | Err((error, vm_proto)) => { | 587 | 4 | self.vm_proto = vm_proto; | 588 | 4 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 7 | Ok(ReadyToRun { | 593 | 7 | resume_value: None, | 594 | 7 | inner: Box::new(Inner { | 595 | 7 | common: self.common, | 596 | 7 | vm, | 597 | 7 | storage_transaction_depth: 0, | 598 | 7 | signatures_batch_verification: None, | 599 | 7 | allocator, | 600 | 7 | storage_proof_size_behavior, | 601 | 7 | }), | 602 | 7 | }) | 603 | 11 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1i_EEB9_ Line | Count | Source | 513 | 1 | pub fn run_vectored( | 514 | 1 | mut self, | 515 | 1 | function_to_call: &str, | 516 | 1 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 1 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 1 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 1 | // Determine the total length of `data`. | 520 | 1 | let mut data_len_u32: u32 = 0; | 521 | 1 | for data in data.clone() { | 522 | 1 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 1 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 1 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 1 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 1 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 1 | | 537 | 1 | // Prepare the virtual machine for execution. | 538 | 1 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 1 | let data_ptr = match allocator.allocate( | 542 | 1 | &mut MemAccess { | 543 | 1 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 1 | memory_total_pages: self.common.memory_total_pages, | 545 | 1 | }, | 546 | 1 | data_len_u32, | 547 | 1 | ) { | 548 | 1 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 1 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 1 | .checked_sub(u32::from(vm.memory_size())) | 559 | 1 | { | 560 | 1 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 1 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 1 | .unwrap_or_else(|_| unreachable!()); | 563 | 1 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 1 | let mut data_ptr_iter = data_ptr; | 567 | 2 | for data1 in data { | 568 | 1 | let data = data.as_ref(); | 569 | 1 | vm.write_memory(data_ptr_iter, data) | 570 | 1 | .unwrap_or_else(|_| unreachable!()); | 571 | 1 | data_ptr_iter = data_ptr_iter | 572 | 1 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 1 | .unwrap_or_else(|| unreachable!()); | 574 | 1 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 1 | let vm = match vm.start( | 579 | 1 | function_to_call, | 580 | 1 | &[ | 581 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 1 | ], | 584 | 1 | ) { | 585 | 1 | Ok(vm) => vm, | 586 | 0 | Err((error, vm_proto)) => { | 587 | 0 | self.vm_proto = vm_proto; | 588 | 0 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 1 | Ok(ReadyToRun { | 593 | 1 | resume_value: None, | 594 | 1 | inner: Box::new(Inner { | 595 | 1 | common: self.common, | 596 | 1 | vm, | 597 | 1 | storage_transaction_depth: 0, | 598 | 1 | signatures_batch_verification: None, | 599 | 1 | allocator, | 600 | 1 | storage_proof_size_behavior, | 601 | 1 | }), | 602 | 1 | }) | 603 | 1 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRShINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1i_Kj2_EEB9_ Line | Count | Source | 513 | 2 | pub fn run_vectored( | 514 | 2 | mut self, | 515 | 2 | function_to_call: &str, | 516 | 2 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 2 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 2 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 2 | // Determine the total length of `data`. | 520 | 2 | let mut data_len_u32: u32 = 0; | 521 | 4 | for data in data.clone()2 { | 522 | 4 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 4 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 4 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 4 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 2 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 2 | | 537 | 2 | // Prepare the virtual machine for execution. | 538 | 2 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 2 | let data_ptr = match allocator.allocate( | 542 | 2 | &mut MemAccess { | 543 | 2 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 2 | memory_total_pages: self.common.memory_total_pages, | 545 | 2 | }, | 546 | 2 | data_len_u32, | 547 | 2 | ) { | 548 | 2 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 2 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 2 | .checked_sub(u32::from(vm.memory_size())) | 559 | 2 | { | 560 | 2 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 2 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 2 | .unwrap_or_else(|_| unreachable!()); | 563 | 2 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 2 | let mut data_ptr_iter = data_ptr; | 567 | 6 | for data4 in data { | 568 | 4 | let data = data.as_ref(); | 569 | 4 | vm.write_memory(data_ptr_iter, data) | 570 | 4 | .unwrap_or_else(|_| unreachable!()); | 571 | 4 | data_ptr_iter = data_ptr_iter | 572 | 4 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 4 | .unwrap_or_else(|| unreachable!()); | 574 | 4 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 2 | let vm = match vm.start( | 579 | 2 | function_to_call, | 580 | 2 | &[ | 581 | 2 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 2 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 2 | ], | 584 | 2 | ) { | 585 | 2 | Ok(vm) => vm, | 586 | 0 | Err((error, vm_proto)) => { | 587 | 0 | self.vm_proto = vm_proto; | 588 | 0 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 2 | Ok(ReadyToRun { | 593 | 2 | resume_value: None, | 594 | 2 | inner: Box::new(Inner { | 595 | 2 | common: self.common, | 596 | 2 | vm, | 597 | 2 | storage_transaction_depth: 0, | 598 | 2 | signatures_batch_verification: None, | 599 | 2 | allocator, | 600 | 2 | storage_proof_size_behavior, | 601 | 2 | }), | 602 | 2 | }) | 603 | 2 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1i_EEB9_ Line | Count | Source | 513 | 30 | pub fn run_vectored( | 514 | 30 | mut self, | 515 | 30 | function_to_call: &str, | 516 | 30 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 30 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 30 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 30 | // Determine the total length of `data`. | 520 | 30 | let mut data_len_u32: u32 = 0; | 521 | 30 | for data in data.clone() { | 522 | 30 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 30 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 30 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 30 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 30 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 30 | | 537 | 30 | // Prepare the virtual machine for execution. | 538 | 30 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 30 | let data_ptr = match allocator.allocate( | 542 | 30 | &mut MemAccess { | 543 | 30 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 30 | memory_total_pages: self.common.memory_total_pages, | 545 | 30 | }, | 546 | 30 | data_len_u32, | 547 | 30 | ) { | 548 | 30 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 30 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 30 | .checked_sub(u32::from(vm.memory_size())) | 559 | 30 | { | 560 | 30 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 30 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 30 | .unwrap_or_else(|_| unreachable!()); | 563 | 30 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 30 | let mut data_ptr_iter = data_ptr; | 567 | 60 | for data30 in data { | 568 | 30 | let data = data.as_ref(); | 569 | 30 | vm.write_memory(data_ptr_iter, data) | 570 | 30 | .unwrap_or_else(|_| unreachable!()); | 571 | 30 | data_ptr_iter = data_ptr_iter | 572 | 30 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 30 | .unwrap_or_else(|| unreachable!()); | 574 | 30 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 30 | let vm = match vm.start( | 579 | 30 | function_to_call, | 580 | 30 | &[ | 581 | 30 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 30 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 30 | ], | 584 | 30 | ) { | 585 | 30 | Ok(vm) => vm, | 586 | 0 | Err((error, vm_proto)) => { | 587 | 0 | self.vm_proto = vm_proto; | 588 | 0 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 30 | Ok(ReadyToRun { | 593 | 30 | resume_value: None, | 594 | 30 | inner: Box::new(Inner { | 595 | 30 | common: self.common, | 596 | 30 | vm, | 597 | 30 | storage_transaction_depth: 0, | 598 | 30 | signatures_batch_verification: None, | 599 | 30 | allocator, | 600 | 30 | storage_proof_size_behavior, | 601 | 30 | }), | 602 | 30 | }) | 603 | 30 | } |
_RINvMs_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1i_EEB9_ Line | Count | Source | 513 | 1 | pub fn run_vectored( | 514 | 1 | mut self, | 515 | 1 | function_to_call: &str, | 516 | 1 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 1 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 1 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 1 | // Determine the total length of `data`. | 520 | 1 | let mut data_len_u32: u32 = 0; | 521 | 1 | for data0 in data.clone() { | 522 | 0 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 0 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 0 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 0 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 1 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 1 | | 537 | 1 | // Prepare the virtual machine for execution. | 538 | 1 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 1 | let data_ptr = match allocator.allocate( | 542 | 1 | &mut MemAccess { | 543 | 1 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 1 | memory_total_pages: self.common.memory_total_pages, | 545 | 1 | }, | 546 | 1 | data_len_u32, | 547 | 1 | ) { | 548 | 1 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 1 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 1 | .checked_sub(u32::from(vm.memory_size())) | 559 | 1 | { | 560 | 1 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 1 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 1 | .unwrap_or_else(|_| unreachable!()); | 563 | 1 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 1 | let mut data_ptr_iter = data_ptr; | 567 | 1 | for data0 in data { | 568 | 0 | let data = data.as_ref(); | 569 | 0 | vm.write_memory(data_ptr_iter, data) | 570 | 0 | .unwrap_or_else(|_| unreachable!()); | 571 | 0 | data_ptr_iter = data_ptr_iter | 572 | 0 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 0 | .unwrap_or_else(|| unreachable!()); | 574 | 0 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 1 | let vm = match vm.start( | 579 | 1 | function_to_call, | 580 | 1 | &[ | 581 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 1 | ], | 584 | 1 | ) { | 585 | 1 | Ok(vm) => vm, | 586 | 0 | Err((error, vm_proto)) => { | 587 | 0 | self.vm_proto = vm_proto; | 588 | 0 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 1 | Ok(ReadyToRun { | 593 | 1 | resume_value: None, | 594 | 1 | inner: Box::new(Inner { | 595 | 1 | common: self.common, | 596 | 1 | vm, | 597 | 1 | storage_transaction_depth: 0, | 598 | 1 | signatures_batch_verification: None, | 599 | 1 | allocator, | 600 | 1 | storage_proof_size_behavior, | 601 | 1 | }), | 602 | 1 | }) | 603 | 1 | } |
Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1j_EECsDDUKWWCHAU_18smoldot_light_wasm Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherIB1k_RShINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EEIB1k_B1W_IB1k_INtNtCsdZExvAaxgia_5alloc3vec3VechEB1T_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB3M_3map3MapIB3I_IB3I_IB3I_INtNtNtB3O_7sources4once4OnceB1O_EB55_EB55_EB55_ENcNtB1j_4Left0EIB4A_IB3I_IB56_B2N_EINtNtB3M_7flatten7FlatMapNtNtB9_6header8LogsIterIB4A_INtNtNtB3Q_5array4iter8IntoIterB2W_Kj2_ENcNtB2N_5Right0ENCNvMs2_B6S_NtB6S_9DigestRef14scale_encoding0EENcNtB1j_5Right0EEEB9_ Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredINtCs1qmLyiTSqYF_6either6EitherINtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_EIB1k_Ahj8_IB1k_B1O_B2J_EEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB39_3map3MapINtNtNtB3b_7sources4once4OnceB1O_ENcNtB1j_4Left0EIB3X_INtNtB39_7flatten7FlatMapINtNtNtB3d_5array4iter8IntoIterTB2J_B2J_EKj1_EIB35_IB3X_IB4e_B2J_ENcNtB2E_4Left0EIB3X_IB35_IB3X_B4d_NcNtB2O_4Left0EIB3X_B6o_NcNtB2O_5Right0EENcNtB2E_5Right0EENCINvMs_NtNtB9_6author7runtimeNtB8a_18InherentExtrinsics25inject_raw_inherents_listB2J_B5u_E0ENcNtB1j_5Right0EEEB9_ _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1j_EEB9_ Line | Count | Source | 513 | 126 | pub fn run_vectored( | 514 | 126 | mut self, | 515 | 126 | function_to_call: &str, | 516 | 126 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 126 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 126 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 126 | // Determine the total length of `data`. | 520 | 126 | let mut data_len_u32: u32 = 0; | 521 | 126 | for data0 in data.clone() { | 522 | 0 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 0 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 0 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 0 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 126 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 126 | | 537 | 126 | // Prepare the virtual machine for execution. | 538 | 126 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 126 | let data_ptr = match allocator.allocate( | 542 | 126 | &mut MemAccess { | 543 | 126 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 126 | memory_total_pages: self.common.memory_total_pages, | 545 | 126 | }, | 546 | 126 | data_len_u32, | 547 | 126 | ) { | 548 | 126 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 126 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 126 | .checked_sub(u32::from(vm.memory_size())) | 559 | 126 | { | 560 | 126 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 126 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 126 | .unwrap_or_else(|_| unreachable!()); | 563 | 126 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 126 | let mut data_ptr_iter = data_ptr; | 567 | 126 | for data0 in data { | 568 | 0 | let data = data.as_ref(); | 569 | 0 | vm.write_memory(data_ptr_iter, data) | 570 | 0 | .unwrap_or_else(|_| unreachable!()); | 571 | 0 | data_ptr_iter = data_ptr_iter | 572 | 0 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 0 | .unwrap_or_else(|| unreachable!()); | 574 | 0 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 126 | let vm = match vm.start( | 579 | 126 | function_to_call, | 580 | 126 | &[ | 581 | 126 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 126 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 126 | ], | 584 | 126 | ) { | 585 | 126 | Ok(vm) => vm, | 586 | 0 | Err((error, vm_proto)) => { | 587 | 0 | self.vm_proto = vm_proto; | 588 | 0 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 126 | Ok(ReadyToRun { | 593 | 126 | resume_value: None, | 594 | 126 | inner: Box::new(Inner { | 595 | 126 | common: self.common, | 596 | 126 | vm, | 597 | 126 | storage_transaction_depth: 0, | 598 | 126 | signatures_batch_verification: None, | 599 | 126 | allocator, | 600 | 126 | storage_proof_size_behavior, | 601 | 126 | }), | 602 | 126 | }) | 603 | 126 | } |
Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1j_EEB9_ Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1j_EEB9_ Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1j_EEB9_ Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1j_EECsiLzmwikkc22_14json_rpc_basic _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources5empty5EmptyB1j_EECsiUjFBJteJ7x_17smoldot_full_node Line | Count | Source | 513 | 1 | pub fn run_vectored( | 514 | 1 | mut self, | 515 | 1 | function_to_call: &str, | 516 | 1 | storage_proof_size_behavior: StorageProofSizeBehavior, | 517 | 1 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 518 | 1 | ) -> Result<ReadyToRun, (StartErr, Self)> { | 519 | 1 | // Determine the total length of `data`. | 520 | 1 | let mut data_len_u32: u32 = 0; | 521 | 1 | for data0 in data.clone() { | 522 | 0 | let len = match u32::try_from(data.as_ref().len()) { | 523 | 0 | Ok(v) => v, | 524 | 0 | Err(_) => return Err((StartErr::DataSizeOverflow, self)), | 525 | | }; | 526 | 0 | data_len_u32 = match data_len_u32.checked_add(len) { | 527 | 0 | Some(v) => v, | 528 | 0 | None => return Err((StartErr::DataSizeOverflow, self)), | 529 | | }; | 530 | | } | 531 | | | 532 | | // Initialize the state of the memory allocator. This is the allocator that is used in | 533 | | // order to allocate space for the input data, and also later used when the Wasm code | 534 | | // requests variable-length data. | 535 | 1 | let mut allocator = allocator::FreeingBumpHeapAllocator::new(self.common.heap_base); | 536 | 1 | | 537 | 1 | // Prepare the virtual machine for execution. | 538 | 1 | let mut vm = self.vm_proto.prepare(); | 539 | | | 540 | | // Write the input data in the VM's memory using the allocator. | 541 | 1 | let data_ptr = match allocator.allocate( | 542 | 1 | &mut MemAccess { | 543 | 1 | vm: MemAccessVm::Prepare(&mut vm), | 544 | 1 | memory_total_pages: self.common.memory_total_pages, | 545 | 1 | }, | 546 | 1 | data_len_u32, | 547 | 1 | ) { | 548 | 1 | Ok(p) => p, | 549 | | Err(_) => { | 550 | 0 | self.vm_proto = vm.into_prototype(); | 551 | 0 | return Err((StartErr::DataSizeOverflow, self)); | 552 | | } | 553 | | }; | 554 | | | 555 | | // While the allocator has reserved memory, it might have reserved more memory than its | 556 | | // current size. | 557 | 1 | if let Some(to_grow) = ((data_ptr + data_len_u32).saturating_sub(1) / (64 * 1024) + 1) | 558 | 1 | .checked_sub(u32::from(vm.memory_size())) | 559 | 1 | { | 560 | 1 | // If the memory can't be grown, it indicates a bug in the allocator. | 561 | 1 | vm.grow_memory(HeapPages::from(to_grow)) | 562 | 1 | .unwrap_or_else(|_| unreachable!()); | 563 | 1 | }0 | 564 | | | 565 | | // Writing the input data into the VM. | 566 | 1 | let mut data_ptr_iter = data_ptr; | 567 | 1 | for data0 in data { | 568 | 0 | let data = data.as_ref(); | 569 | 0 | vm.write_memory(data_ptr_iter, data) | 570 | 0 | .unwrap_or_else(|_| unreachable!()); | 571 | 0 | data_ptr_iter = data_ptr_iter | 572 | 0 | .checked_add(u32::try_from(data.len()).unwrap_or_else(|_| unreachable!())) | 573 | 0 | .unwrap_or_else(|| unreachable!()); | 574 | 0 | } | 575 | | | 576 | | // Now start executing the function. We pass as parameter the location and size of the | 577 | | // input data. | 578 | 1 | let vm = match vm.start( | 579 | 1 | function_to_call, | 580 | 1 | &[ | 581 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_ptr.to_ne_bytes())), | 582 | 1 | vm::WasmValue::I32(i32::from_ne_bytes(data_len_u32.to_ne_bytes())), | 583 | 1 | ], | 584 | 1 | ) { | 585 | 1 | Ok(vm) => vm, | 586 | 0 | Err((error, vm_proto)) => { | 587 | 0 | self.vm_proto = vm_proto; | 588 | 0 | return Err((error.into(), self)); | 589 | | } | 590 | | }; | 591 | | | 592 | 1 | Ok(ReadyToRun { | 593 | 1 | resume_value: None, | 594 | 1 | inner: Box::new(Inner { | 595 | 1 | common: self.common, | 596 | 1 | vm, | 597 | 1 | storage_transaction_depth: 0, | 598 | 1 | signatures_batch_verification: None, | 599 | 1 | allocator, | 600 | 1 | storage_proof_size_behavior, | 601 | 1 | }), | 602 | 1 | }) | 603 | 1 | } |
Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1j_EECscDgN54JpMGG_6author Unexecuted instantiation: _RINvMs_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototype12run_vectoredRRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1j_EECsibGXYHQB8Ea_25json_rpc_general_requests |
604 | | } |
605 | | |
606 | | impl fmt::Debug for HostVmPrototype { |
607 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
608 | 0 | f.debug_tuple("HostVmPrototype").finish() |
609 | 0 | } Unexecuted instantiation: _RNvXs0_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_15HostVmPrototypeNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs0_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_15HostVmPrototypeNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
610 | | } |
611 | | |
612 | | /// Running virtual machine. |
613 | | #[must_use] |
614 | | #[derive(derive_more::From, Debug)] |
615 | | pub enum HostVm { |
616 | | /// Wasm virtual machine is ready to be run. Call [`ReadyToRun::run`] to make progress. |
617 | | #[from] |
618 | | ReadyToRun(ReadyToRun), |
619 | | /// Function execution has succeeded. Contains the return value of the call. |
620 | | /// |
621 | | /// The trie root hash of all the child tries must be recalculated and written to the main trie |
622 | | /// similar to when a [`ExternalStorageRoot`] with a `child_trie` of `None` is generated. See |
623 | | /// the documentation of [`ExternalStorageRoot`]. |
624 | | #[from] |
625 | | Finished(Finished), |
626 | | /// The Wasm blob did something that doesn't conform to the runtime environment. |
627 | | Error { |
628 | | /// Virtual machine ready to be used again. |
629 | | prototype: HostVmPrototype, |
630 | | /// Error that happened. |
631 | | error: Error, |
632 | | }, |
633 | | /// Must load an storage value. |
634 | | #[from] |
635 | | ExternalStorageGet(ExternalStorageGet), |
636 | | /// Must set an storage value. |
637 | | #[from] |
638 | | ExternalStorageSet(ExternalStorageSet), |
639 | | /// See documentation of [`ExternalStorageAppend`]. |
640 | | #[from] |
641 | | ExternalStorageAppend(ExternalStorageAppend), |
642 | | /// Must remove all the storage values starting with a certain prefix. |
643 | | #[from] |
644 | | ExternalStorageClearPrefix(ExternalStorageClearPrefix), |
645 | | /// Must provide the trie root hash of the storage and write the trie root hash of child tries |
646 | | /// to the main trie. |
647 | | #[from] |
648 | | ExternalStorageRoot(ExternalStorageRoot), |
649 | | /// Need to provide the storage key that follows a specific one. |
650 | | #[from] |
651 | | ExternalStorageNextKey(ExternalStorageNextKey), |
652 | | /// Must set off-chain index value. |
653 | | #[from] |
654 | | ExternalOffchainIndexSet(ExternalOffchainIndexSet), |
655 | | /// Must load an offchain storage value. |
656 | | #[from] |
657 | | ExternalOffchainStorageGet(ExternalOffchainStorageGet), |
658 | | /// Must set value of an off-chain storage entry. |
659 | | #[from] |
660 | | ExternalOffchainStorageSet(ExternalOffchainStorageSet), |
661 | | /// Need to provide the current timestamp. |
662 | | #[from] |
663 | | OffchainTimestamp(OffchainTimestamp), |
664 | | /// Must return random seed. |
665 | | #[from] |
666 | | OffchainRandomSeed(OffchainRandomSeed), |
667 | | /// Submit a transaction from offchain worker. |
668 | | #[from] |
669 | | OffchainSubmitTransaction(OffchainSubmitTransaction), |
670 | | /// Need to verify whether a signature is valid. |
671 | | #[from] |
672 | | SignatureVerification(SignatureVerification), |
673 | | /// Need to call `Core_version` on the given Wasm code and return the raw output (i.e. |
674 | | /// still SCALE-encoded), or an error if the call has failed. |
675 | | #[from] |
676 | | CallRuntimeVersion(CallRuntimeVersion), |
677 | | /// Declares the start of a storage transaction. See [`HostVm::EndStorageTransaction`]. |
678 | | #[from] |
679 | | StartStorageTransaction(StartStorageTransaction), |
680 | | /// Ends a storage transaction. All changes made to the storage (e.g. through a |
681 | | /// [`HostVm::ExternalStorageSet`]) since the previous |
682 | | /// [`HostVm::StartStorageTransaction`] must be rolled back if `rollback` is true. |
683 | | /// |
684 | | /// Guaranteed by the code in this module to never happen if no transaction is in progress. |
685 | | /// If the runtime attempts to end a non-existing transaction, an [`HostVm::Error`] is |
686 | | /// generated instead. |
687 | | EndStorageTransaction { |
688 | | /// Object used to resume execution. |
689 | | resume: EndStorageTransaction, |
690 | | /// If true, changes must be rolled back. |
691 | | rollback: bool, |
692 | | }, |
693 | | /// Need to provide the maximum log level. |
694 | | #[from] |
695 | | GetMaxLogLevel(GetMaxLogLevel), |
696 | | /// Runtime has emitted a log entry. |
697 | | #[from] |
698 | | LogEmit(LogEmit), |
699 | | } |
700 | | |
701 | | impl HostVm { |
702 | | /// Cancels execution of the virtual machine and returns back the prototype. |
703 | 0 | pub fn into_prototype(self) -> HostVmPrototype { |
704 | 0 | match self { |
705 | 0 | HostVm::ReadyToRun(inner) => inner.inner.into_prototype(), |
706 | 0 | HostVm::Finished(inner) => inner.inner.into_prototype(), |
707 | 0 | HostVm::Error { prototype, .. } => prototype, |
708 | 0 | HostVm::ExternalStorageGet(inner) => inner.inner.into_prototype(), |
709 | 0 | HostVm::ExternalStorageSet(inner) => inner.inner.into_prototype(), |
710 | 0 | HostVm::ExternalStorageAppend(inner) => inner.inner.into_prototype(), |
711 | 0 | HostVm::ExternalStorageClearPrefix(inner) => inner.inner.into_prototype(), |
712 | 0 | HostVm::ExternalStorageRoot(inner) => inner.inner.into_prototype(), |
713 | 0 | HostVm::ExternalStorageNextKey(inner) => inner.inner.into_prototype(), |
714 | 0 | HostVm::ExternalOffchainIndexSet(inner) => inner.inner.into_prototype(), |
715 | 0 | HostVm::ExternalOffchainStorageGet(inner) => inner.inner.into_prototype(), |
716 | 0 | HostVm::ExternalOffchainStorageSet(inner) => inner.inner.into_prototype(), |
717 | 0 | HostVm::OffchainTimestamp(inner) => inner.inner.into_prototype(), |
718 | 0 | HostVm::OffchainRandomSeed(inner) => inner.inner.into_prototype(), |
719 | 0 | HostVm::OffchainSubmitTransaction(inner) => inner.inner.into_prototype(), |
720 | 0 | HostVm::SignatureVerification(inner) => inner.inner.into_prototype(), |
721 | 0 | HostVm::CallRuntimeVersion(inner) => inner.inner.into_prototype(), |
722 | 0 | HostVm::StartStorageTransaction(inner) => inner.inner.into_prototype(), |
723 | 0 | HostVm::EndStorageTransaction { resume, .. } => resume.inner.into_prototype(), |
724 | 0 | HostVm::GetMaxLogLevel(inner) => inner.inner.into_prototype(), |
725 | 0 | HostVm::LogEmit(inner) => inner.inner.into_prototype(), |
726 | | } |
727 | 0 | } Unexecuted instantiation: _RNvMs1_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_6HostVm14into_prototype Unexecuted instantiation: _RNvMs1_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_6HostVm14into_prototype |
728 | | } |
729 | | |
730 | | /// Virtual machine is ready to run. |
731 | | pub struct ReadyToRun { |
732 | | inner: Box<Inner>, |
733 | | resume_value: Option<vm::WasmValue>, |
734 | | } |
735 | | |
736 | | impl ReadyToRun { |
737 | | /// Runs the virtual machine until something important happens. |
738 | | /// |
739 | | /// > **Note**: This is when the actual CPU-heavy computation happens. |
740 | 1.49k | pub fn run(mut self) -> HostVm { |
741 | 34.4k | loop { |
742 | 34.4k | match self.run_once() { |
743 | 32.9k | HostVm::ReadyToRun(r) => self = r, |
744 | 1.49k | other => return other, |
745 | 1.49k | } |
746 | 1.49k | } |
747 | 1.49k | } _RNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_10ReadyToRun3run Line | Count | Source | 740 | 1.15k | pub fn run(mut self) -> HostVm { | 741 | 29.2k | loop { | 742 | 29.2k | match self.run_once() { | 743 | 28.0k | HostVm::ReadyToRun(r) => self = r, | 744 | 1.15k | other => return other, | 745 | 1.15k | } | 746 | 1.15k | } | 747 | 1.15k | } |
_RNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_10ReadyToRun3run Line | Count | Source | 740 | 338 | pub fn run(mut self) -> HostVm { | 741 | 5.20k | loop { | 742 | 5.20k | match self.run_once() { | 743 | 4.86k | HostVm::ReadyToRun(r) => self = r, | 744 | 338 | other => return other, | 745 | 338 | } | 746 | 338 | } | 747 | 338 | } |
|
748 | | |
749 | 34.4k | fn run_once(mut self) -> HostVm { |
750 | | // `vm::ExecOutcome::Interrupted` is by far the variant that requires the most |
751 | | // handling code. As such, special-case all other variants before. |
752 | 34.4k | let (id, params34.2k ) = match self.inner.vm.run(self.resume_value) { |
753 | 34.2k | Ok(vm::ExecOutcome::Interrupted { id, params }) => (id, params), |
754 | | |
755 | | Ok(vm::ExecOutcome::Finished { |
756 | 169 | return_value: Ok(Some(vm::WasmValue::I64(ret))), |
757 | 169 | }) => { |
758 | 169 | // Wasm virtual machine has successfully returned. |
759 | 169 | |
760 | 169 | if self.inner.storage_transaction_depth > 0 { |
761 | 0 | return HostVm::Error { |
762 | 0 | prototype: self.inner.into_prototype(), |
763 | 0 | error: Error::FinishedWithPendingTransaction, |
764 | 0 | }; |
765 | 169 | } |
766 | 169 | |
767 | 169 | // Turn the `i64` into a `u64`, not changing any bit. |
768 | 169 | let ret = u64::from_ne_bytes(ret.to_ne_bytes()); |
769 | 169 | |
770 | 169 | // According to the runtime environment specification, the return value is two |
771 | 169 | // consecutive I32s representing the length and size of the SCALE-encoded |
772 | 169 | // return value. |
773 | 169 | let value_size = u32::try_from(ret >> 32).unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_once0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_once0Bb_ |
774 | 169 | let value_ptr = u32::try_from(ret & 0xffff_ffff).unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces_0Bb_ |
775 | 169 | |
776 | 169 | if value_size.saturating_add(value_ptr) |
777 | 169 | <= u32::from(self.inner.vm.memory_size()) * 64 * 1024 |
778 | | { |
779 | 165 | return HostVm::Finished(Finished { |
780 | 165 | inner: self.inner, |
781 | 165 | value_ptr, |
782 | 165 | value_size, |
783 | 165 | }); |
784 | 4 | } |
785 | 4 | let error = Error::ReturnedPtrOutOfRange { |
786 | 4 | pointer: value_ptr, |
787 | 4 | size: value_size, |
788 | 4 | memory_size: u32::from(self.inner.vm.memory_size()) * 64 * 1024, |
789 | 4 | }; |
790 | 4 | |
791 | 4 | return HostVm::Error { |
792 | 4 | prototype: self.inner.into_prototype(), |
793 | 4 | error, |
794 | 4 | }; |
795 | | } |
796 | | |
797 | | Ok(vm::ExecOutcome::Finished { |
798 | 2 | return_value: Ok(return_value), |
799 | 2 | }) => { |
800 | 2 | // The Wasm function has successfully returned, but the specs require that it |
801 | 2 | // returns a `i64`. |
802 | 2 | return HostVm::Error { |
803 | 2 | prototype: self.inner.into_prototype(), |
804 | 2 | error: Error::BadReturnValue { |
805 | 2 | actual: return_value.map(|v| v.ty()), _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces0_0Bb_ Line | Count | Source | 805 | 2 | actual: return_value.map(|v| v.ty()), |
Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces0_0Bb_ |
806 | 2 | }, |
807 | 2 | }; |
808 | | } |
809 | | |
810 | | Ok(vm::ExecOutcome::Finished { |
811 | 2 | return_value: Err(err), |
812 | 2 | }) => { |
813 | 2 | return HostVm::Error { |
814 | 2 | error: Error::Trap(err), |
815 | 2 | prototype: self.inner.into_prototype(), |
816 | 2 | } |
817 | | } |
818 | | |
819 | | Err(vm::RunErr::BadValueTy { .. }) => { |
820 | | // Tried to inject back the value returned by a host function, but it doesn't |
821 | | // match what the Wasm code expects. Given that we check the host function |
822 | | // signatures at initialization, this indicates a bug in this implementation. |
823 | 0 | unreachable!() |
824 | | } |
825 | | |
826 | | Err(vm::RunErr::Poisoned) => { |
827 | | // Can only happen if there's a bug somewhere. |
828 | 0 | unreachable!() |
829 | | } |
830 | | }; |
831 | | |
832 | | // The Wasm code has called an host_fn. The `id` is a value that we passed |
833 | | // at initialization, and corresponds to an index in `registered_functions`. |
834 | 34.2k | let host_fn34.2k = match self.inner.common.registered_functions.get(id) { |
835 | 34.2k | Some(FunctionImport::Resolved(f)) => *f, |
836 | 2 | Some(FunctionImport::Unresolved { name, module }) => { |
837 | 2 | return HostVm::Error { |
838 | 2 | error: Error::UnresolvedFunctionCalled { |
839 | 2 | function: name.clone(), |
840 | 2 | module_name: module.clone(), |
841 | 2 | }, |
842 | 2 | prototype: self.inner.into_prototype(), |
843 | 2 | }; |
844 | | } |
845 | 0 | None => unreachable!(), |
846 | | }; |
847 | | |
848 | | // Passed a parameter index. Produces an `impl AsRef<[u8]>`. |
849 | | macro_rules! expect_pointer_size { |
850 | | ($num:expr) => {{ |
851 | | let val = match ¶ms[$num] { |
852 | | vm::WasmValue::I64(v) => u64::from_ne_bytes(v.to_ne_bytes()), |
853 | | // The signatures are checked at initialization and the Wasm VM ensures that |
854 | | // the proper parameter types are provided. |
855 | | _ => unreachable!(), |
856 | | }; |
857 | | |
858 | | let len = u32::try_from(val >> 32).unwrap_or_else(|_| unreachable!()); |
859 | | let ptr = u32::try_from(val & 0xffffffff).unwrap_or_else(|_| unreachable!()); |
860 | | |
861 | | let result = self.inner.vm.read_memory(ptr, len); |
862 | | match result { |
863 | | Ok(v) => v, |
864 | | Err(vm::OutOfBoundsError) => { |
865 | | drop(result); |
866 | | return HostVm::Error { |
867 | | error: Error::ParamOutOfRange { |
868 | | function: host_fn.name(), |
869 | | param_num: $num, |
870 | | pointer: ptr, |
871 | | length: len, |
872 | | }, |
873 | | prototype: self.inner.into_prototype(), |
874 | | }; |
875 | | } |
876 | | } |
877 | | }}; |
878 | | } |
879 | | |
880 | | macro_rules! expect_pointer_size_raw { |
881 | | ($num:expr) => {{ |
882 | | let val = match ¶ms[$num] { |
883 | | vm::WasmValue::I64(v) => u64::from_ne_bytes(v.to_ne_bytes()), |
884 | | // The signatures are checked at initialization and the Wasm VM ensures that |
885 | | // the proper parameter types are provided. |
886 | | _ => unreachable!(), |
887 | | }; |
888 | | |
889 | | let len = u32::try_from(val >> 32).unwrap_or_else(|_| unreachable!()); |
890 | | let ptr = u32::try_from(val & 0xffffffff).unwrap_or_else(|_| unreachable!()); |
891 | | |
892 | | if len.saturating_add(ptr) > u32::from(self.inner.vm.memory_size()) * 64 * 1024 { |
893 | | return HostVm::Error { |
894 | | error: Error::ParamOutOfRange { |
895 | | function: host_fn.name(), |
896 | | param_num: $num, |
897 | | pointer: ptr, |
898 | | length: len, |
899 | | }, |
900 | | prototype: self.inner.into_prototype(), |
901 | | }; |
902 | | } |
903 | | |
904 | | (ptr, len) |
905 | | }}; |
906 | | } |
907 | | |
908 | | macro_rules! expect_pointer_constant_size { |
909 | | ($num:expr, $size:expr) => {{ |
910 | | let ptr = match params[$num] { |
911 | | vm::WasmValue::I32(v) => u32::from_ne_bytes(v.to_ne_bytes()), |
912 | | // The signatures are checked at initialization and the Wasm VM ensures that |
913 | | // the proper parameter types are provided. |
914 | | _ => unreachable!(), |
915 | | }; |
916 | | |
917 | | let result = self.inner.vm.read_memory(ptr, $size); |
918 | | match result { |
919 | | Ok(v) => { |
920 | | *<&[u8; $size]>::try_from(v.as_ref()).unwrap_or_else(|_| unreachable!()) |
921 | | } |
922 | | Err(vm::OutOfBoundsError) => { |
923 | | drop(result); |
924 | | return HostVm::Error { |
925 | | error: Error::ParamOutOfRange { |
926 | | function: host_fn.name(), |
927 | | param_num: $num, |
928 | | pointer: ptr, |
929 | | length: $size, |
930 | | }, |
931 | | prototype: self.inner.into_prototype(), |
932 | | }; |
933 | | } |
934 | | } |
935 | | }}; |
936 | | } |
937 | | |
938 | | macro_rules! expect_pointer_constant_size_raw { |
939 | | ($num:expr, $size:expr) => {{ |
940 | | let ptr = match params[$num] { |
941 | | vm::WasmValue::I32(v) => u32::from_ne_bytes(v.to_ne_bytes()), |
942 | | // The signatures are checked at initialization and the Wasm VM ensures that |
943 | | // the proper parameter types are provided. |
944 | | _ => unreachable!(), |
945 | | }; |
946 | | |
947 | | if u32::saturating_add($size, ptr) |
948 | | > u32::from(self.inner.vm.memory_size()) * 64 * 1024 |
949 | | { |
950 | | return HostVm::Error { |
951 | | error: Error::ParamOutOfRange { |
952 | | function: host_fn.name(), |
953 | | param_num: $num, |
954 | | pointer: ptr, |
955 | | length: $size, |
956 | | }, |
957 | | prototype: self.inner.into_prototype(), |
958 | | }; |
959 | | } |
960 | | |
961 | | ptr |
962 | | }}; |
963 | | } |
964 | | |
965 | | macro_rules! expect_u32 { |
966 | | ($num:expr) => {{ |
967 | | match ¶ms[$num] { |
968 | | vm::WasmValue::I32(v) => u32::from_ne_bytes(v.to_ne_bytes()), |
969 | | // The signatures are checked at initialization and the Wasm VM ensures that |
970 | | // the proper parameter types are provided. |
971 | | _ => unreachable!(), |
972 | | } |
973 | | }}; |
974 | | } |
975 | | |
976 | | macro_rules! expect_offchain_storage_kind { |
977 | | ($num:expr) => {{ |
978 | | match ¶ms[$num] { |
979 | | // `0` indicates `StorageKind::PERSISTENT`, the only kind of offchain |
980 | | // storage that is available. |
981 | | vm::WasmValue::I32(0) => true, |
982 | | // `1` indicates `StorageKind::LOCAL`, which is valid but has never been |
983 | | // implemented in Substrate. |
984 | | vm::WasmValue::I32(1) => false, |
985 | | vm::WasmValue::I32(_) => { |
986 | | return HostVm::Error { |
987 | | error: Error::ParamDecodeError, |
988 | | prototype: self.inner.into_prototype(), |
989 | | } |
990 | | } |
991 | | // The signatures are checked at initialization and the Wasm VM ensures that |
992 | | // the proper parameter types are provided. |
993 | | _ => unreachable!(), |
994 | | } |
995 | | }}; |
996 | | } |
997 | | |
998 | | macro_rules! expect_state_version { |
999 | | ($num:expr) => {{ |
1000 | | match ¶ms[$num] { |
1001 | | vm::WasmValue::I32(0) => TrieEntryVersion::V0, |
1002 | | vm::WasmValue::I32(1) => TrieEntryVersion::V1, |
1003 | | vm::WasmValue::I32(_) => { |
1004 | | return HostVm::Error { |
1005 | | error: Error::ParamDecodeError, |
1006 | | prototype: self.inner.into_prototype(), |
1007 | | } |
1008 | | } |
1009 | | // The signatures are checked at initialization and the Wasm VM ensures that |
1010 | | // the proper parameter types are provided. |
1011 | | _ => unreachable!(), |
1012 | | } |
1013 | | }}; |
1014 | | } |
1015 | | |
1016 | | // TODO: implement all functions and remove this macro |
1017 | | macro_rules! host_fn_not_implemented { |
1018 | | () => {{ |
1019 | | return HostVm::Error { |
1020 | | error: Error::HostFunctionNotImplemented { |
1021 | | function: host_fn.name(), |
1022 | | }, |
1023 | | prototype: self.inner.into_prototype(), |
1024 | | }; |
1025 | | }}; |
1026 | | } |
1027 | | |
1028 | | // Handle the function calls. |
1029 | | // Some of these enum variants simply change the state of `self`, while most of them |
1030 | | // instead return an `ExternalVm` to the user. |
1031 | 34.2k | match host_fn { |
1032 | | HostFunction::ext_storage_set_version_1 => { |
1033 | 300 | let (key_ptr, key_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesl_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesk_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesl_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesk_0Bb_ |
1034 | 300 | let (value_ptr, value_size) = expect_pointer_size_raw!(1)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesn_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesm_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesn_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesm_0Bb_ |
1035 | 300 | HostVm::ExternalStorageSet(ExternalStorageSet { |
1036 | 300 | key_ptr, |
1037 | 300 | key_size, |
1038 | 300 | child_trie_ptr_size: None, |
1039 | 300 | value: Some((value_ptr, value_size)), |
1040 | 300 | inner: self.inner, |
1041 | 300 | }) |
1042 | | } |
1043 | | HostFunction::ext_storage_get_version_1 => { |
1044 | 655 | let (key_ptr, key_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesp_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onceso_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesp_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onceso_0Bb_ |
1045 | 655 | HostVm::ExternalStorageGet(ExternalStorageGet { |
1046 | 655 | key_ptr, |
1047 | 655 | key_size, |
1048 | 655 | child_trie_ptr_size: None, |
1049 | 655 | calling: id, |
1050 | 655 | value_out_ptr: None, |
1051 | 655 | offset: 0, |
1052 | 655 | max_size: u32::MAX, |
1053 | 655 | inner: self.inner, |
1054 | 655 | }) |
1055 | | } |
1056 | | HostFunction::ext_storage_read_version_1 => { |
1057 | 10 | let (key_ptr, key_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesr_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesq_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesr_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesq_0Bb_ |
1058 | 10 | let (value_out_ptr, value_out_size) = expect_pointer_size_raw!(1)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncest_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncess_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncest_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncess_0Bb_ |
1059 | 10 | let offset = expect_u32!(2); |
1060 | 10 | HostVm::ExternalStorageGet(ExternalStorageGet { |
1061 | 10 | key_ptr, |
1062 | 10 | key_size, |
1063 | 10 | child_trie_ptr_size: None, |
1064 | 10 | calling: id, |
1065 | 10 | value_out_ptr: Some(value_out_ptr), |
1066 | 10 | offset, |
1067 | 10 | max_size: value_out_size, |
1068 | 10 | inner: self.inner, |
1069 | 10 | }) |
1070 | | } |
1071 | | HostFunction::ext_storage_clear_version_1 => { |
1072 | 71 | let (key_ptr, key_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesv_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesu_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesv_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesu_0Bb_ |
1073 | 71 | HostVm::ExternalStorageSet(ExternalStorageSet { |
1074 | 71 | key_ptr, |
1075 | 71 | key_size, |
1076 | 71 | child_trie_ptr_size: None, |
1077 | 71 | value: None, |
1078 | 71 | inner: self.inner, |
1079 | 71 | }) |
1080 | | } |
1081 | | HostFunction::ext_storage_exists_version_1 => { |
1082 | 16 | let (key_ptr, key_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesx_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesw_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesx_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesw_0Bb_ |
1083 | 16 | HostVm::ExternalStorageGet(ExternalStorageGet { |
1084 | 16 | key_ptr, |
1085 | 16 | key_size, |
1086 | 16 | child_trie_ptr_size: None, |
1087 | 16 | calling: id, |
1088 | 16 | value_out_ptr: None, |
1089 | 16 | offset: 0, |
1090 | 16 | max_size: 0, |
1091 | 16 | inner: self.inner, |
1092 | 16 | }) |
1093 | | } |
1094 | | HostFunction::ext_storage_clear_prefix_version_1 => { |
1095 | 1 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesz_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesy_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesz_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesy_0Bb_ |
1096 | 1 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { |
1097 | 1 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), |
1098 | 1 | child_trie_ptr_size: None, |
1099 | 1 | inner: self.inner, |
1100 | 1 | max_keys_to_remove: None, |
1101 | 1 | calling: id, |
1102 | 1 | }) |
1103 | | } |
1104 | | HostFunction::ext_storage_clear_prefix_version_2 => { |
1105 | 4 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesB_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesA_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesB_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesA_0Bb_ |
1106 | | |
1107 | 4 | let max_keys_to_remove = { |
1108 | 4 | let input = expect_pointer_size!(1)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesD_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesC_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesD_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesC_0Bb_ |
1109 | 4 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = |
1110 | 4 | nom::combinator::all_consuming(util::nom_option_decode( |
1111 | 4 | nom::number::streaming::le_u32, |
1112 | 4 | ))(input.as_ref()) |
1113 | 4 | .map(|(_, parse_result)| parse_result); _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1_0Bb_ Line | Count | Source | 1113 | 4 | .map(|(_, parse_result)| parse_result); |
Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1_0Bb_ |
1114 | 4 | |
1115 | 4 | match parsing_result { |
1116 | 4 | Ok(val) => Ok(val), |
1117 | 0 | Err(_) => Err(()), |
1118 | | } |
1119 | | }; |
1120 | | |
1121 | 4 | let max_keys_to_remove = match max_keys_to_remove { |
1122 | 4 | Ok(l) => l, |
1123 | | Err(()) => { |
1124 | 0 | return HostVm::Error { |
1125 | 0 | error: Error::ParamDecodeError, |
1126 | 0 | prototype: self.inner.into_prototype(), |
1127 | 0 | }; |
1128 | | } |
1129 | | }; |
1130 | | |
1131 | 4 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { |
1132 | 4 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), |
1133 | 4 | child_trie_ptr_size: None, |
1134 | 4 | inner: self.inner, |
1135 | 4 | max_keys_to_remove, |
1136 | 4 | calling: id, |
1137 | 4 | }) |
1138 | | } |
1139 | | HostFunction::ext_storage_root_version_1 => { |
1140 | 1 | HostVm::ExternalStorageRoot(ExternalStorageRoot { |
1141 | 1 | inner: self.inner, |
1142 | 1 | calling: id, |
1143 | 1 | child_trie_ptr_size: None, |
1144 | 1 | }) |
1145 | | } |
1146 | | HostFunction::ext_storage_root_version_2 => { |
1147 | | // The `ext_storage_root_version_2` host function gets passed as parameter the |
1148 | | // state version of the runtime. This is in fact completely unnecessary as the |
1149 | | // same information is found in the runtime specification, and this parameter |
1150 | | // should be considered as a historical accident. We verify that the version |
1151 | | // provided as parameter is the same as the one in the specification. |
1152 | 4 | let version_param = expect_state_version!(0); |
1153 | 4 | let version_spec = self |
1154 | 4 | .inner |
1155 | 4 | .common |
1156 | 4 | .runtime_version |
1157 | 4 | .as_ref() |
1158 | 4 | .unwrap_or_else(|| unreachable!()0 ) Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2_0Bb_ |
1159 | 4 | .decode() |
1160 | 4 | .state_version |
1161 | 4 | .unwrap_or(TrieEntryVersion::V0); |
1162 | 4 | |
1163 | 4 | if version_param != version_spec { |
1164 | 0 | return HostVm::Error { |
1165 | 0 | error: Error::StateVersionMismatch { |
1166 | 0 | parameter: version_param, |
1167 | 0 | specification: version_spec, |
1168 | 0 | }, |
1169 | 0 | prototype: self.inner.into_prototype(), |
1170 | 0 | }; |
1171 | 4 | } |
1172 | 4 | |
1173 | 4 | HostVm::ExternalStorageRoot(ExternalStorageRoot { |
1174 | 4 | inner: self.inner, |
1175 | 4 | calling: id, |
1176 | 4 | child_trie_ptr_size: None, |
1177 | 4 | }) |
1178 | | } |
1179 | | HostFunction::ext_storage_changes_root_version_1 => { |
1180 | | // The changes trie is an obsolete attempt at having a second trie containing, for |
1181 | | // each storage item, the latest block height where this item has been modified. |
1182 | | // When this function returns `None`, it indicates that the changes trie is |
1183 | | // disabled. While this function used to be called by the runtimes of |
1184 | | // Westend/Polkadot/Kusama (and maybe others), it has never returned anything else |
1185 | | // but `None`. The entire changes trie mechanism was ultimately removed in |
1186 | | // October 2021. |
1187 | | // This function is no longer called by recent runtimes, but must be preserved for |
1188 | | // backwards compatibility. |
1189 | 1 | self.inner.alloc_write_and_return_pointer_size( |
1190 | 1 | HostFunction::ext_storage_changes_root_version_1.name(), |
1191 | 1 | iter::once(&[0][..]), |
1192 | 1 | ) |
1193 | | } |
1194 | | HostFunction::ext_storage_next_key_version_1 => { |
1195 | 1 | let (key_ptr, key_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesF_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesE_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesF_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesE_0Bb_ |
1196 | 1 | HostVm::ExternalStorageNextKey(ExternalStorageNextKey { |
1197 | 1 | key_ptr, |
1198 | 1 | key_size, |
1199 | 1 | child_trie_ptr_size: None, |
1200 | 1 | inner: self.inner, |
1201 | 1 | }) |
1202 | | } |
1203 | | HostFunction::ext_storage_append_version_1 => { |
1204 | 71 | let (key_ptr, key_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesH_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesG_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesH_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesG_0Bb_ |
1205 | 71 | let (value_ptr, value_size) = expect_pointer_size_raw!(1)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesJ_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesI_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesJ_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesI_0Bb_ |
1206 | 71 | HostVm::ExternalStorageAppend(ExternalStorageAppend { |
1207 | 71 | key_ptr, |
1208 | 71 | key_size, |
1209 | 71 | value_ptr, |
1210 | 71 | value_size, |
1211 | 71 | inner: self.inner, |
1212 | 71 | }) |
1213 | | } |
1214 | | HostFunction::ext_storage_start_transaction_version_1 => { |
1215 | | // TODO: a maximum depth is important in order to prevent a malicious runtime from crashing the client, but the depth needs to be the same as in Substrate; figure out |
1216 | 14 | self.inner.storage_transaction_depth += 1; |
1217 | 14 | HostVm::StartStorageTransaction(StartStorageTransaction { inner: self.inner }) |
1218 | | } |
1219 | | HostFunction::ext_storage_rollback_transaction_version_1 => { |
1220 | 0 | if self.inner.storage_transaction_depth == 0 { |
1221 | 0 | return HostVm::Error { |
1222 | 0 | error: Error::NoActiveTransaction, |
1223 | 0 | prototype: self.inner.into_prototype(), |
1224 | 0 | }; |
1225 | 0 | } |
1226 | 0 |
|
1227 | 0 | self.inner.storage_transaction_depth -= 1; |
1228 | 0 | HostVm::EndStorageTransaction { |
1229 | 0 | resume: EndStorageTransaction { inner: self.inner }, |
1230 | 0 | rollback: true, |
1231 | 0 | } |
1232 | | } |
1233 | | HostFunction::ext_storage_commit_transaction_version_1 => { |
1234 | 14 | if self.inner.storage_transaction_depth == 0 { |
1235 | 0 | return HostVm::Error { |
1236 | 0 | error: Error::NoActiveTransaction, |
1237 | 0 | prototype: self.inner.into_prototype(), |
1238 | 0 | }; |
1239 | 14 | } |
1240 | 14 | |
1241 | 14 | self.inner.storage_transaction_depth -= 1; |
1242 | 14 | HostVm::EndStorageTransaction { |
1243 | 14 | resume: EndStorageTransaction { inner: self.inner }, |
1244 | 14 | rollback: false, |
1245 | 14 | } |
1246 | | } |
1247 | | HostFunction::ext_storage_proof_size_storage_proof_size_version_1 => { |
1248 | 0 | match self.inner.storage_proof_size_behavior { |
1249 | 0 | StorageProofSizeBehavior::ConstantReturnValue(value) => { |
1250 | 0 | HostVm::ReadyToRun(ReadyToRun { |
1251 | 0 | inner: self.inner, |
1252 | 0 | resume_value: Some(vm::WasmValue::I64(i64::from_ne_bytes( |
1253 | 0 | value.to_ne_bytes(), |
1254 | 0 | ))), |
1255 | 0 | }) |
1256 | | } |
1257 | 0 | StorageProofSizeBehavior::Unimplemented => HostVm::Error { |
1258 | 0 | error: Error::HostFunctionNotImplemented { |
1259 | 0 | function: host_fn.name(), |
1260 | 0 | }, |
1261 | 0 | prototype: self.inner.into_prototype(), |
1262 | 0 | }, |
1263 | | } |
1264 | | } |
1265 | | HostFunction::ext_default_child_storage_get_version_1 => { |
1266 | 2 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesL_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesK_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesL_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesK_0Bb_ |
1267 | 2 | let (key_ptr, key_size) = expect_pointer_size_raw!(1)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesN_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesM_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesN_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesM_0Bb_ |
1268 | 2 | HostVm::ExternalStorageGet(ExternalStorageGet { |
1269 | 2 | key_ptr, |
1270 | 2 | key_size, |
1271 | 2 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1272 | 2 | calling: id, |
1273 | 2 | value_out_ptr: None, |
1274 | 2 | offset: 0, |
1275 | 2 | max_size: u32::MAX, |
1276 | 2 | inner: self.inner, |
1277 | 2 | }) |
1278 | | } |
1279 | | HostFunction::ext_default_child_storage_read_version_1 => { |
1280 | 4 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesP_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesO_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesP_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesO_0Bb_ |
1281 | 4 | let (key_ptr, key_size) = expect_pointer_size_raw!(1)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesR_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesQ_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesR_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesQ_0Bb_ |
1282 | 4 | let (value_out_ptr, value_out_size) = expect_pointer_size_raw!(2)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesT_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesS_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesT_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesS_0Bb_ |
1283 | 4 | let offset = expect_u32!(3); |
1284 | 4 | HostVm::ExternalStorageGet(ExternalStorageGet { |
1285 | 4 | key_ptr, |
1286 | 4 | key_size, |
1287 | 4 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1288 | 4 | calling: id, |
1289 | 4 | value_out_ptr: Some(value_out_ptr), |
1290 | 4 | offset, |
1291 | 4 | max_size: value_out_size, |
1292 | 4 | inner: self.inner, |
1293 | 4 | }) |
1294 | | } |
1295 | | HostFunction::ext_default_child_storage_storage_kill_version_1 => { |
1296 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesV_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesU_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesV_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesU_0Bb_ |
1297 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { |
1298 | 0 | prefix_ptr_size: None, |
1299 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1300 | 0 | inner: self.inner, |
1301 | 0 | max_keys_to_remove: None, |
1302 | 0 | calling: id, |
1303 | 0 | }) |
1304 | | } |
1305 | | HostFunction::ext_default_child_storage_storage_kill_version_2 |
1306 | | | HostFunction::ext_default_child_storage_storage_kill_version_3 => { |
1307 | 1 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesX_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesW_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesX_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesW_0Bb_ |
1308 | | |
1309 | 1 | let max_keys_to_remove = { |
1310 | 1 | let input = expect_pointer_size!(1)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesZ_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesY_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesZ_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesY_0Bb_ |
1311 | 1 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = |
1312 | 1 | nom::combinator::all_consuming(util::nom_option_decode( |
1313 | 1 | nom::number::streaming::le_u32, |
1314 | 1 | ))(input.as_ref()) |
1315 | 1 | .map(|(_, parse_result)| parse_result); _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces3_0Bb_ Line | Count | Source | 1315 | 1 | .map(|(_, parse_result)| parse_result); |
Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces3_0Bb_ |
1316 | 1 | |
1317 | 1 | match parsing_result { |
1318 | 1 | Ok(val) => Ok(val), |
1319 | 0 | Err(_) => Err(()), |
1320 | | } |
1321 | | }; |
1322 | | |
1323 | 1 | let max_keys_to_remove = match max_keys_to_remove { |
1324 | 1 | Ok(l) => l, |
1325 | | Err(()) => { |
1326 | 0 | return HostVm::Error { |
1327 | 0 | error: Error::ParamDecodeError, |
1328 | 0 | prototype: self.inner.into_prototype(), |
1329 | 0 | }; |
1330 | | } |
1331 | | }; |
1332 | | |
1333 | 1 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { |
1334 | 1 | prefix_ptr_size: None, |
1335 | 1 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1336 | 1 | inner: self.inner, |
1337 | 1 | max_keys_to_remove, |
1338 | 1 | calling: id, |
1339 | 1 | }) |
1340 | | } |
1341 | | HostFunction::ext_default_child_storage_clear_prefix_version_1 => { |
1342 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces11_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces10_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces11_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces10_0Bb_ |
1343 | 0 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces13_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces12_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces13_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces12_0Bb_ |
1344 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { |
1345 | 0 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), |
1346 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1347 | 0 | inner: self.inner, |
1348 | 0 | max_keys_to_remove: None, |
1349 | 0 | calling: id, |
1350 | 0 | }) |
1351 | | } |
1352 | | HostFunction::ext_default_child_storage_clear_prefix_version_2 => { |
1353 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces15_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces14_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces15_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces14_0Bb_ |
1354 | 0 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces17_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces16_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces17_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces16_0Bb_ |
1355 | | |
1356 | 0 | let max_keys_to_remove = { |
1357 | 0 | let input = expect_pointer_size!(2); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces19_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces18_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces19_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces18_0Bb_ |
1358 | 0 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = |
1359 | 0 | nom::combinator::all_consuming(util::nom_option_decode( |
1360 | 0 | nom::number::streaming::le_u32, |
1361 | 0 | ))(input.as_ref()) |
1362 | 0 | .map(|(_, parse_result)| parse_result); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces4_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces4_0Bb_ |
1363 | 0 |
|
1364 | 0 | match parsing_result { |
1365 | 0 | Ok(val) => Ok(val), |
1366 | 0 | Err(_) => Err(()), |
1367 | | } |
1368 | | }; |
1369 | | |
1370 | 0 | let max_keys_to_remove = match max_keys_to_remove { |
1371 | 0 | Ok(l) => l, |
1372 | | Err(()) => { |
1373 | 0 | return HostVm::Error { |
1374 | 0 | error: Error::ParamDecodeError, |
1375 | 0 | prototype: self.inner.into_prototype(), |
1376 | 0 | }; |
1377 | | } |
1378 | | }; |
1379 | | |
1380 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { |
1381 | 0 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), |
1382 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1383 | 0 | inner: self.inner, |
1384 | 0 | max_keys_to_remove, |
1385 | 0 | calling: id, |
1386 | 0 | }) |
1387 | | } |
1388 | | HostFunction::ext_default_child_storage_set_version_1 => { |
1389 | 4 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1b_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1a_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1b_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1a_0Bb_ |
1390 | 4 | let (key_ptr, key_size) = expect_pointer_size_raw!(1)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1d_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1c_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1d_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1c_0Bb_ |
1391 | 4 | let (value_ptr, value_size) = expect_pointer_size_raw!(2)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1f_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1e_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1f_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1e_0Bb_ |
1392 | 4 | HostVm::ExternalStorageSet(ExternalStorageSet { |
1393 | 4 | key_ptr, |
1394 | 4 | key_size, |
1395 | 4 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1396 | 4 | value: Some((value_ptr, value_size)), |
1397 | 4 | inner: self.inner, |
1398 | 4 | }) |
1399 | | } |
1400 | | HostFunction::ext_default_child_storage_clear_version_1 => { |
1401 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1h_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1g_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1h_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1g_0Bb_ |
1402 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1j_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1i_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1j_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1i_0Bb_ |
1403 | 0 | HostVm::ExternalStorageSet(ExternalStorageSet { |
1404 | 0 | key_ptr, |
1405 | 0 | key_size, |
1406 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1407 | 0 | value: None, |
1408 | 0 | inner: self.inner, |
1409 | 0 | }) |
1410 | | } |
1411 | | HostFunction::ext_default_child_storage_exists_version_1 => { |
1412 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1l_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1k_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1l_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1k_0Bb_ |
1413 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1n_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1m_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1n_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1m_0Bb_ |
1414 | 0 | HostVm::ExternalStorageGet(ExternalStorageGet { |
1415 | 0 | key_ptr, |
1416 | 0 | key_size, |
1417 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1418 | 0 | calling: id, |
1419 | 0 | value_out_ptr: None, |
1420 | 0 | offset: 0, |
1421 | 0 | max_size: 0, |
1422 | 0 | inner: self.inner, |
1423 | 0 | }) |
1424 | | } |
1425 | | HostFunction::ext_default_child_storage_next_key_version_1 => { |
1426 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1p_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1o_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1p_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1o_0Bb_ |
1427 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1r_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1q_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1r_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1q_0Bb_ |
1428 | 0 | HostVm::ExternalStorageNextKey(ExternalStorageNextKey { |
1429 | 0 | key_ptr, |
1430 | 0 | key_size, |
1431 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1432 | 0 | inner: self.inner, |
1433 | 0 | }) |
1434 | | } |
1435 | | HostFunction::ext_default_child_storage_root_version_1 => { |
1436 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1t_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1s_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1t_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1s_0Bb_ |
1437 | 0 | HostVm::ExternalStorageRoot(ExternalStorageRoot { |
1438 | 0 | inner: self.inner, |
1439 | 0 | calling: id, |
1440 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1441 | 0 | }) |
1442 | | } |
1443 | | HostFunction::ext_default_child_storage_root_version_2 => { |
1444 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1v_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1u_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1v_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1u_0Bb_ |
1445 | | |
1446 | | // The `ext_default_child_storage_root_version_2` host function gets passed as |
1447 | | // parameter the state version of the runtime. This is in fact completely |
1448 | | // unnecessary as the same information is found in the runtime specification, and |
1449 | | // this parameter should be considered as a historical accident. We verify that the |
1450 | | // version provided as parameter is the same as the one in the specification. |
1451 | 0 | let version_param = expect_state_version!(1); |
1452 | 0 | let version_spec = self |
1453 | 0 | .inner |
1454 | 0 | .common |
1455 | 0 | .runtime_version |
1456 | 0 | .as_ref() |
1457 | 0 | .unwrap_or_else(|| unreachable!()) Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces5_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces5_0Bb_ |
1458 | 0 | .decode() |
1459 | 0 | .state_version |
1460 | 0 | .unwrap_or(TrieEntryVersion::V0); |
1461 | 0 |
|
1462 | 0 | if version_param != version_spec { |
1463 | 0 | return HostVm::Error { |
1464 | 0 | error: Error::StateVersionMismatch { |
1465 | 0 | parameter: version_param, |
1466 | 0 | specification: version_spec, |
1467 | 0 | }, |
1468 | 0 | prototype: self.inner.into_prototype(), |
1469 | 0 | }; |
1470 | 0 | } |
1471 | 0 |
|
1472 | 0 | HostVm::ExternalStorageRoot(ExternalStorageRoot { |
1473 | 0 | inner: self.inner, |
1474 | 0 | calling: id, |
1475 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), |
1476 | 0 | }) |
1477 | | } |
1478 | 0 | HostFunction::ext_crypto_ed25519_public_keys_version_1 => host_fn_not_implemented!(), |
1479 | 0 | HostFunction::ext_crypto_ed25519_generate_version_1 => host_fn_not_implemented!(), |
1480 | 0 | HostFunction::ext_crypto_ed25519_sign_version_1 => host_fn_not_implemented!(), |
1481 | | HostFunction::ext_crypto_ed25519_verify_version_1 |
1482 | | | HostFunction::ext_crypto_ed25519_batch_verify_version_1 => { |
1483 | 0 | let is_batch_verification = matches!( |
1484 | 0 | host_fn, |
1485 | | HostFunction::ext_crypto_ed25519_batch_verify_version_1 |
1486 | | ); |
1487 | | |
1488 | 0 | if is_batch_verification && self.inner.signatures_batch_verification.is_none() { |
1489 | 0 | return HostVm::Error { |
1490 | 0 | error: Error::BatchVerifyWithoutStarting, |
1491 | 0 | prototype: self.inner.into_prototype(), |
1492 | 0 | }; |
1493 | 0 | } |
1494 | | |
1495 | 0 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1x_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1w_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1x_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1w_0Bb_ |
1496 | | HostVm::SignatureVerification(SignatureVerification { |
1497 | 0 | algorithm: SignatureVerificationAlgorithm::Ed25519, |
1498 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 64), |
1499 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 32), |
1500 | 0 | message_ptr, |
1501 | 0 | message_size, |
1502 | 0 | inner: self.inner, |
1503 | 0 | is_batch_verification, |
1504 | | }) |
1505 | | } |
1506 | 0 | HostFunction::ext_crypto_sr25519_public_keys_version_1 => host_fn_not_implemented!(), |
1507 | 0 | HostFunction::ext_crypto_sr25519_generate_version_1 => host_fn_not_implemented!(), |
1508 | 0 | HostFunction::ext_crypto_sr25519_sign_version_1 => host_fn_not_implemented!(), |
1509 | | HostFunction::ext_crypto_sr25519_verify_version_1 |
1510 | | | HostFunction::ext_crypto_sr25519_batch_verify_version_1 => { |
1511 | 0 | let is_batch_verification = matches!( |
1512 | 0 | host_fn, |
1513 | | HostFunction::ext_crypto_sr25519_batch_verify_version_1 |
1514 | | ); |
1515 | | |
1516 | 0 | if is_batch_verification && self.inner.signatures_batch_verification.is_none() { |
1517 | 0 | return HostVm::Error { |
1518 | 0 | error: Error::BatchVerifyWithoutStarting, |
1519 | 0 | prototype: self.inner.into_prototype(), |
1520 | 0 | }; |
1521 | 0 | } |
1522 | | |
1523 | 0 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1z_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1y_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1z_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1y_0Bb_ |
1524 | | HostVm::SignatureVerification(SignatureVerification { |
1525 | 0 | algorithm: SignatureVerificationAlgorithm::Sr25519V1, |
1526 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 64), |
1527 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 32), |
1528 | 0 | message_ptr, |
1529 | 0 | message_size, |
1530 | 0 | inner: self.inner, |
1531 | 0 | is_batch_verification, |
1532 | | }) |
1533 | | } |
1534 | | HostFunction::ext_crypto_sr25519_verify_version_2 => { |
1535 | 6 | let (message_ptr, message_size) = expect_pointer_size_raw!(1)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1B_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1A_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1B_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1A_0Bb_ |
1536 | | HostVm::SignatureVerification(SignatureVerification { |
1537 | 6 | algorithm: SignatureVerificationAlgorithm::Sr25519V2, |
1538 | 6 | signature_ptr: expect_pointer_constant_size_raw!(0, 64), |
1539 | 6 | public_key_ptr: expect_pointer_constant_size_raw!(2, 32), |
1540 | 6 | message_ptr, |
1541 | 6 | message_size, |
1542 | 6 | inner: self.inner, |
1543 | | is_batch_verification: false, |
1544 | | }) |
1545 | | } |
1546 | 0 | HostFunction::ext_crypto_ecdsa_generate_version_1 => host_fn_not_implemented!(), |
1547 | | HostFunction::ext_crypto_ecdsa_sign_version_1 => { |
1548 | | // NOTE: safe to unwrap here because we supply the nn to blake2b fn |
1549 | 0 | let data = <[u8; 32]>::try_from( |
1550 | 0 | blake2_rfc::blake2b::blake2b(32, &[], expect_pointer_size!(0).as_ref()) Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1D_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1C_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1D_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1C_0Bb_ |
1551 | 0 | .as_bytes(), |
1552 | 0 | ) |
1553 | 0 | .unwrap_or_else(|_| unreachable!()); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces6_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces6_0Bb_ |
1554 | 0 | let message = libsecp256k1::Message::parse(&data); |
1555 | | |
1556 | 0 | if let Ok(sc) = |
1557 | 0 | libsecp256k1::SecretKey::parse(&expect_pointer_constant_size!(1, 32)) Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1E_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1E_0Bb_ |
1558 | | { |
1559 | 0 | let (sig, ri) = libsecp256k1::sign(&message, &sc); |
1560 | 0 |
|
1561 | 0 | // NOTE: the function returns 2 slices: signature (64 bytes) and recovery ID (1 byte; AS A SLICE) |
1562 | 0 | self.inner.alloc_write_and_return_pointer( |
1563 | 0 | host_fn.name(), |
1564 | 0 | [&sig.serialize()[..], &[ri.serialize()]].into_iter(), |
1565 | 0 | ) |
1566 | | } else { |
1567 | 0 | HostVm::Error { |
1568 | 0 | error: Error::ParamDecodeError, |
1569 | 0 | prototype: self.inner.into_prototype(), |
1570 | 0 | } |
1571 | | } |
1572 | | } |
1573 | 0 | HostFunction::ext_crypto_ecdsa_public_keys_version_1 => host_fn_not_implemented!(), |
1574 | | HostFunction::ext_crypto_ecdsa_verify_version_1 |
1575 | | | HostFunction::ext_crypto_ecdsa_batch_verify_version_1 => { |
1576 | 0 | let is_batch_verification = matches!( |
1577 | 0 | host_fn, |
1578 | | HostFunction::ext_crypto_ecdsa_batch_verify_version_1 |
1579 | | ); |
1580 | | |
1581 | 0 | if is_batch_verification && self.inner.signatures_batch_verification.is_none() { |
1582 | 0 | return HostVm::Error { |
1583 | 0 | error: Error::BatchVerifyWithoutStarting, |
1584 | 0 | prototype: self.inner.into_prototype(), |
1585 | 0 | }; |
1586 | 0 | } |
1587 | | |
1588 | 0 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1G_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1F_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1G_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1F_0Bb_ |
1589 | | HostVm::SignatureVerification(SignatureVerification { |
1590 | 0 | algorithm: SignatureVerificationAlgorithm::Ecdsa, |
1591 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 65), |
1592 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 33), |
1593 | 0 | message_ptr, |
1594 | 0 | message_size, |
1595 | 0 | inner: self.inner, |
1596 | 0 | is_batch_verification, |
1597 | | }) |
1598 | | } |
1599 | 0 | HostFunction::ext_crypto_ecdsa_verify_version_2 => host_fn_not_implemented!(), |
1600 | | HostFunction::ext_crypto_ecdsa_sign_prehashed_version_1 => { |
1601 | | // TODO: seems misimplemented, see https://spec.polkadot.network/#id-ext_crypto_ecdsa_sign_prehashed |
1602 | 0 | let message = libsecp256k1::Message::parse(&expect_pointer_constant_size!(0, 32)); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1H_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1H_0Bb_ |
1603 | | |
1604 | 0 | if let Ok(sc) = |
1605 | 0 | libsecp256k1::SecretKey::parse(&expect_pointer_constant_size!(1, 32)) Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1I_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1I_0Bb_ |
1606 | | { |
1607 | 0 | let (sig, ri) = libsecp256k1::sign(&message, &sc); |
1608 | 0 |
|
1609 | 0 | // NOTE: the function returns 2 slices: signature (64 bytes) and recovery ID (1 byte; AS A SLICE) |
1610 | 0 | self.inner.alloc_write_and_return_pointer( |
1611 | 0 | host_fn.name(), |
1612 | 0 | [&sig.serialize()[..], &[ri.serialize()]].into_iter(), |
1613 | 0 | ) |
1614 | | } else { |
1615 | 0 | HostVm::Error { |
1616 | 0 | error: Error::ParamDecodeError, |
1617 | 0 | prototype: self.inner.into_prototype(), |
1618 | 0 | } |
1619 | | } |
1620 | | } |
1621 | | HostFunction::ext_crypto_ecdsa_verify_prehashed_version_1 => { |
1622 | | HostVm::SignatureVerification(SignatureVerification { |
1623 | 0 | algorithm: SignatureVerificationAlgorithm::EcdsaPrehashed, |
1624 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 65), |
1625 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 33), |
1626 | 0 | message_ptr: expect_pointer_constant_size_raw!(1, 32), |
1627 | | message_size: 32, |
1628 | 0 | inner: self.inner, |
1629 | | is_batch_verification: false, |
1630 | | }) |
1631 | | } |
1632 | | |
1633 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_version_1 |
1634 | | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_version_2 => { |
1635 | 0 | let sig = expect_pointer_constant_size!(0, 65); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1J_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1J_0Bb_ |
1636 | 0 | let msg = expect_pointer_constant_size!(1, 32); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1K_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1K_0Bb_ |
1637 | 0 | let is_v2 = matches!( |
1638 | 0 | host_fn, |
1639 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_version_2 |
1640 | | ); |
1641 | | |
1642 | 0 | let result = { |
1643 | 0 | let rs = if is_v2 { |
1644 | 0 | libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) |
1645 | | } else { |
1646 | 0 | libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64]) |
1647 | | }; |
1648 | | |
1649 | 0 | if let Ok(rs) = rs { |
1650 | 0 | let v = libsecp256k1::RecoveryId::parse(if sig[64] > 26 { |
1651 | 0 | sig[64] - 27 |
1652 | | } else { |
1653 | 0 | sig[64] |
1654 | | }); |
1655 | | |
1656 | 0 | if let Ok(v) = v { |
1657 | 0 | let pubkey = libsecp256k1::recover( |
1658 | 0 | &libsecp256k1::Message::parse_slice(&msg) |
1659 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces7_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces7_0Bb_ |
1660 | 0 | &rs, |
1661 | 0 | &v, |
1662 | 0 | ); |
1663 | | |
1664 | 0 | if let Ok(pubkey) = pubkey { |
1665 | 0 | let mut res = Vec::with_capacity(65); |
1666 | 0 | res.push(0); |
1667 | 0 | res.extend_from_slice(&pubkey.serialize()[1..65]); |
1668 | 0 | res |
1669 | | } else { |
1670 | 0 | vec![1, 2] |
1671 | | } |
1672 | | } else { |
1673 | 0 | vec![1, 1] |
1674 | | } |
1675 | | } else { |
1676 | 0 | vec![1, 0] |
1677 | | } |
1678 | | }; |
1679 | | |
1680 | 0 | self.inner |
1681 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&result)) |
1682 | | } |
1683 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_compressed_version_1 |
1684 | | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_compressed_version_2 => { |
1685 | 0 | let sig = expect_pointer_constant_size!(0, 65); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1L_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1L_0Bb_ |
1686 | 0 | let msg = expect_pointer_constant_size!(1, 32); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1M_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1M_0Bb_ |
1687 | 0 | let is_v2 = matches!( |
1688 | 0 | host_fn, |
1689 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_compressed_version_2 |
1690 | | ); |
1691 | | |
1692 | 0 | let result = { |
1693 | 0 | let rs = if is_v2 { |
1694 | 0 | libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) |
1695 | | } else { |
1696 | 0 | libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64]) |
1697 | | }; |
1698 | | |
1699 | 0 | if let Ok(rs) = rs { |
1700 | 0 | let v = libsecp256k1::RecoveryId::parse(if sig[64] > 26 { |
1701 | 0 | sig[64] - 27 |
1702 | | } else { |
1703 | 0 | sig[64] |
1704 | | }); |
1705 | | |
1706 | 0 | if let Ok(v) = v { |
1707 | 0 | let pubkey = libsecp256k1::recover( |
1708 | 0 | &libsecp256k1::Message::parse_slice(&msg) |
1709 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces8_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces8_0Bb_ |
1710 | 0 | &rs, |
1711 | 0 | &v, |
1712 | 0 | ); |
1713 | | |
1714 | 0 | if let Ok(pubkey) = pubkey { |
1715 | 0 | let mut res = Vec::with_capacity(34); |
1716 | 0 | res.push(0); |
1717 | 0 | res.extend_from_slice(&pubkey.serialize_compressed()); |
1718 | 0 | res |
1719 | | } else { |
1720 | 0 | vec![1, 2] |
1721 | | } |
1722 | | } else { |
1723 | 0 | vec![1, 1] |
1724 | | } |
1725 | | } else { |
1726 | 0 | vec![1, 0] |
1727 | | } |
1728 | | }; |
1729 | | |
1730 | 0 | self.inner |
1731 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&result)) |
1732 | | } |
1733 | | HostFunction::ext_crypto_start_batch_verify_version_1 => { |
1734 | 4 | if self.inner.signatures_batch_verification.is_some() { |
1735 | 0 | return HostVm::Error { |
1736 | 0 | error: Error::AlreadyBatchVerify, |
1737 | 0 | prototype: self.inner.into_prototype(), |
1738 | 0 | }; |
1739 | 4 | } |
1740 | 4 | |
1741 | 4 | self.inner.signatures_batch_verification = Some(true); |
1742 | 4 | |
1743 | 4 | HostVm::ReadyToRun(ReadyToRun { |
1744 | 4 | resume_value: None, |
1745 | 4 | inner: self.inner, |
1746 | 4 | }) |
1747 | | } |
1748 | | HostFunction::ext_crypto_finish_batch_verify_version_1 => { |
1749 | 4 | let Some(outcome) = self.inner.signatures_batch_verification.take() else { |
1750 | 0 | return HostVm::Error { |
1751 | 0 | error: Error::NoBatchVerify, |
1752 | 0 | prototype: self.inner.into_prototype(), |
1753 | 0 | }; |
1754 | | }; |
1755 | | |
1756 | | HostVm::ReadyToRun(ReadyToRun { |
1757 | 4 | resume_value: Some(vm::WasmValue::I32(if outcome { 1 } else { 00 })), |
1758 | 4 | inner: self.inner, |
1759 | | }) |
1760 | | } |
1761 | | HostFunction::ext_hashing_keccak_256_version_1 => { |
1762 | 2 | let hash = |
1763 | 2 | <sha3::Keccak256 as sha3::Digest>::digest(expect_pointer_size!(0)0 .as_ref()); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1O_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1N_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1O_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1N_0Bb_ |
1764 | 2 | self.inner |
1765 | 2 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash)) |
1766 | | } |
1767 | | HostFunction::ext_hashing_keccak_512_version_1 => { |
1768 | 2 | let hash = |
1769 | 2 | <sha3::Keccak512 as sha3::Digest>::digest(expect_pointer_size!(0)0 .as_ref()); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1Q_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1P_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1Q_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1P_0Bb_ |
1770 | 2 | self.inner |
1771 | 2 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash)) |
1772 | | } |
1773 | | HostFunction::ext_hashing_sha2_256_version_1 => { |
1774 | 2 | let hash = <sha2::Sha256 as sha2::Digest>::digest(expect_pointer_size!(0)0 .as_ref()); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1S_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1R_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1S_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1R_0Bb_ |
1775 | 2 | self.inner |
1776 | 2 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash)) |
1777 | | } |
1778 | | HostFunction::ext_hashing_blake2_128_version_1 => { |
1779 | 148 | let out = { |
1780 | 148 | let data = expect_pointer_size!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1U_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1T_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1U_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1T_0Bb_ |
1781 | 148 | blake2_rfc::blake2b::blake2b(16, &[], data.as_ref()) |
1782 | 148 | }; |
1783 | 148 | |
1784 | 148 | self.inner |
1785 | 148 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(out.as_bytes())) |
1786 | | } |
1787 | | HostFunction::ext_hashing_blake2_256_version_1 => { |
1788 | 30 | let out = { |
1789 | 30 | let data = expect_pointer_size!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1W_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1V_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1W_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1V_0Bb_ |
1790 | 30 | blake2_rfc::blake2b::blake2b(32, &[], data.as_ref()) |
1791 | 30 | }; |
1792 | 30 | |
1793 | 30 | self.inner |
1794 | 30 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(out.as_bytes())) |
1795 | | } |
1796 | | HostFunction::ext_hashing_twox_64_version_1 => { |
1797 | 67 | let mut h0 = twox_hash::XxHash::with_seed(0); |
1798 | 67 | { |
1799 | 67 | let data = expect_pointer_size!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1Y_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1X_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1Y_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1X_0Bb_ |
1800 | 67 | h0.write(data.as_ref()); |
1801 | 67 | } |
1802 | 67 | let r0 = h0.finish(); |
1803 | 67 | |
1804 | 67 | self.inner |
1805 | 67 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&r0.to_le_bytes())) |
1806 | | } |
1807 | | HostFunction::ext_hashing_twox_128_version_1 => { |
1808 | 1.81k | let mut h0 = twox_hash::XxHash::with_seed(0); |
1809 | 1.81k | let mut h1 = twox_hash::XxHash::with_seed(1); |
1810 | 1.81k | { |
1811 | 1.81k | let data = expect_pointer_size!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces20_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1Z_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces20_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces1Z_0Bb_ |
1812 | 1.81k | let data = data.as_ref(); |
1813 | 1.81k | h0.write(data); |
1814 | 1.81k | h1.write(data); |
1815 | 1.81k | } |
1816 | 1.81k | let r0 = h0.finish(); |
1817 | 1.81k | let r1 = h1.finish(); |
1818 | 1.81k | |
1819 | 1.81k | self.inner.alloc_write_and_return_pointer( |
1820 | 1.81k | host_fn.name(), |
1821 | 1.81k | iter::once(&r0.to_le_bytes()).chain(iter::once(&r1.to_le_bytes())), |
1822 | 1.81k | ) |
1823 | | } |
1824 | | HostFunction::ext_hashing_twox_256_version_1 => { |
1825 | 2 | let mut h0 = twox_hash::XxHash::with_seed(0); |
1826 | 2 | let mut h1 = twox_hash::XxHash::with_seed(1); |
1827 | 2 | let mut h2 = twox_hash::XxHash::with_seed(2); |
1828 | 2 | let mut h3 = twox_hash::XxHash::with_seed(3); |
1829 | 2 | { |
1830 | 2 | let data = expect_pointer_size!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces22_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces21_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces22_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces21_0Bb_ |
1831 | 2 | let data = data.as_ref(); |
1832 | 2 | h0.write(data); |
1833 | 2 | h1.write(data); |
1834 | 2 | h2.write(data); |
1835 | 2 | h3.write(data); |
1836 | 2 | } |
1837 | 2 | let r0 = h0.finish(); |
1838 | 2 | let r1 = h1.finish(); |
1839 | 2 | let r2 = h2.finish(); |
1840 | 2 | let r3 = h3.finish(); |
1841 | 2 | |
1842 | 2 | self.inner.alloc_write_and_return_pointer( |
1843 | 2 | host_fn.name(), |
1844 | 2 | iter::once(&r0.to_le_bytes()) |
1845 | 2 | .chain(iter::once(&r1.to_le_bytes())) |
1846 | 2 | .chain(iter::once(&r2.to_le_bytes())) |
1847 | 2 | .chain(iter::once(&r3.to_le_bytes())), |
1848 | 2 | ) |
1849 | | } |
1850 | | HostFunction::ext_offchain_index_set_version_1 => { |
1851 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces24_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces23_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces24_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces23_0Bb_ |
1852 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces26_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces25_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces26_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces25_0Bb_ |
1853 | 0 | HostVm::ExternalOffchainIndexSet(ExternalOffchainIndexSet { |
1854 | 0 | key_ptr, |
1855 | 0 | key_size, |
1856 | 0 | value: Some((value_ptr, value_size)), |
1857 | 0 | inner: self.inner, |
1858 | 0 | }) |
1859 | | } |
1860 | | HostFunction::ext_offchain_index_clear_version_1 => { |
1861 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces28_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces27_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces28_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces27_0Bb_ |
1862 | 0 | HostVm::ExternalOffchainIndexSet(ExternalOffchainIndexSet { |
1863 | 0 | key_ptr, |
1864 | 0 | key_size, |
1865 | 0 | value: None, |
1866 | 0 | inner: self.inner, |
1867 | 0 | }) |
1868 | | } |
1869 | 0 | HostFunction::ext_offchain_is_validator_version_1 => HostVm::ReadyToRun(ReadyToRun { |
1870 | 0 | inner: self.inner, |
1871 | 0 | resume_value: Some(vm::WasmValue::I32(1)), // TODO: ask the API user |
1872 | 0 | }), |
1873 | | HostFunction::ext_offchain_submit_transaction_version_1 => { |
1874 | 0 | let (tx_ptr, tx_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2a_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces29_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2a_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces29_0Bb_ |
1875 | 0 | HostVm::OffchainSubmitTransaction(OffchainSubmitTransaction { |
1876 | 0 | inner: self.inner, |
1877 | 0 | calling: id, |
1878 | 0 | tx_ptr, |
1879 | 0 | tx_size, |
1880 | 0 | }) |
1881 | | } |
1882 | | HostFunction::ext_offchain_network_state_version_1 => { |
1883 | 0 | host_fn_not_implemented!() |
1884 | | } |
1885 | | HostFunction::ext_offchain_timestamp_version_1 => { |
1886 | 0 | HostVm::OffchainTimestamp(OffchainTimestamp { inner: self.inner }) |
1887 | | } |
1888 | | HostFunction::ext_offchain_sleep_until_version_1 => { |
1889 | 0 | host_fn_not_implemented!() |
1890 | | } |
1891 | | HostFunction::ext_offchain_random_seed_version_1 => { |
1892 | 0 | HostVm::OffchainRandomSeed(OffchainRandomSeed { |
1893 | 0 | inner: self.inner, |
1894 | 0 | calling: id, |
1895 | 0 | }) |
1896 | | } |
1897 | | HostFunction::ext_offchain_local_storage_set_version_1 => { |
1898 | 0 | if expect_offchain_storage_kind!(0) { |
1899 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2c_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2b_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2c_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2b_0Bb_ |
1900 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(2); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2e_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2d_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2e_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2d_0Bb_ |
1901 | 0 | HostVm::ExternalOffchainStorageSet(ExternalOffchainStorageSet { |
1902 | 0 | key_ptr, |
1903 | 0 | key_size, |
1904 | 0 | value: Some((value_ptr, value_size)), |
1905 | 0 | old_value: None, |
1906 | 0 | inner: self.inner, |
1907 | 0 | }) |
1908 | | } else { |
1909 | 0 | HostVm::ReadyToRun(ReadyToRun { |
1910 | 0 | inner: self.inner, |
1911 | 0 | resume_value: None, |
1912 | 0 | }) |
1913 | | } |
1914 | | } |
1915 | | HostFunction::ext_offchain_local_storage_compare_and_set_version_1 => { |
1916 | 0 | if expect_offchain_storage_kind!(0) { |
1917 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2g_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2f_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2g_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2f_0Bb_ |
1918 | 0 | let (old_value_ptr, old_value_size) = expect_pointer_size_raw!(2); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2i_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2h_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2i_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2h_0Bb_ |
1919 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(3); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2k_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2j_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2k_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2j_0Bb_ |
1920 | 0 | HostVm::ExternalOffchainStorageSet(ExternalOffchainStorageSet { |
1921 | 0 | key_ptr, |
1922 | 0 | key_size, |
1923 | 0 | value: Some((value_ptr, value_size)), |
1924 | 0 | old_value: Some((old_value_ptr, old_value_size)), |
1925 | 0 | inner: self.inner, |
1926 | 0 | }) |
1927 | | } else { |
1928 | 0 | HostVm::ReadyToRun(ReadyToRun { |
1929 | 0 | inner: self.inner, |
1930 | 0 | resume_value: Some(vm::WasmValue::I32(0)), |
1931 | 0 | }) |
1932 | | } |
1933 | | } |
1934 | | HostFunction::ext_offchain_local_storage_get_version_1 => { |
1935 | 0 | if expect_offchain_storage_kind!(0) { |
1936 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2m_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2l_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2m_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2l_0Bb_ |
1937 | 0 | HostVm::ExternalOffchainStorageGet(ExternalOffchainStorageGet { |
1938 | 0 | key_ptr, |
1939 | 0 | key_size, |
1940 | 0 | calling: id, |
1941 | 0 | inner: self.inner, |
1942 | 0 | }) |
1943 | | } else { |
1944 | | // Write a SCALE-encoded `None`. |
1945 | 0 | self.inner |
1946 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&[0])) |
1947 | | } |
1948 | | } |
1949 | | HostFunction::ext_offchain_local_storage_clear_version_1 => { |
1950 | 0 | if expect_offchain_storage_kind!(0) { |
1951 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2o_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2n_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2o_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2n_0Bb_ |
1952 | 0 | HostVm::ExternalOffchainStorageSet(ExternalOffchainStorageSet { |
1953 | 0 | key_ptr, |
1954 | 0 | key_size, |
1955 | 0 | value: None, |
1956 | 0 | old_value: None, |
1957 | 0 | inner: self.inner, |
1958 | 0 | }) |
1959 | | } else { |
1960 | 0 | HostVm::ReadyToRun(ReadyToRun { |
1961 | 0 | inner: self.inner, |
1962 | 0 | resume_value: None, |
1963 | 0 | }) |
1964 | | } |
1965 | | } |
1966 | 0 | HostFunction::ext_offchain_http_request_start_version_1 => host_fn_not_implemented!(), |
1967 | | HostFunction::ext_offchain_http_request_add_header_version_1 => { |
1968 | 0 | host_fn_not_implemented!() |
1969 | | } |
1970 | | HostFunction::ext_offchain_http_request_write_body_version_1 => { |
1971 | 0 | host_fn_not_implemented!() |
1972 | | } |
1973 | 0 | HostFunction::ext_offchain_http_response_wait_version_1 => host_fn_not_implemented!(), |
1974 | | HostFunction::ext_offchain_http_response_headers_version_1 => { |
1975 | 0 | host_fn_not_implemented!() |
1976 | | } |
1977 | | HostFunction::ext_offchain_http_response_read_body_version_1 => { |
1978 | 0 | host_fn_not_implemented!() |
1979 | | } |
1980 | | HostFunction::ext_trie_blake2_256_root_version_1 |
1981 | | | HostFunction::ext_trie_blake2_256_root_version_2 |
1982 | | | HostFunction::ext_trie_keccak_256_root_version_1 |
1983 | | | HostFunction::ext_trie_keccak_256_root_version_2 => { |
1984 | 0 | let state_version = if matches!( |
1985 | 0 | host_fn, |
1986 | | HostFunction::ext_trie_blake2_256_root_version_2 |
1987 | | | HostFunction::ext_trie_keccak_256_root_version_2 |
1988 | | ) { |
1989 | 0 | expect_state_version!(1) |
1990 | | } else { |
1991 | 0 | TrieEntryVersion::V0 |
1992 | | }; |
1993 | | |
1994 | 0 | let result = { |
1995 | 0 | let input = expect_pointer_size!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2q_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2p_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2q_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2p_0Bb_ |
1996 | 0 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = |
1997 | 0 | nom::combinator::all_consuming(nom::combinator::flat_map( |
1998 | 0 | crate::util::nom_scale_compact_usize, |
1999 | 0 | |num_elems| { |
2000 | 0 | nom::multi::many_m_n( |
2001 | 0 | num_elems, |
2002 | 0 | num_elems, |
2003 | 0 | nom::sequence::tuple(( |
2004 | 0 | nom::combinator::flat_map( |
2005 | 0 | crate::util::nom_scale_compact_usize, |
2006 | 0 | nom::bytes::streaming::take, |
2007 | 0 | ), |
2008 | 0 | nom::combinator::flat_map( |
2009 | 0 | crate::util::nom_scale_compact_usize, |
2010 | 0 | nom::bytes::streaming::take, |
2011 | 0 | ), |
2012 | 0 | )), |
2013 | 0 | ) |
2014 | 0 | }, Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces9_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces9_0Bb_ |
2015 | 0 | ))(input.as_ref()) |
2016 | 0 | .map(|(_, parse_result)| parse_result); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesa_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesa_0Bb_ |
2017 | 0 |
|
2018 | 0 | match parsing_result { |
2019 | 0 | Ok(elements) => Ok(trie::trie_root( |
2020 | 0 | state_version, |
2021 | 0 | if matches!( |
2022 | 0 | host_fn, |
2023 | | HostFunction::ext_trie_blake2_256_root_version_1 |
2024 | | | HostFunction::ext_trie_blake2_256_root_version_2 |
2025 | | ) { |
2026 | 0 | trie::HashFunction::Blake2 |
2027 | | } else { |
2028 | 0 | trie::HashFunction::Keccak256 |
2029 | | }, |
2030 | 0 | &elements[..], |
2031 | | )), |
2032 | 0 | Err(_) => Err(()), |
2033 | | } |
2034 | | }; |
2035 | | |
2036 | 0 | match result { |
2037 | 0 | Ok(out) => self |
2038 | 0 | .inner |
2039 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&out)), |
2040 | 0 | Err(()) => HostVm::Error { |
2041 | 0 | error: Error::ParamDecodeError, |
2042 | 0 | prototype: self.inner.into_prototype(), |
2043 | 0 | }, |
2044 | | } |
2045 | | } |
2046 | | HostFunction::ext_trie_blake2_256_ordered_root_version_1 |
2047 | | | HostFunction::ext_trie_blake2_256_ordered_root_version_2 |
2048 | | | HostFunction::ext_trie_keccak_256_ordered_root_version_1 |
2049 | | | HostFunction::ext_trie_keccak_256_ordered_root_version_2 => { |
2050 | 5 | let state_version = if matches!1 ( |
2051 | 5 | host_fn, |
2052 | | HostFunction::ext_trie_blake2_256_ordered_root_version_2 |
2053 | | | HostFunction::ext_trie_keccak_256_ordered_root_version_2 |
2054 | | ) { |
2055 | 4 | expect_state_version!(1) |
2056 | | } else { |
2057 | 1 | TrieEntryVersion::V0 |
2058 | | }; |
2059 | | |
2060 | 5 | let result = { |
2061 | 5 | let input = expect_pointer_size!(0)0 ; Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2s_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2r_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2s_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2r_0Bb_ |
2062 | 5 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = |
2063 | 5 | nom::combinator::all_consuming(nom::combinator::flat_map( |
2064 | 5 | crate::util::nom_scale_compact_usize, |
2065 | 5 | |num_elems| { |
2066 | 5 | nom::multi::many_m_n( |
2067 | 5 | num_elems, |
2068 | 5 | num_elems, |
2069 | 5 | nom::combinator::flat_map( |
2070 | 5 | crate::util::nom_scale_compact_usize, |
2071 | 5 | nom::bytes::streaming::take, |
2072 | 5 | ), |
2073 | 5 | ) |
2074 | 5 | }, _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesb_0Bb_ Line | Count | Source | 2065 | 5 | |num_elems| { | 2066 | 5 | nom::multi::many_m_n( | 2067 | 5 | num_elems, | 2068 | 5 | num_elems, | 2069 | 5 | nom::combinator::flat_map( | 2070 | 5 | crate::util::nom_scale_compact_usize, | 2071 | 5 | nom::bytes::streaming::take, | 2072 | 5 | ), | 2073 | 5 | ) | 2074 | 5 | }, |
Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesb_0Bb_ |
2075 | 5 | ))(input.as_ref()) |
2076 | 5 | .map(|(_, parse_result)| parse_result); _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesc_0Bb_ Line | Count | Source | 2076 | 5 | .map(|(_, parse_result)| parse_result); |
Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesc_0Bb_ |
2077 | 5 | |
2078 | 5 | match parsing_result { |
2079 | 5 | Ok(elements) => Ok(trie::ordered_root( |
2080 | 5 | state_version, |
2081 | 0 | if matches!( |
2082 | 5 | host_fn, |
2083 | | HostFunction::ext_trie_blake2_256_ordered_root_version_1 |
2084 | | | HostFunction::ext_trie_blake2_256_ordered_root_version_2 |
2085 | | ) { |
2086 | 5 | trie::HashFunction::Blake2 |
2087 | | } else { |
2088 | 0 | trie::HashFunction::Keccak256 |
2089 | | }, |
2090 | 5 | &elements[..], |
2091 | | )), |
2092 | 0 | Err(_) => Err(()), |
2093 | | } |
2094 | | }; |
2095 | | |
2096 | 5 | match result { |
2097 | 5 | Ok(out) => self |
2098 | 5 | .inner |
2099 | 5 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&out)), |
2100 | 0 | Err(()) => HostVm::Error { |
2101 | 0 | error: Error::ParamDecodeError, |
2102 | 0 | prototype: self.inner.into_prototype(), |
2103 | 0 | }, |
2104 | | } |
2105 | | } |
2106 | 0 | HostFunction::ext_trie_blake2_256_verify_proof_version_1 => host_fn_not_implemented!(), |
2107 | 0 | HostFunction::ext_trie_blake2_256_verify_proof_version_2 => host_fn_not_implemented!(), |
2108 | 0 | HostFunction::ext_trie_keccak_256_verify_proof_version_1 => host_fn_not_implemented!(), |
2109 | 0 | HostFunction::ext_trie_keccak_256_verify_proof_version_2 => host_fn_not_implemented!(), |
2110 | | HostFunction::ext_misc_print_num_version_1 => { |
2111 | 0 | let num = match params[0] { |
2112 | 0 | vm::WasmValue::I64(v) => u64::from_ne_bytes(v.to_ne_bytes()), |
2113 | | // The signatures are checked at initialization and the Wasm VM ensures that |
2114 | | // the proper parameter types are provided. |
2115 | 0 | _ => unreachable!(), |
2116 | | }; |
2117 | | |
2118 | 0 | HostVm::LogEmit(LogEmit { |
2119 | 0 | inner: self.inner, |
2120 | 0 | log_entry: LogEmitInner::Num(num), |
2121 | 0 | }) |
2122 | | } |
2123 | | HostFunction::ext_misc_print_utf8_version_1 => { |
2124 | 0 | let (str_ptr, str_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2u_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2t_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2u_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2t_0Bb_ |
2125 | | |
2126 | 0 | let utf8_check = str::from_utf8( |
2127 | 0 | self.inner |
2128 | 0 | .vm |
2129 | 0 | .read_memory(str_ptr, str_size) |
2130 | 0 | .unwrap_or_else(|_| unreachable!()) Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesd_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesd_0Bb_ |
2131 | 0 | .as_ref(), |
2132 | 0 | ) |
2133 | 0 | .map(|_| ()); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncese_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncese_0Bb_ |
2134 | 0 | if let Err(error) = utf8_check { |
2135 | 0 | return HostVm::Error { |
2136 | 0 | error: Error::Utf8Error { |
2137 | 0 | function: host_fn.name(), |
2138 | 0 | param_num: 2, |
2139 | 0 | error, |
2140 | 0 | }, |
2141 | 0 | prototype: self.inner.into_prototype(), |
2142 | 0 | }; |
2143 | 0 | } |
2144 | 0 |
|
2145 | 0 | HostVm::LogEmit(LogEmit { |
2146 | 0 | inner: self.inner, |
2147 | 0 | log_entry: LogEmitInner::Utf8 { str_ptr, str_size }, |
2148 | 0 | }) |
2149 | | } |
2150 | | HostFunction::ext_misc_print_hex_version_1 => { |
2151 | 0 | let (data_ptr, data_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2w_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2v_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2w_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2v_0Bb_ |
2152 | 0 | HostVm::LogEmit(LogEmit { |
2153 | 0 | inner: self.inner, |
2154 | 0 | log_entry: LogEmitInner::Hex { |
2155 | 0 | data_ptr, |
2156 | 0 | data_size, |
2157 | 0 | }, |
2158 | 0 | }) |
2159 | | } |
2160 | | HostFunction::ext_misc_runtime_version_version_1 => { |
2161 | 0 | let (wasm_blob_ptr, wasm_blob_size) = expect_pointer_size_raw!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2y_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2x_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2y_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2x_0Bb_ |
2162 | 0 | HostVm::CallRuntimeVersion(CallRuntimeVersion { |
2163 | 0 | inner: self.inner, |
2164 | 0 | wasm_blob_ptr, |
2165 | 0 | wasm_blob_size, |
2166 | 0 | }) |
2167 | | } |
2168 | | HostFunction::ext_allocator_malloc_version_1 => { |
2169 | 14.1k | let size = expect_u32!(0); |
2170 | | |
2171 | 14.1k | let ptr = match self.inner.alloc(host_fn.name(), size) { |
2172 | 14.1k | Ok(p) => p, |
2173 | 0 | Err(error) => { |
2174 | 0 | return HostVm::Error { |
2175 | 0 | error, |
2176 | 0 | prototype: self.inner.into_prototype(), |
2177 | 0 | } |
2178 | | } |
2179 | | }; |
2180 | | |
2181 | 14.1k | let ptr_i32 = i32::from_ne_bytes(ptr.to_ne_bytes()); |
2182 | 14.1k | HostVm::ReadyToRun(ReadyToRun { |
2183 | 14.1k | resume_value: Some(vm::WasmValue::I32(ptr_i32)), |
2184 | 14.1k | inner: self.inner, |
2185 | 14.1k | }) |
2186 | | } |
2187 | | HostFunction::ext_allocator_free_version_1 => { |
2188 | 16.7k | let pointer = expect_u32!(0); |
2189 | 16.7k | match self.inner.allocator.deallocate( |
2190 | 16.7k | &mut MemAccess { |
2191 | 16.7k | vm: MemAccessVm::Running(&mut self.inner.vm), |
2192 | 16.7k | memory_total_pages: self.inner.common.memory_total_pages, |
2193 | 16.7k | }, |
2194 | 16.7k | pointer, |
2195 | 16.7k | ) { |
2196 | 16.7k | Ok(()) => {} |
2197 | | Err(_) => { |
2198 | 0 | return HostVm::Error { |
2199 | 0 | error: Error::FreeError { pointer }, |
2200 | 0 | prototype: self.inner.into_prototype(), |
2201 | 0 | } |
2202 | | } |
2203 | | }; |
2204 | | |
2205 | 16.7k | HostVm::ReadyToRun(ReadyToRun { |
2206 | 16.7k | resume_value: None, |
2207 | 16.7k | inner: self.inner, |
2208 | 16.7k | }) |
2209 | | } |
2210 | | HostFunction::ext_logging_log_version_1 => { |
2211 | 0 | let log_level = expect_u32!(0); |
2212 | | |
2213 | 0 | let (target_str_ptr, target_str_size) = expect_pointer_size_raw!(1); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2A_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2z_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2A_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2z_0Bb_ |
2214 | 0 | let target_utf8_check = str::from_utf8( |
2215 | 0 | self.inner |
2216 | 0 | .vm |
2217 | 0 | .read_memory(target_str_ptr, target_str_size) |
2218 | 0 | .unwrap_or_else(|_| unreachable!()) Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesf_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesf_0Bb_ |
2219 | 0 | .as_ref(), |
2220 | 0 | ) |
2221 | 0 | .map(|_| ()); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesg_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesg_0Bb_ |
2222 | 0 | if let Err(error) = target_utf8_check { |
2223 | 0 | return HostVm::Error { |
2224 | 0 | error: Error::Utf8Error { |
2225 | 0 | function: host_fn.name(), |
2226 | 0 | param_num: 1, |
2227 | 0 | error, |
2228 | 0 | }, |
2229 | 0 | prototype: self.inner.into_prototype(), |
2230 | 0 | }; |
2231 | 0 | } |
2232 | | |
2233 | 0 | let (msg_str_ptr, msg_str_size) = expect_pointer_size_raw!(2); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2C_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2B_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2C_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2B_0Bb_ |
2234 | 0 | let msg_utf8_check = str::from_utf8( |
2235 | 0 | self.inner |
2236 | 0 | .vm |
2237 | 0 | .read_memory(msg_str_ptr, msg_str_size) |
2238 | 0 | .unwrap_or_else(|_| unreachable!()) Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesh_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesh_0Bb_ |
2239 | 0 | .as_ref(), |
2240 | 0 | ) |
2241 | 0 | .map(|_| ()); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesi_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesi_0Bb_ |
2242 | 0 | if let Err(error) = msg_utf8_check { |
2243 | 0 | return HostVm::Error { |
2244 | 0 | error: Error::Utf8Error { |
2245 | 0 | function: host_fn.name(), |
2246 | 0 | param_num: 2, |
2247 | 0 | error, |
2248 | 0 | }, |
2249 | 0 | prototype: self.inner.into_prototype(), |
2250 | 0 | }; |
2251 | 0 | } |
2252 | 0 |
|
2253 | 0 | HostVm::LogEmit(LogEmit { |
2254 | 0 | inner: self.inner, |
2255 | 0 | log_entry: LogEmitInner::Log { |
2256 | 0 | log_level, |
2257 | 0 | target_str_ptr, |
2258 | 0 | target_str_size, |
2259 | 0 | msg_str_ptr, |
2260 | 0 | msg_str_size, |
2261 | 0 | }, |
2262 | 0 | }) |
2263 | | } |
2264 | | HostFunction::ext_logging_max_level_version_1 => { |
2265 | 136 | HostVm::GetMaxLogLevel(GetMaxLogLevel { inner: self.inner }) |
2266 | | } |
2267 | | HostFunction::ext_panic_handler_abort_on_panic_version_1 => { |
2268 | 0 | let message = { |
2269 | 0 | let message_bytes = expect_pointer_size!(0); Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2E_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2D_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2E_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_onces2D_0Bb_ |
2270 | 0 | str::from_utf8(message_bytes.as_ref()).map(|msg| msg.to_owned()) Unexecuted instantiation: _RNCNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesj_0Bb_ Unexecuted instantiation: _RNCNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_10ReadyToRun8run_oncesj_0Bb_ |
2271 | 0 | }; |
2272 | 0 |
|
2273 | 0 | match message { |
2274 | 0 | Ok(message) => HostVm::Error { |
2275 | 0 | error: Error::AbortOnPanic { message }, |
2276 | 0 | prototype: self.inner.into_prototype(), |
2277 | 0 | }, |
2278 | 0 | Err(error) => HostVm::Error { |
2279 | 0 | error: Error::Utf8Error { |
2280 | 0 | function: host_fn.name(), |
2281 | 0 | param_num: 0, |
2282 | 0 | error, |
2283 | 0 | }, |
2284 | 0 | prototype: self.inner.into_prototype(), |
2285 | 0 | }, |
2286 | | } |
2287 | | } |
2288 | | } |
2289 | 34.4k | } _RNvMs2_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_10ReadyToRun8run_once Line | Count | Source | 749 | 29.2k | fn run_once(mut self) -> HostVm { | 750 | | // `vm::ExecOutcome::Interrupted` is by far the variant that requires the most | 751 | | // handling code. As such, special-case all other variants before. | 752 | 29.2k | let (id, params29.1k ) = match self.inner.vm.run(self.resume_value) { | 753 | 29.1k | Ok(vm::ExecOutcome::Interrupted { id, params }) => (id, params), | 754 | | | 755 | | Ok(vm::ExecOutcome::Finished { | 756 | 42 | return_value: Ok(Some(vm::WasmValue::I64(ret))), | 757 | 42 | }) => { | 758 | 42 | // Wasm virtual machine has successfully returned. | 759 | 42 | | 760 | 42 | if self.inner.storage_transaction_depth > 0 { | 761 | 0 | return HostVm::Error { | 762 | 0 | prototype: self.inner.into_prototype(), | 763 | 0 | error: Error::FinishedWithPendingTransaction, | 764 | 0 | }; | 765 | 42 | } | 766 | 42 | | 767 | 42 | // Turn the `i64` into a `u64`, not changing any bit. | 768 | 42 | let ret = u64::from_ne_bytes(ret.to_ne_bytes()); | 769 | 42 | | 770 | 42 | // According to the runtime environment specification, the return value is two | 771 | 42 | // consecutive I32s representing the length and size of the SCALE-encoded | 772 | 42 | // return value. | 773 | 42 | let value_size = u32::try_from(ret >> 32).unwrap_or_else(|_| unreachable!()); | 774 | 42 | let value_ptr = u32::try_from(ret & 0xffff_ffff).unwrap_or_else(|_| unreachable!()); | 775 | 42 | | 776 | 42 | if value_size.saturating_add(value_ptr) | 777 | 42 | <= u32::from(self.inner.vm.memory_size()) * 64 * 1024 | 778 | | { | 779 | 38 | return HostVm::Finished(Finished { | 780 | 38 | inner: self.inner, | 781 | 38 | value_ptr, | 782 | 38 | value_size, | 783 | 38 | }); | 784 | 4 | } | 785 | 4 | let error = Error::ReturnedPtrOutOfRange { | 786 | 4 | pointer: value_ptr, | 787 | 4 | size: value_size, | 788 | 4 | memory_size: u32::from(self.inner.vm.memory_size()) * 64 * 1024, | 789 | 4 | }; | 790 | 4 | | 791 | 4 | return HostVm::Error { | 792 | 4 | prototype: self.inner.into_prototype(), | 793 | 4 | error, | 794 | 4 | }; | 795 | | } | 796 | | | 797 | | Ok(vm::ExecOutcome::Finished { | 798 | 2 | return_value: Ok(return_value), | 799 | 2 | }) => { | 800 | 2 | // The Wasm function has successfully returned, but the specs require that it | 801 | 2 | // returns a `i64`. | 802 | 2 | return HostVm::Error { | 803 | 2 | prototype: self.inner.into_prototype(), | 804 | 2 | error: Error::BadReturnValue { | 805 | 2 | actual: return_value.map(|v| v.ty()), | 806 | 2 | }, | 807 | 2 | }; | 808 | | } | 809 | | | 810 | | Ok(vm::ExecOutcome::Finished { | 811 | 2 | return_value: Err(err), | 812 | 2 | }) => { | 813 | 2 | return HostVm::Error { | 814 | 2 | error: Error::Trap(err), | 815 | 2 | prototype: self.inner.into_prototype(), | 816 | 2 | } | 817 | | } | 818 | | | 819 | | Err(vm::RunErr::BadValueTy { .. }) => { | 820 | | // Tried to inject back the value returned by a host function, but it doesn't | 821 | | // match what the Wasm code expects. Given that we check the host function | 822 | | // signatures at initialization, this indicates a bug in this implementation. | 823 | 0 | unreachable!() | 824 | | } | 825 | | | 826 | | Err(vm::RunErr::Poisoned) => { | 827 | | // Can only happen if there's a bug somewhere. | 828 | 0 | unreachable!() | 829 | | } | 830 | | }; | 831 | | | 832 | | // The Wasm code has called an host_fn. The `id` is a value that we passed | 833 | | // at initialization, and corresponds to an index in `registered_functions`. | 834 | 29.1k | let host_fn29.1k = match self.inner.common.registered_functions.get(id) { | 835 | 29.1k | Some(FunctionImport::Resolved(f)) => *f, | 836 | 2 | Some(FunctionImport::Unresolved { name, module }) => { | 837 | 2 | return HostVm::Error { | 838 | 2 | error: Error::UnresolvedFunctionCalled { | 839 | 2 | function: name.clone(), | 840 | 2 | module_name: module.clone(), | 841 | 2 | }, | 842 | 2 | prototype: self.inner.into_prototype(), | 843 | 2 | }; | 844 | | } | 845 | 0 | None => unreachable!(), | 846 | | }; | 847 | | | 848 | | // Passed a parameter index. Produces an `impl AsRef<[u8]>`. | 849 | | macro_rules! expect_pointer_size { | 850 | | ($num:expr) => {{ | 851 | | let val = match ¶ms[$num] { | 852 | | vm::WasmValue::I64(v) => u64::from_ne_bytes(v.to_ne_bytes()), | 853 | | // The signatures are checked at initialization and the Wasm VM ensures that | 854 | | // the proper parameter types are provided. | 855 | | _ => unreachable!(), | 856 | | }; | 857 | | | 858 | | let len = u32::try_from(val >> 32).unwrap_or_else(|_| unreachable!()); | 859 | | let ptr = u32::try_from(val & 0xffffffff).unwrap_or_else(|_| unreachable!()); | 860 | | | 861 | | let result = self.inner.vm.read_memory(ptr, len); | 862 | | match result { | 863 | | Ok(v) => v, | 864 | | Err(vm::OutOfBoundsError) => { | 865 | | drop(result); | 866 | | return HostVm::Error { | 867 | | error: Error::ParamOutOfRange { | 868 | | function: host_fn.name(), | 869 | | param_num: $num, | 870 | | pointer: ptr, | 871 | | length: len, | 872 | | }, | 873 | | prototype: self.inner.into_prototype(), | 874 | | }; | 875 | | } | 876 | | } | 877 | | }}; | 878 | | } | 879 | | | 880 | | macro_rules! expect_pointer_size_raw { | 881 | | ($num:expr) => {{ | 882 | | let val = match ¶ms[$num] { | 883 | | vm::WasmValue::I64(v) => u64::from_ne_bytes(v.to_ne_bytes()), | 884 | | // The signatures are checked at initialization and the Wasm VM ensures that | 885 | | // the proper parameter types are provided. | 886 | | _ => unreachable!(), | 887 | | }; | 888 | | | 889 | | let len = u32::try_from(val >> 32).unwrap_or_else(|_| unreachable!()); | 890 | | let ptr = u32::try_from(val & 0xffffffff).unwrap_or_else(|_| unreachable!()); | 891 | | | 892 | | if len.saturating_add(ptr) > u32::from(self.inner.vm.memory_size()) * 64 * 1024 { | 893 | | return HostVm::Error { | 894 | | error: Error::ParamOutOfRange { | 895 | | function: host_fn.name(), | 896 | | param_num: $num, | 897 | | pointer: ptr, | 898 | | length: len, | 899 | | }, | 900 | | prototype: self.inner.into_prototype(), | 901 | | }; | 902 | | } | 903 | | | 904 | | (ptr, len) | 905 | | }}; | 906 | | } | 907 | | | 908 | | macro_rules! expect_pointer_constant_size { | 909 | | ($num:expr, $size:expr) => {{ | 910 | | let ptr = match params[$num] { | 911 | | vm::WasmValue::I32(v) => u32::from_ne_bytes(v.to_ne_bytes()), | 912 | | // The signatures are checked at initialization and the Wasm VM ensures that | 913 | | // the proper parameter types are provided. | 914 | | _ => unreachable!(), | 915 | | }; | 916 | | | 917 | | let result = self.inner.vm.read_memory(ptr, $size); | 918 | | match result { | 919 | | Ok(v) => { | 920 | | *<&[u8; $size]>::try_from(v.as_ref()).unwrap_or_else(|_| unreachable!()) | 921 | | } | 922 | | Err(vm::OutOfBoundsError) => { | 923 | | drop(result); | 924 | | return HostVm::Error { | 925 | | error: Error::ParamOutOfRange { | 926 | | function: host_fn.name(), | 927 | | param_num: $num, | 928 | | pointer: ptr, | 929 | | length: $size, | 930 | | }, | 931 | | prototype: self.inner.into_prototype(), | 932 | | }; | 933 | | } | 934 | | } | 935 | | }}; | 936 | | } | 937 | | | 938 | | macro_rules! expect_pointer_constant_size_raw { | 939 | | ($num:expr, $size:expr) => {{ | 940 | | let ptr = match params[$num] { | 941 | | vm::WasmValue::I32(v) => u32::from_ne_bytes(v.to_ne_bytes()), | 942 | | // The signatures are checked at initialization and the Wasm VM ensures that | 943 | | // the proper parameter types are provided. | 944 | | _ => unreachable!(), | 945 | | }; | 946 | | | 947 | | if u32::saturating_add($size, ptr) | 948 | | > u32::from(self.inner.vm.memory_size()) * 64 * 1024 | 949 | | { | 950 | | return HostVm::Error { | 951 | | error: Error::ParamOutOfRange { | 952 | | function: host_fn.name(), | 953 | | param_num: $num, | 954 | | pointer: ptr, | 955 | | length: $size, | 956 | | }, | 957 | | prototype: self.inner.into_prototype(), | 958 | | }; | 959 | | } | 960 | | | 961 | | ptr | 962 | | }}; | 963 | | } | 964 | | | 965 | | macro_rules! expect_u32 { | 966 | | ($num:expr) => {{ | 967 | | match ¶ms[$num] { | 968 | | vm::WasmValue::I32(v) => u32::from_ne_bytes(v.to_ne_bytes()), | 969 | | // The signatures are checked at initialization and the Wasm VM ensures that | 970 | | // the proper parameter types are provided. | 971 | | _ => unreachable!(), | 972 | | } | 973 | | }}; | 974 | | } | 975 | | | 976 | | macro_rules! expect_offchain_storage_kind { | 977 | | ($num:expr) => {{ | 978 | | match ¶ms[$num] { | 979 | | // `0` indicates `StorageKind::PERSISTENT`, the only kind of offchain | 980 | | // storage that is available. | 981 | | vm::WasmValue::I32(0) => true, | 982 | | // `1` indicates `StorageKind::LOCAL`, which is valid but has never been | 983 | | // implemented in Substrate. | 984 | | vm::WasmValue::I32(1) => false, | 985 | | vm::WasmValue::I32(_) => { | 986 | | return HostVm::Error { | 987 | | error: Error::ParamDecodeError, | 988 | | prototype: self.inner.into_prototype(), | 989 | | } | 990 | | } | 991 | | // The signatures are checked at initialization and the Wasm VM ensures that | 992 | | // the proper parameter types are provided. | 993 | | _ => unreachable!(), | 994 | | } | 995 | | }}; | 996 | | } | 997 | | | 998 | | macro_rules! expect_state_version { | 999 | | ($num:expr) => {{ | 1000 | | match ¶ms[$num] { | 1001 | | vm::WasmValue::I32(0) => TrieEntryVersion::V0, | 1002 | | vm::WasmValue::I32(1) => TrieEntryVersion::V1, | 1003 | | vm::WasmValue::I32(_) => { | 1004 | | return HostVm::Error { | 1005 | | error: Error::ParamDecodeError, | 1006 | | prototype: self.inner.into_prototype(), | 1007 | | } | 1008 | | } | 1009 | | // The signatures are checked at initialization and the Wasm VM ensures that | 1010 | | // the proper parameter types are provided. | 1011 | | _ => unreachable!(), | 1012 | | } | 1013 | | }}; | 1014 | | } | 1015 | | | 1016 | | // TODO: implement all functions and remove this macro | 1017 | | macro_rules! host_fn_not_implemented { | 1018 | | () => {{ | 1019 | | return HostVm::Error { | 1020 | | error: Error::HostFunctionNotImplemented { | 1021 | | function: host_fn.name(), | 1022 | | }, | 1023 | | prototype: self.inner.into_prototype(), | 1024 | | }; | 1025 | | }}; | 1026 | | } | 1027 | | | 1028 | | // Handle the function calls. | 1029 | | // Some of these enum variants simply change the state of `self`, while most of them | 1030 | | // instead return an `ExternalVm` to the user. | 1031 | 29.1k | match host_fn { | 1032 | | HostFunction::ext_storage_set_version_1 => { | 1033 | 300 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1034 | 300 | let (value_ptr, value_size) = expect_pointer_size_raw!(1); | 1035 | 300 | HostVm::ExternalStorageSet(ExternalStorageSet { | 1036 | 300 | key_ptr, | 1037 | 300 | key_size, | 1038 | 300 | child_trie_ptr_size: None, | 1039 | 300 | value: Some((value_ptr, value_size)), | 1040 | 300 | inner: self.inner, | 1041 | 300 | }) | 1042 | | } | 1043 | | HostFunction::ext_storage_get_version_1 => { | 1044 | 571 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1045 | 571 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1046 | 571 | key_ptr, | 1047 | 571 | key_size, | 1048 | 571 | child_trie_ptr_size: None, | 1049 | 571 | calling: id, | 1050 | 571 | value_out_ptr: None, | 1051 | 571 | offset: 0, | 1052 | 571 | max_size: u32::MAX, | 1053 | 571 | inner: self.inner, | 1054 | 571 | }) | 1055 | | } | 1056 | | HostFunction::ext_storage_read_version_1 => { | 1057 | 10 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1058 | 10 | let (value_out_ptr, value_out_size) = expect_pointer_size_raw!(1); | 1059 | 10 | let offset = expect_u32!(2); | 1060 | 10 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1061 | 10 | key_ptr, | 1062 | 10 | key_size, | 1063 | 10 | child_trie_ptr_size: None, | 1064 | 10 | calling: id, | 1065 | 10 | value_out_ptr: Some(value_out_ptr), | 1066 | 10 | offset, | 1067 | 10 | max_size: value_out_size, | 1068 | 10 | inner: self.inner, | 1069 | 10 | }) | 1070 | | } | 1071 | | HostFunction::ext_storage_clear_version_1 => { | 1072 | 71 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1073 | 71 | HostVm::ExternalStorageSet(ExternalStorageSet { | 1074 | 71 | key_ptr, | 1075 | 71 | key_size, | 1076 | 71 | child_trie_ptr_size: None, | 1077 | 71 | value: None, | 1078 | 71 | inner: self.inner, | 1079 | 71 | }) | 1080 | | } | 1081 | | HostFunction::ext_storage_exists_version_1 => { | 1082 | 16 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1083 | 16 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1084 | 16 | key_ptr, | 1085 | 16 | key_size, | 1086 | 16 | child_trie_ptr_size: None, | 1087 | 16 | calling: id, | 1088 | 16 | value_out_ptr: None, | 1089 | 16 | offset: 0, | 1090 | 16 | max_size: 0, | 1091 | 16 | inner: self.inner, | 1092 | 16 | }) | 1093 | | } | 1094 | | HostFunction::ext_storage_clear_prefix_version_1 => { | 1095 | 1 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(0); | 1096 | 1 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1097 | 1 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), | 1098 | 1 | child_trie_ptr_size: None, | 1099 | 1 | inner: self.inner, | 1100 | 1 | max_keys_to_remove: None, | 1101 | 1 | calling: id, | 1102 | 1 | }) | 1103 | | } | 1104 | | HostFunction::ext_storage_clear_prefix_version_2 => { | 1105 | 4 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(0); | 1106 | | | 1107 | 4 | let max_keys_to_remove = { | 1108 | 4 | let input = expect_pointer_size!(1); | 1109 | 4 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = | 1110 | 4 | nom::combinator::all_consuming(util::nom_option_decode( | 1111 | 4 | nom::number::streaming::le_u32, | 1112 | 4 | ))(input.as_ref()) | 1113 | 4 | .map(|(_, parse_result)| parse_result); | 1114 | 4 | | 1115 | 4 | match parsing_result { | 1116 | 4 | Ok(val) => Ok(val), | 1117 | 0 | Err(_) => Err(()), | 1118 | | } | 1119 | | }; | 1120 | | | 1121 | 4 | let max_keys_to_remove = match max_keys_to_remove { | 1122 | 4 | Ok(l) => l, | 1123 | | Err(()) => { | 1124 | 0 | return HostVm::Error { | 1125 | 0 | error: Error::ParamDecodeError, | 1126 | 0 | prototype: self.inner.into_prototype(), | 1127 | 0 | }; | 1128 | | } | 1129 | | }; | 1130 | | | 1131 | 4 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1132 | 4 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), | 1133 | 4 | child_trie_ptr_size: None, | 1134 | 4 | inner: self.inner, | 1135 | 4 | max_keys_to_remove, | 1136 | 4 | calling: id, | 1137 | 4 | }) | 1138 | | } | 1139 | | HostFunction::ext_storage_root_version_1 => { | 1140 | 1 | HostVm::ExternalStorageRoot(ExternalStorageRoot { | 1141 | 1 | inner: self.inner, | 1142 | 1 | calling: id, | 1143 | 1 | child_trie_ptr_size: None, | 1144 | 1 | }) | 1145 | | } | 1146 | | HostFunction::ext_storage_root_version_2 => { | 1147 | | // The `ext_storage_root_version_2` host function gets passed as parameter the | 1148 | | // state version of the runtime. This is in fact completely unnecessary as the | 1149 | | // same information is found in the runtime specification, and this parameter | 1150 | | // should be considered as a historical accident. We verify that the version | 1151 | | // provided as parameter is the same as the one in the specification. | 1152 | 4 | let version_param = expect_state_version!(0); | 1153 | 4 | let version_spec = self | 1154 | 4 | .inner | 1155 | 4 | .common | 1156 | 4 | .runtime_version | 1157 | 4 | .as_ref() | 1158 | 4 | .unwrap_or_else(|| unreachable!()) | 1159 | 4 | .decode() | 1160 | 4 | .state_version | 1161 | 4 | .unwrap_or(TrieEntryVersion::V0); | 1162 | 4 | | 1163 | 4 | if version_param != version_spec { | 1164 | 0 | return HostVm::Error { | 1165 | 0 | error: Error::StateVersionMismatch { | 1166 | 0 | parameter: version_param, | 1167 | 0 | specification: version_spec, | 1168 | 0 | }, | 1169 | 0 | prototype: self.inner.into_prototype(), | 1170 | 0 | }; | 1171 | 4 | } | 1172 | 4 | | 1173 | 4 | HostVm::ExternalStorageRoot(ExternalStorageRoot { | 1174 | 4 | inner: self.inner, | 1175 | 4 | calling: id, | 1176 | 4 | child_trie_ptr_size: None, | 1177 | 4 | }) | 1178 | | } | 1179 | | HostFunction::ext_storage_changes_root_version_1 => { | 1180 | | // The changes trie is an obsolete attempt at having a second trie containing, for | 1181 | | // each storage item, the latest block height where this item has been modified. | 1182 | | // When this function returns `None`, it indicates that the changes trie is | 1183 | | // disabled. While this function used to be called by the runtimes of | 1184 | | // Westend/Polkadot/Kusama (and maybe others), it has never returned anything else | 1185 | | // but `None`. The entire changes trie mechanism was ultimately removed in | 1186 | | // October 2021. | 1187 | | // This function is no longer called by recent runtimes, but must be preserved for | 1188 | | // backwards compatibility. | 1189 | 1 | self.inner.alloc_write_and_return_pointer_size( | 1190 | 1 | HostFunction::ext_storage_changes_root_version_1.name(), | 1191 | 1 | iter::once(&[0][..]), | 1192 | 1 | ) | 1193 | | } | 1194 | | HostFunction::ext_storage_next_key_version_1 => { | 1195 | 1 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1196 | 1 | HostVm::ExternalStorageNextKey(ExternalStorageNextKey { | 1197 | 1 | key_ptr, | 1198 | 1 | key_size, | 1199 | 1 | child_trie_ptr_size: None, | 1200 | 1 | inner: self.inner, | 1201 | 1 | }) | 1202 | | } | 1203 | | HostFunction::ext_storage_append_version_1 => { | 1204 | 71 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1205 | 71 | let (value_ptr, value_size) = expect_pointer_size_raw!(1); | 1206 | 71 | HostVm::ExternalStorageAppend(ExternalStorageAppend { | 1207 | 71 | key_ptr, | 1208 | 71 | key_size, | 1209 | 71 | value_ptr, | 1210 | 71 | value_size, | 1211 | 71 | inner: self.inner, | 1212 | 71 | }) | 1213 | | } | 1214 | | HostFunction::ext_storage_start_transaction_version_1 => { | 1215 | | // TODO: a maximum depth is important in order to prevent a malicious runtime from crashing the client, but the depth needs to be the same as in Substrate; figure out | 1216 | 14 | self.inner.storage_transaction_depth += 1; | 1217 | 14 | HostVm::StartStorageTransaction(StartStorageTransaction { inner: self.inner }) | 1218 | | } | 1219 | | HostFunction::ext_storage_rollback_transaction_version_1 => { | 1220 | 0 | if self.inner.storage_transaction_depth == 0 { | 1221 | 0 | return HostVm::Error { | 1222 | 0 | error: Error::NoActiveTransaction, | 1223 | 0 | prototype: self.inner.into_prototype(), | 1224 | 0 | }; | 1225 | 0 | } | 1226 | 0 |
| 1227 | 0 | self.inner.storage_transaction_depth -= 1; | 1228 | 0 | HostVm::EndStorageTransaction { | 1229 | 0 | resume: EndStorageTransaction { inner: self.inner }, | 1230 | 0 | rollback: true, | 1231 | 0 | } | 1232 | | } | 1233 | | HostFunction::ext_storage_commit_transaction_version_1 => { | 1234 | 14 | if self.inner.storage_transaction_depth == 0 { | 1235 | 0 | return HostVm::Error { | 1236 | 0 | error: Error::NoActiveTransaction, | 1237 | 0 | prototype: self.inner.into_prototype(), | 1238 | 0 | }; | 1239 | 14 | } | 1240 | 14 | | 1241 | 14 | self.inner.storage_transaction_depth -= 1; | 1242 | 14 | HostVm::EndStorageTransaction { | 1243 | 14 | resume: EndStorageTransaction { inner: self.inner }, | 1244 | 14 | rollback: false, | 1245 | 14 | } | 1246 | | } | 1247 | | HostFunction::ext_storage_proof_size_storage_proof_size_version_1 => { | 1248 | 0 | match self.inner.storage_proof_size_behavior { | 1249 | 0 | StorageProofSizeBehavior::ConstantReturnValue(value) => { | 1250 | 0 | HostVm::ReadyToRun(ReadyToRun { | 1251 | 0 | inner: self.inner, | 1252 | 0 | resume_value: Some(vm::WasmValue::I64(i64::from_ne_bytes( | 1253 | 0 | value.to_ne_bytes(), | 1254 | 0 | ))), | 1255 | 0 | }) | 1256 | | } | 1257 | 0 | StorageProofSizeBehavior::Unimplemented => HostVm::Error { | 1258 | 0 | error: Error::HostFunctionNotImplemented { | 1259 | 0 | function: host_fn.name(), | 1260 | 0 | }, | 1261 | 0 | prototype: self.inner.into_prototype(), | 1262 | 0 | }, | 1263 | | } | 1264 | | } | 1265 | | HostFunction::ext_default_child_storage_get_version_1 => { | 1266 | 2 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1267 | 2 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1268 | 2 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1269 | 2 | key_ptr, | 1270 | 2 | key_size, | 1271 | 2 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1272 | 2 | calling: id, | 1273 | 2 | value_out_ptr: None, | 1274 | 2 | offset: 0, | 1275 | 2 | max_size: u32::MAX, | 1276 | 2 | inner: self.inner, | 1277 | 2 | }) | 1278 | | } | 1279 | | HostFunction::ext_default_child_storage_read_version_1 => { | 1280 | 4 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1281 | 4 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1282 | 4 | let (value_out_ptr, value_out_size) = expect_pointer_size_raw!(2); | 1283 | 4 | let offset = expect_u32!(3); | 1284 | 4 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1285 | 4 | key_ptr, | 1286 | 4 | key_size, | 1287 | 4 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1288 | 4 | calling: id, | 1289 | 4 | value_out_ptr: Some(value_out_ptr), | 1290 | 4 | offset, | 1291 | 4 | max_size: value_out_size, | 1292 | 4 | inner: self.inner, | 1293 | 4 | }) | 1294 | | } | 1295 | | HostFunction::ext_default_child_storage_storage_kill_version_1 => { | 1296 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1297 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1298 | 0 | prefix_ptr_size: None, | 1299 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1300 | 0 | inner: self.inner, | 1301 | 0 | max_keys_to_remove: None, | 1302 | 0 | calling: id, | 1303 | 0 | }) | 1304 | | } | 1305 | | HostFunction::ext_default_child_storage_storage_kill_version_2 | 1306 | | | HostFunction::ext_default_child_storage_storage_kill_version_3 => { | 1307 | 1 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1308 | | | 1309 | 1 | let max_keys_to_remove = { | 1310 | 1 | let input = expect_pointer_size!(1); | 1311 | 1 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = | 1312 | 1 | nom::combinator::all_consuming(util::nom_option_decode( | 1313 | 1 | nom::number::streaming::le_u32, | 1314 | 1 | ))(input.as_ref()) | 1315 | 1 | .map(|(_, parse_result)| parse_result); | 1316 | 1 | | 1317 | 1 | match parsing_result { | 1318 | 1 | Ok(val) => Ok(val), | 1319 | 0 | Err(_) => Err(()), | 1320 | | } | 1321 | | }; | 1322 | | | 1323 | 1 | let max_keys_to_remove = match max_keys_to_remove { | 1324 | 1 | Ok(l) => l, | 1325 | | Err(()) => { | 1326 | 0 | return HostVm::Error { | 1327 | 0 | error: Error::ParamDecodeError, | 1328 | 0 | prototype: self.inner.into_prototype(), | 1329 | 0 | }; | 1330 | | } | 1331 | | }; | 1332 | | | 1333 | 1 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1334 | 1 | prefix_ptr_size: None, | 1335 | 1 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1336 | 1 | inner: self.inner, | 1337 | 1 | max_keys_to_remove, | 1338 | 1 | calling: id, | 1339 | 1 | }) | 1340 | | } | 1341 | | HostFunction::ext_default_child_storage_clear_prefix_version_1 => { | 1342 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1343 | 0 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(1); | 1344 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1345 | 0 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), | 1346 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1347 | 0 | inner: self.inner, | 1348 | 0 | max_keys_to_remove: None, | 1349 | 0 | calling: id, | 1350 | 0 | }) | 1351 | | } | 1352 | | HostFunction::ext_default_child_storage_clear_prefix_version_2 => { | 1353 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1354 | 0 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(1); | 1355 | | | 1356 | 0 | let max_keys_to_remove = { | 1357 | 0 | let input = expect_pointer_size!(2); | 1358 | 0 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = | 1359 | 0 | nom::combinator::all_consuming(util::nom_option_decode( | 1360 | 0 | nom::number::streaming::le_u32, | 1361 | 0 | ))(input.as_ref()) | 1362 | 0 | .map(|(_, parse_result)| parse_result); | 1363 | 0 |
| 1364 | 0 | match parsing_result { | 1365 | 0 | Ok(val) => Ok(val), | 1366 | 0 | Err(_) => Err(()), | 1367 | | } | 1368 | | }; | 1369 | | | 1370 | 0 | let max_keys_to_remove = match max_keys_to_remove { | 1371 | 0 | Ok(l) => l, | 1372 | | Err(()) => { | 1373 | 0 | return HostVm::Error { | 1374 | 0 | error: Error::ParamDecodeError, | 1375 | 0 | prototype: self.inner.into_prototype(), | 1376 | 0 | }; | 1377 | | } | 1378 | | }; | 1379 | | | 1380 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1381 | 0 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), | 1382 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1383 | 0 | inner: self.inner, | 1384 | 0 | max_keys_to_remove, | 1385 | 0 | calling: id, | 1386 | 0 | }) | 1387 | | } | 1388 | | HostFunction::ext_default_child_storage_set_version_1 => { | 1389 | 4 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1390 | 4 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1391 | 4 | let (value_ptr, value_size) = expect_pointer_size_raw!(2); | 1392 | 4 | HostVm::ExternalStorageSet(ExternalStorageSet { | 1393 | 4 | key_ptr, | 1394 | 4 | key_size, | 1395 | 4 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1396 | 4 | value: Some((value_ptr, value_size)), | 1397 | 4 | inner: self.inner, | 1398 | 4 | }) | 1399 | | } | 1400 | | HostFunction::ext_default_child_storage_clear_version_1 => { | 1401 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1402 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1403 | 0 | HostVm::ExternalStorageSet(ExternalStorageSet { | 1404 | 0 | key_ptr, | 1405 | 0 | key_size, | 1406 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1407 | 0 | value: None, | 1408 | 0 | inner: self.inner, | 1409 | 0 | }) | 1410 | | } | 1411 | | HostFunction::ext_default_child_storage_exists_version_1 => { | 1412 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1413 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1414 | 0 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1415 | 0 | key_ptr, | 1416 | 0 | key_size, | 1417 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1418 | 0 | calling: id, | 1419 | 0 | value_out_ptr: None, | 1420 | 0 | offset: 0, | 1421 | 0 | max_size: 0, | 1422 | 0 | inner: self.inner, | 1423 | 0 | }) | 1424 | | } | 1425 | | HostFunction::ext_default_child_storage_next_key_version_1 => { | 1426 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1427 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1428 | 0 | HostVm::ExternalStorageNextKey(ExternalStorageNextKey { | 1429 | 0 | key_ptr, | 1430 | 0 | key_size, | 1431 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1432 | 0 | inner: self.inner, | 1433 | 0 | }) | 1434 | | } | 1435 | | HostFunction::ext_default_child_storage_root_version_1 => { | 1436 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1437 | 0 | HostVm::ExternalStorageRoot(ExternalStorageRoot { | 1438 | 0 | inner: self.inner, | 1439 | 0 | calling: id, | 1440 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1441 | 0 | }) | 1442 | | } | 1443 | | HostFunction::ext_default_child_storage_root_version_2 => { | 1444 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1445 | | | 1446 | | // The `ext_default_child_storage_root_version_2` host function gets passed as | 1447 | | // parameter the state version of the runtime. This is in fact completely | 1448 | | // unnecessary as the same information is found in the runtime specification, and | 1449 | | // this parameter should be considered as a historical accident. We verify that the | 1450 | | // version provided as parameter is the same as the one in the specification. | 1451 | 0 | let version_param = expect_state_version!(1); | 1452 | 0 | let version_spec = self | 1453 | 0 | .inner | 1454 | 0 | .common | 1455 | 0 | .runtime_version | 1456 | 0 | .as_ref() | 1457 | 0 | .unwrap_or_else(|| unreachable!()) | 1458 | 0 | .decode() | 1459 | 0 | .state_version | 1460 | 0 | .unwrap_or(TrieEntryVersion::V0); | 1461 | 0 |
| 1462 | 0 | if version_param != version_spec { | 1463 | 0 | return HostVm::Error { | 1464 | 0 | error: Error::StateVersionMismatch { | 1465 | 0 | parameter: version_param, | 1466 | 0 | specification: version_spec, | 1467 | 0 | }, | 1468 | 0 | prototype: self.inner.into_prototype(), | 1469 | 0 | }; | 1470 | 0 | } | 1471 | 0 |
| 1472 | 0 | HostVm::ExternalStorageRoot(ExternalStorageRoot { | 1473 | 0 | inner: self.inner, | 1474 | 0 | calling: id, | 1475 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1476 | 0 | }) | 1477 | | } | 1478 | 0 | HostFunction::ext_crypto_ed25519_public_keys_version_1 => host_fn_not_implemented!(), | 1479 | 0 | HostFunction::ext_crypto_ed25519_generate_version_1 => host_fn_not_implemented!(), | 1480 | 0 | HostFunction::ext_crypto_ed25519_sign_version_1 => host_fn_not_implemented!(), | 1481 | | HostFunction::ext_crypto_ed25519_verify_version_1 | 1482 | | | HostFunction::ext_crypto_ed25519_batch_verify_version_1 => { | 1483 | 0 | let is_batch_verification = matches!( | 1484 | 0 | host_fn, | 1485 | | HostFunction::ext_crypto_ed25519_batch_verify_version_1 | 1486 | | ); | 1487 | | | 1488 | 0 | if is_batch_verification && self.inner.signatures_batch_verification.is_none() { | 1489 | 0 | return HostVm::Error { | 1490 | 0 | error: Error::BatchVerifyWithoutStarting, | 1491 | 0 | prototype: self.inner.into_prototype(), | 1492 | 0 | }; | 1493 | 0 | } | 1494 | | | 1495 | 0 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); | 1496 | | HostVm::SignatureVerification(SignatureVerification { | 1497 | 0 | algorithm: SignatureVerificationAlgorithm::Ed25519, | 1498 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 64), | 1499 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 32), | 1500 | 0 | message_ptr, | 1501 | 0 | message_size, | 1502 | 0 | inner: self.inner, | 1503 | 0 | is_batch_verification, | 1504 | | }) | 1505 | | } | 1506 | 0 | HostFunction::ext_crypto_sr25519_public_keys_version_1 => host_fn_not_implemented!(), | 1507 | 0 | HostFunction::ext_crypto_sr25519_generate_version_1 => host_fn_not_implemented!(), | 1508 | 0 | HostFunction::ext_crypto_sr25519_sign_version_1 => host_fn_not_implemented!(), | 1509 | | HostFunction::ext_crypto_sr25519_verify_version_1 | 1510 | | | HostFunction::ext_crypto_sr25519_batch_verify_version_1 => { | 1511 | 0 | let is_batch_verification = matches!( | 1512 | 0 | host_fn, | 1513 | | HostFunction::ext_crypto_sr25519_batch_verify_version_1 | 1514 | | ); | 1515 | | | 1516 | 0 | if is_batch_verification && self.inner.signatures_batch_verification.is_none() { | 1517 | 0 | return HostVm::Error { | 1518 | 0 | error: Error::BatchVerifyWithoutStarting, | 1519 | 0 | prototype: self.inner.into_prototype(), | 1520 | 0 | }; | 1521 | 0 | } | 1522 | | | 1523 | 0 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); | 1524 | | HostVm::SignatureVerification(SignatureVerification { | 1525 | 0 | algorithm: SignatureVerificationAlgorithm::Sr25519V1, | 1526 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 64), | 1527 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 32), | 1528 | 0 | message_ptr, | 1529 | 0 | message_size, | 1530 | 0 | inner: self.inner, | 1531 | 0 | is_batch_verification, | 1532 | | }) | 1533 | | } | 1534 | | HostFunction::ext_crypto_sr25519_verify_version_2 => { | 1535 | 6 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); | 1536 | | HostVm::SignatureVerification(SignatureVerification { | 1537 | 6 | algorithm: SignatureVerificationAlgorithm::Sr25519V2, | 1538 | 6 | signature_ptr: expect_pointer_constant_size_raw!(0, 64), | 1539 | 6 | public_key_ptr: expect_pointer_constant_size_raw!(2, 32), | 1540 | 6 | message_ptr, | 1541 | 6 | message_size, | 1542 | 6 | inner: self.inner, | 1543 | | is_batch_verification: false, | 1544 | | }) | 1545 | | } | 1546 | 0 | HostFunction::ext_crypto_ecdsa_generate_version_1 => host_fn_not_implemented!(), | 1547 | | HostFunction::ext_crypto_ecdsa_sign_version_1 => { | 1548 | | // NOTE: safe to unwrap here because we supply the nn to blake2b fn | 1549 | 0 | let data = <[u8; 32]>::try_from( | 1550 | 0 | blake2_rfc::blake2b::blake2b(32, &[], expect_pointer_size!(0).as_ref()) | 1551 | 0 | .as_bytes(), | 1552 | 0 | ) | 1553 | 0 | .unwrap_or_else(|_| unreachable!()); | 1554 | 0 | let message = libsecp256k1::Message::parse(&data); | 1555 | | | 1556 | 0 | if let Ok(sc) = | 1557 | 0 | libsecp256k1::SecretKey::parse(&expect_pointer_constant_size!(1, 32)) | 1558 | | { | 1559 | 0 | let (sig, ri) = libsecp256k1::sign(&message, &sc); | 1560 | 0 |
| 1561 | 0 | // NOTE: the function returns 2 slices: signature (64 bytes) and recovery ID (1 byte; AS A SLICE) | 1562 | 0 | self.inner.alloc_write_and_return_pointer( | 1563 | 0 | host_fn.name(), | 1564 | 0 | [&sig.serialize()[..], &[ri.serialize()]].into_iter(), | 1565 | 0 | ) | 1566 | | } else { | 1567 | 0 | HostVm::Error { | 1568 | 0 | error: Error::ParamDecodeError, | 1569 | 0 | prototype: self.inner.into_prototype(), | 1570 | 0 | } | 1571 | | } | 1572 | | } | 1573 | 0 | HostFunction::ext_crypto_ecdsa_public_keys_version_1 => host_fn_not_implemented!(), | 1574 | | HostFunction::ext_crypto_ecdsa_verify_version_1 | 1575 | | | HostFunction::ext_crypto_ecdsa_batch_verify_version_1 => { | 1576 | 0 | let is_batch_verification = matches!( | 1577 | 0 | host_fn, | 1578 | | HostFunction::ext_crypto_ecdsa_batch_verify_version_1 | 1579 | | ); | 1580 | | | 1581 | 0 | if is_batch_verification && self.inner.signatures_batch_verification.is_none() { | 1582 | 0 | return HostVm::Error { | 1583 | 0 | error: Error::BatchVerifyWithoutStarting, | 1584 | 0 | prototype: self.inner.into_prototype(), | 1585 | 0 | }; | 1586 | 0 | } | 1587 | | | 1588 | 0 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); | 1589 | | HostVm::SignatureVerification(SignatureVerification { | 1590 | 0 | algorithm: SignatureVerificationAlgorithm::Ecdsa, | 1591 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 65), | 1592 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 33), | 1593 | 0 | message_ptr, | 1594 | 0 | message_size, | 1595 | 0 | inner: self.inner, | 1596 | 0 | is_batch_verification, | 1597 | | }) | 1598 | | } | 1599 | 0 | HostFunction::ext_crypto_ecdsa_verify_version_2 => host_fn_not_implemented!(), | 1600 | | HostFunction::ext_crypto_ecdsa_sign_prehashed_version_1 => { | 1601 | | // TODO: seems misimplemented, see https://spec.polkadot.network/#id-ext_crypto_ecdsa_sign_prehashed | 1602 | 0 | let message = libsecp256k1::Message::parse(&expect_pointer_constant_size!(0, 32)); | 1603 | | | 1604 | 0 | if let Ok(sc) = | 1605 | 0 | libsecp256k1::SecretKey::parse(&expect_pointer_constant_size!(1, 32)) | 1606 | | { | 1607 | 0 | let (sig, ri) = libsecp256k1::sign(&message, &sc); | 1608 | 0 |
| 1609 | 0 | // NOTE: the function returns 2 slices: signature (64 bytes) and recovery ID (1 byte; AS A SLICE) | 1610 | 0 | self.inner.alloc_write_and_return_pointer( | 1611 | 0 | host_fn.name(), | 1612 | 0 | [&sig.serialize()[..], &[ri.serialize()]].into_iter(), | 1613 | 0 | ) | 1614 | | } else { | 1615 | 0 | HostVm::Error { | 1616 | 0 | error: Error::ParamDecodeError, | 1617 | 0 | prototype: self.inner.into_prototype(), | 1618 | 0 | } | 1619 | | } | 1620 | | } | 1621 | | HostFunction::ext_crypto_ecdsa_verify_prehashed_version_1 => { | 1622 | | HostVm::SignatureVerification(SignatureVerification { | 1623 | 0 | algorithm: SignatureVerificationAlgorithm::EcdsaPrehashed, | 1624 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 65), | 1625 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 33), | 1626 | 0 | message_ptr: expect_pointer_constant_size_raw!(1, 32), | 1627 | | message_size: 32, | 1628 | 0 | inner: self.inner, | 1629 | | is_batch_verification: false, | 1630 | | }) | 1631 | | } | 1632 | | | 1633 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_version_1 | 1634 | | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_version_2 => { | 1635 | 0 | let sig = expect_pointer_constant_size!(0, 65); | 1636 | 0 | let msg = expect_pointer_constant_size!(1, 32); | 1637 | 0 | let is_v2 = matches!( | 1638 | 0 | host_fn, | 1639 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_version_2 | 1640 | | ); | 1641 | | | 1642 | 0 | let result = { | 1643 | 0 | let rs = if is_v2 { | 1644 | 0 | libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) | 1645 | | } else { | 1646 | 0 | libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64]) | 1647 | | }; | 1648 | | | 1649 | 0 | if let Ok(rs) = rs { | 1650 | 0 | let v = libsecp256k1::RecoveryId::parse(if sig[64] > 26 { | 1651 | 0 | sig[64] - 27 | 1652 | | } else { | 1653 | 0 | sig[64] | 1654 | | }); | 1655 | | | 1656 | 0 | if let Ok(v) = v { | 1657 | 0 | let pubkey = libsecp256k1::recover( | 1658 | 0 | &libsecp256k1::Message::parse_slice(&msg) | 1659 | 0 | .unwrap_or_else(|_| unreachable!()), | 1660 | 0 | &rs, | 1661 | 0 | &v, | 1662 | 0 | ); | 1663 | | | 1664 | 0 | if let Ok(pubkey) = pubkey { | 1665 | 0 | let mut res = Vec::with_capacity(65); | 1666 | 0 | res.push(0); | 1667 | 0 | res.extend_from_slice(&pubkey.serialize()[1..65]); | 1668 | 0 | res | 1669 | | } else { | 1670 | 0 | vec![1, 2] | 1671 | | } | 1672 | | } else { | 1673 | 0 | vec![1, 1] | 1674 | | } | 1675 | | } else { | 1676 | 0 | vec![1, 0] | 1677 | | } | 1678 | | }; | 1679 | | | 1680 | 0 | self.inner | 1681 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&result)) | 1682 | | } | 1683 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_compressed_version_1 | 1684 | | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_compressed_version_2 => { | 1685 | 0 | let sig = expect_pointer_constant_size!(0, 65); | 1686 | 0 | let msg = expect_pointer_constant_size!(1, 32); | 1687 | 0 | let is_v2 = matches!( | 1688 | 0 | host_fn, | 1689 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_compressed_version_2 | 1690 | | ); | 1691 | | | 1692 | 0 | let result = { | 1693 | 0 | let rs = if is_v2 { | 1694 | 0 | libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) | 1695 | | } else { | 1696 | 0 | libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64]) | 1697 | | }; | 1698 | | | 1699 | 0 | if let Ok(rs) = rs { | 1700 | 0 | let v = libsecp256k1::RecoveryId::parse(if sig[64] > 26 { | 1701 | 0 | sig[64] - 27 | 1702 | | } else { | 1703 | 0 | sig[64] | 1704 | | }); | 1705 | | | 1706 | 0 | if let Ok(v) = v { | 1707 | 0 | let pubkey = libsecp256k1::recover( | 1708 | 0 | &libsecp256k1::Message::parse_slice(&msg) | 1709 | 0 | .unwrap_or_else(|_| unreachable!()), | 1710 | 0 | &rs, | 1711 | 0 | &v, | 1712 | 0 | ); | 1713 | | | 1714 | 0 | if let Ok(pubkey) = pubkey { | 1715 | 0 | let mut res = Vec::with_capacity(34); | 1716 | 0 | res.push(0); | 1717 | 0 | res.extend_from_slice(&pubkey.serialize_compressed()); | 1718 | 0 | res | 1719 | | } else { | 1720 | 0 | vec![1, 2] | 1721 | | } | 1722 | | } else { | 1723 | 0 | vec![1, 1] | 1724 | | } | 1725 | | } else { | 1726 | 0 | vec![1, 0] | 1727 | | } | 1728 | | }; | 1729 | | | 1730 | 0 | self.inner | 1731 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&result)) | 1732 | | } | 1733 | | HostFunction::ext_crypto_start_batch_verify_version_1 => { | 1734 | 4 | if self.inner.signatures_batch_verification.is_some() { | 1735 | 0 | return HostVm::Error { | 1736 | 0 | error: Error::AlreadyBatchVerify, | 1737 | 0 | prototype: self.inner.into_prototype(), | 1738 | 0 | }; | 1739 | 4 | } | 1740 | 4 | | 1741 | 4 | self.inner.signatures_batch_verification = Some(true); | 1742 | 4 | | 1743 | 4 | HostVm::ReadyToRun(ReadyToRun { | 1744 | 4 | resume_value: None, | 1745 | 4 | inner: self.inner, | 1746 | 4 | }) | 1747 | | } | 1748 | | HostFunction::ext_crypto_finish_batch_verify_version_1 => { | 1749 | 4 | let Some(outcome) = self.inner.signatures_batch_verification.take() else { | 1750 | 0 | return HostVm::Error { | 1751 | 0 | error: Error::NoBatchVerify, | 1752 | 0 | prototype: self.inner.into_prototype(), | 1753 | 0 | }; | 1754 | | }; | 1755 | | | 1756 | | HostVm::ReadyToRun(ReadyToRun { | 1757 | 4 | resume_value: Some(vm::WasmValue::I32(if outcome { 1 } else { 00 })), | 1758 | 4 | inner: self.inner, | 1759 | | }) | 1760 | | } | 1761 | | HostFunction::ext_hashing_keccak_256_version_1 => { | 1762 | 2 | let hash = | 1763 | 2 | <sha3::Keccak256 as sha3::Digest>::digest(expect_pointer_size!(0).as_ref()); | 1764 | 2 | self.inner | 1765 | 2 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash)) | 1766 | | } | 1767 | | HostFunction::ext_hashing_keccak_512_version_1 => { | 1768 | 2 | let hash = | 1769 | 2 | <sha3::Keccak512 as sha3::Digest>::digest(expect_pointer_size!(0).as_ref()); | 1770 | 2 | self.inner | 1771 | 2 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash)) | 1772 | | } | 1773 | | HostFunction::ext_hashing_sha2_256_version_1 => { | 1774 | 2 | let hash = <sha2::Sha256 as sha2::Digest>::digest(expect_pointer_size!(0).as_ref()); | 1775 | 2 | self.inner | 1776 | 2 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash)) | 1777 | | } | 1778 | | HostFunction::ext_hashing_blake2_128_version_1 => { | 1779 | 148 | let out = { | 1780 | 148 | let data = expect_pointer_size!(0); | 1781 | 148 | blake2_rfc::blake2b::blake2b(16, &[], data.as_ref()) | 1782 | 148 | }; | 1783 | 148 | | 1784 | 148 | self.inner | 1785 | 148 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(out.as_bytes())) | 1786 | | } | 1787 | | HostFunction::ext_hashing_blake2_256_version_1 => { | 1788 | 30 | let out = { | 1789 | 30 | let data = expect_pointer_size!(0); | 1790 | 30 | blake2_rfc::blake2b::blake2b(32, &[], data.as_ref()) | 1791 | 30 | }; | 1792 | 30 | | 1793 | 30 | self.inner | 1794 | 30 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(out.as_bytes())) | 1795 | | } | 1796 | | HostFunction::ext_hashing_twox_64_version_1 => { | 1797 | 67 | let mut h0 = twox_hash::XxHash::with_seed(0); | 1798 | 67 | { | 1799 | 67 | let data = expect_pointer_size!(0); | 1800 | 67 | h0.write(data.as_ref()); | 1801 | 67 | } | 1802 | 67 | let r0 = h0.finish(); | 1803 | 67 | | 1804 | 67 | self.inner | 1805 | 67 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&r0.to_le_bytes())) | 1806 | | } | 1807 | | HostFunction::ext_hashing_twox_128_version_1 => { | 1808 | 1.73k | let mut h0 = twox_hash::XxHash::with_seed(0); | 1809 | 1.73k | let mut h1 = twox_hash::XxHash::with_seed(1); | 1810 | 1.73k | { | 1811 | 1.73k | let data = expect_pointer_size!(0); | 1812 | 1.73k | let data = data.as_ref(); | 1813 | 1.73k | h0.write(data); | 1814 | 1.73k | h1.write(data); | 1815 | 1.73k | } | 1816 | 1.73k | let r0 = h0.finish(); | 1817 | 1.73k | let r1 = h1.finish(); | 1818 | 1.73k | | 1819 | 1.73k | self.inner.alloc_write_and_return_pointer( | 1820 | 1.73k | host_fn.name(), | 1821 | 1.73k | iter::once(&r0.to_le_bytes()).chain(iter::once(&r1.to_le_bytes())), | 1822 | 1.73k | ) | 1823 | | } | 1824 | | HostFunction::ext_hashing_twox_256_version_1 => { | 1825 | 2 | let mut h0 = twox_hash::XxHash::with_seed(0); | 1826 | 2 | let mut h1 = twox_hash::XxHash::with_seed(1); | 1827 | 2 | let mut h2 = twox_hash::XxHash::with_seed(2); | 1828 | 2 | let mut h3 = twox_hash::XxHash::with_seed(3); | 1829 | 2 | { | 1830 | 2 | let data = expect_pointer_size!(0); | 1831 | 2 | let data = data.as_ref(); | 1832 | 2 | h0.write(data); | 1833 | 2 | h1.write(data); | 1834 | 2 | h2.write(data); | 1835 | 2 | h3.write(data); | 1836 | 2 | } | 1837 | 2 | let r0 = h0.finish(); | 1838 | 2 | let r1 = h1.finish(); | 1839 | 2 | let r2 = h2.finish(); | 1840 | 2 | let r3 = h3.finish(); | 1841 | 2 | | 1842 | 2 | self.inner.alloc_write_and_return_pointer( | 1843 | 2 | host_fn.name(), | 1844 | 2 | iter::once(&r0.to_le_bytes()) | 1845 | 2 | .chain(iter::once(&r1.to_le_bytes())) | 1846 | 2 | .chain(iter::once(&r2.to_le_bytes())) | 1847 | 2 | .chain(iter::once(&r3.to_le_bytes())), | 1848 | 2 | ) | 1849 | | } | 1850 | | HostFunction::ext_offchain_index_set_version_1 => { | 1851 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1852 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(1); | 1853 | 0 | HostVm::ExternalOffchainIndexSet(ExternalOffchainIndexSet { | 1854 | 0 | key_ptr, | 1855 | 0 | key_size, | 1856 | 0 | value: Some((value_ptr, value_size)), | 1857 | 0 | inner: self.inner, | 1858 | 0 | }) | 1859 | | } | 1860 | | HostFunction::ext_offchain_index_clear_version_1 => { | 1861 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1862 | 0 | HostVm::ExternalOffchainIndexSet(ExternalOffchainIndexSet { | 1863 | 0 | key_ptr, | 1864 | 0 | key_size, | 1865 | 0 | value: None, | 1866 | 0 | inner: self.inner, | 1867 | 0 | }) | 1868 | | } | 1869 | 0 | HostFunction::ext_offchain_is_validator_version_1 => HostVm::ReadyToRun(ReadyToRun { | 1870 | 0 | inner: self.inner, | 1871 | 0 | resume_value: Some(vm::WasmValue::I32(1)), // TODO: ask the API user | 1872 | 0 | }), | 1873 | | HostFunction::ext_offchain_submit_transaction_version_1 => { | 1874 | 0 | let (tx_ptr, tx_size) = expect_pointer_size_raw!(0); | 1875 | 0 | HostVm::OffchainSubmitTransaction(OffchainSubmitTransaction { | 1876 | 0 | inner: self.inner, | 1877 | 0 | calling: id, | 1878 | 0 | tx_ptr, | 1879 | 0 | tx_size, | 1880 | 0 | }) | 1881 | | } | 1882 | | HostFunction::ext_offchain_network_state_version_1 => { | 1883 | 0 | host_fn_not_implemented!() | 1884 | | } | 1885 | | HostFunction::ext_offchain_timestamp_version_1 => { | 1886 | 0 | HostVm::OffchainTimestamp(OffchainTimestamp { inner: self.inner }) | 1887 | | } | 1888 | | HostFunction::ext_offchain_sleep_until_version_1 => { | 1889 | 0 | host_fn_not_implemented!() | 1890 | | } | 1891 | | HostFunction::ext_offchain_random_seed_version_1 => { | 1892 | 0 | HostVm::OffchainRandomSeed(OffchainRandomSeed { | 1893 | 0 | inner: self.inner, | 1894 | 0 | calling: id, | 1895 | 0 | }) | 1896 | | } | 1897 | | HostFunction::ext_offchain_local_storage_set_version_1 => { | 1898 | 0 | if expect_offchain_storage_kind!(0) { | 1899 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1900 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(2); | 1901 | 0 | HostVm::ExternalOffchainStorageSet(ExternalOffchainStorageSet { | 1902 | 0 | key_ptr, | 1903 | 0 | key_size, | 1904 | 0 | value: Some((value_ptr, value_size)), | 1905 | 0 | old_value: None, | 1906 | 0 | inner: self.inner, | 1907 | 0 | }) | 1908 | | } else { | 1909 | 0 | HostVm::ReadyToRun(ReadyToRun { | 1910 | 0 | inner: self.inner, | 1911 | 0 | resume_value: None, | 1912 | 0 | }) | 1913 | | } | 1914 | | } | 1915 | | HostFunction::ext_offchain_local_storage_compare_and_set_version_1 => { | 1916 | 0 | if expect_offchain_storage_kind!(0) { | 1917 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1918 | 0 | let (old_value_ptr, old_value_size) = expect_pointer_size_raw!(2); | 1919 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(3); | 1920 | 0 | HostVm::ExternalOffchainStorageSet(ExternalOffchainStorageSet { | 1921 | 0 | key_ptr, | 1922 | 0 | key_size, | 1923 | 0 | value: Some((value_ptr, value_size)), | 1924 | 0 | old_value: Some((old_value_ptr, old_value_size)), | 1925 | 0 | inner: self.inner, | 1926 | 0 | }) | 1927 | | } else { | 1928 | 0 | HostVm::ReadyToRun(ReadyToRun { | 1929 | 0 | inner: self.inner, | 1930 | 0 | resume_value: Some(vm::WasmValue::I32(0)), | 1931 | 0 | }) | 1932 | | } | 1933 | | } | 1934 | | HostFunction::ext_offchain_local_storage_get_version_1 => { | 1935 | 0 | if expect_offchain_storage_kind!(0) { | 1936 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1937 | 0 | HostVm::ExternalOffchainStorageGet(ExternalOffchainStorageGet { | 1938 | 0 | key_ptr, | 1939 | 0 | key_size, | 1940 | 0 | calling: id, | 1941 | 0 | inner: self.inner, | 1942 | 0 | }) | 1943 | | } else { | 1944 | | // Write a SCALE-encoded `None`. | 1945 | 0 | self.inner | 1946 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&[0])) | 1947 | | } | 1948 | | } | 1949 | | HostFunction::ext_offchain_local_storage_clear_version_1 => { | 1950 | 0 | if expect_offchain_storage_kind!(0) { | 1951 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1952 | 0 | HostVm::ExternalOffchainStorageSet(ExternalOffchainStorageSet { | 1953 | 0 | key_ptr, | 1954 | 0 | key_size, | 1955 | 0 | value: None, | 1956 | 0 | old_value: None, | 1957 | 0 | inner: self.inner, | 1958 | 0 | }) | 1959 | | } else { | 1960 | 0 | HostVm::ReadyToRun(ReadyToRun { | 1961 | 0 | inner: self.inner, | 1962 | 0 | resume_value: None, | 1963 | 0 | }) | 1964 | | } | 1965 | | } | 1966 | 0 | HostFunction::ext_offchain_http_request_start_version_1 => host_fn_not_implemented!(), | 1967 | | HostFunction::ext_offchain_http_request_add_header_version_1 => { | 1968 | 0 | host_fn_not_implemented!() | 1969 | | } | 1970 | | HostFunction::ext_offchain_http_request_write_body_version_1 => { | 1971 | 0 | host_fn_not_implemented!() | 1972 | | } | 1973 | 0 | HostFunction::ext_offchain_http_response_wait_version_1 => host_fn_not_implemented!(), | 1974 | | HostFunction::ext_offchain_http_response_headers_version_1 => { | 1975 | 0 | host_fn_not_implemented!() | 1976 | | } | 1977 | | HostFunction::ext_offchain_http_response_read_body_version_1 => { | 1978 | 0 | host_fn_not_implemented!() | 1979 | | } | 1980 | | HostFunction::ext_trie_blake2_256_root_version_1 | 1981 | | | HostFunction::ext_trie_blake2_256_root_version_2 | 1982 | | | HostFunction::ext_trie_keccak_256_root_version_1 | 1983 | | | HostFunction::ext_trie_keccak_256_root_version_2 => { | 1984 | 0 | let state_version = if matches!( | 1985 | 0 | host_fn, | 1986 | | HostFunction::ext_trie_blake2_256_root_version_2 | 1987 | | | HostFunction::ext_trie_keccak_256_root_version_2 | 1988 | | ) { | 1989 | 0 | expect_state_version!(1) | 1990 | | } else { | 1991 | 0 | TrieEntryVersion::V0 | 1992 | | }; | 1993 | | | 1994 | 0 | let result = { | 1995 | 0 | let input = expect_pointer_size!(0); | 1996 | 0 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = | 1997 | 0 | nom::combinator::all_consuming(nom::combinator::flat_map( | 1998 | 0 | crate::util::nom_scale_compact_usize, | 1999 | 0 | |num_elems| { | 2000 | | nom::multi::many_m_n( | 2001 | | num_elems, | 2002 | | num_elems, | 2003 | | nom::sequence::tuple(( | 2004 | | nom::combinator::flat_map( | 2005 | | crate::util::nom_scale_compact_usize, | 2006 | | nom::bytes::streaming::take, | 2007 | | ), | 2008 | | nom::combinator::flat_map( | 2009 | | crate::util::nom_scale_compact_usize, | 2010 | | nom::bytes::streaming::take, | 2011 | | ), | 2012 | | )), | 2013 | | ) | 2014 | 0 | }, | 2015 | 0 | ))(input.as_ref()) | 2016 | 0 | .map(|(_, parse_result)| parse_result); | 2017 | 0 |
| 2018 | 0 | match parsing_result { | 2019 | 0 | Ok(elements) => Ok(trie::trie_root( | 2020 | 0 | state_version, | 2021 | 0 | if matches!( | 2022 | 0 | host_fn, | 2023 | | HostFunction::ext_trie_blake2_256_root_version_1 | 2024 | | | HostFunction::ext_trie_blake2_256_root_version_2 | 2025 | | ) { | 2026 | 0 | trie::HashFunction::Blake2 | 2027 | | } else { | 2028 | 0 | trie::HashFunction::Keccak256 | 2029 | | }, | 2030 | 0 | &elements[..], | 2031 | | )), | 2032 | 0 | Err(_) => Err(()), | 2033 | | } | 2034 | | }; | 2035 | | | 2036 | 0 | match result { | 2037 | 0 | Ok(out) => self | 2038 | 0 | .inner | 2039 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&out)), | 2040 | 0 | Err(()) => HostVm::Error { | 2041 | 0 | error: Error::ParamDecodeError, | 2042 | 0 | prototype: self.inner.into_prototype(), | 2043 | 0 | }, | 2044 | | } | 2045 | | } | 2046 | | HostFunction::ext_trie_blake2_256_ordered_root_version_1 | 2047 | | | HostFunction::ext_trie_blake2_256_ordered_root_version_2 | 2048 | | | HostFunction::ext_trie_keccak_256_ordered_root_version_1 | 2049 | | | HostFunction::ext_trie_keccak_256_ordered_root_version_2 => { | 2050 | 5 | let state_version = if matches!1 ( | 2051 | 5 | host_fn, | 2052 | | HostFunction::ext_trie_blake2_256_ordered_root_version_2 | 2053 | | | HostFunction::ext_trie_keccak_256_ordered_root_version_2 | 2054 | | ) { | 2055 | 4 | expect_state_version!(1) | 2056 | | } else { | 2057 | 1 | TrieEntryVersion::V0 | 2058 | | }; | 2059 | | | 2060 | 5 | let result = { | 2061 | 5 | let input = expect_pointer_size!(0); | 2062 | 5 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = | 2063 | 5 | nom::combinator::all_consuming(nom::combinator::flat_map( | 2064 | 5 | crate::util::nom_scale_compact_usize, | 2065 | 5 | |num_elems| { | 2066 | | nom::multi::many_m_n( | 2067 | | num_elems, | 2068 | | num_elems, | 2069 | | nom::combinator::flat_map( | 2070 | | crate::util::nom_scale_compact_usize, | 2071 | | nom::bytes::streaming::take, | 2072 | | ), | 2073 | | ) | 2074 | 5 | }, | 2075 | 5 | ))(input.as_ref()) | 2076 | 5 | .map(|(_, parse_result)| parse_result); | 2077 | 5 | | 2078 | 5 | match parsing_result { | 2079 | 5 | Ok(elements) => Ok(trie::ordered_root( | 2080 | 5 | state_version, | 2081 | 0 | if matches!( | 2082 | 5 | host_fn, | 2083 | | HostFunction::ext_trie_blake2_256_ordered_root_version_1 | 2084 | | | HostFunction::ext_trie_blake2_256_ordered_root_version_2 | 2085 | | ) { | 2086 | 5 | trie::HashFunction::Blake2 | 2087 | | } else { | 2088 | 0 | trie::HashFunction::Keccak256 | 2089 | | }, | 2090 | 5 | &elements[..], | 2091 | | )), | 2092 | 0 | Err(_) => Err(()), | 2093 | | } | 2094 | | }; | 2095 | | | 2096 | 5 | match result { | 2097 | 5 | Ok(out) => self | 2098 | 5 | .inner | 2099 | 5 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&out)), | 2100 | 0 | Err(()) => HostVm::Error { | 2101 | 0 | error: Error::ParamDecodeError, | 2102 | 0 | prototype: self.inner.into_prototype(), | 2103 | 0 | }, | 2104 | | } | 2105 | | } | 2106 | 0 | HostFunction::ext_trie_blake2_256_verify_proof_version_1 => host_fn_not_implemented!(), | 2107 | 0 | HostFunction::ext_trie_blake2_256_verify_proof_version_2 => host_fn_not_implemented!(), | 2108 | 0 | HostFunction::ext_trie_keccak_256_verify_proof_version_1 => host_fn_not_implemented!(), | 2109 | 0 | HostFunction::ext_trie_keccak_256_verify_proof_version_2 => host_fn_not_implemented!(), | 2110 | | HostFunction::ext_misc_print_num_version_1 => { | 2111 | 0 | let num = match params[0] { | 2112 | 0 | vm::WasmValue::I64(v) => u64::from_ne_bytes(v.to_ne_bytes()), | 2113 | | // The signatures are checked at initialization and the Wasm VM ensures that | 2114 | | // the proper parameter types are provided. | 2115 | 0 | _ => unreachable!(), | 2116 | | }; | 2117 | | | 2118 | 0 | HostVm::LogEmit(LogEmit { | 2119 | 0 | inner: self.inner, | 2120 | 0 | log_entry: LogEmitInner::Num(num), | 2121 | 0 | }) | 2122 | | } | 2123 | | HostFunction::ext_misc_print_utf8_version_1 => { | 2124 | 0 | let (str_ptr, str_size) = expect_pointer_size_raw!(0); | 2125 | | | 2126 | 0 | let utf8_check = str::from_utf8( | 2127 | 0 | self.inner | 2128 | 0 | .vm | 2129 | 0 | .read_memory(str_ptr, str_size) | 2130 | 0 | .unwrap_or_else(|_| unreachable!()) | 2131 | 0 | .as_ref(), | 2132 | 0 | ) | 2133 | 0 | .map(|_| ()); | 2134 | 0 | if let Err(error) = utf8_check { | 2135 | 0 | return HostVm::Error { | 2136 | 0 | error: Error::Utf8Error { | 2137 | 0 | function: host_fn.name(), | 2138 | 0 | param_num: 2, | 2139 | 0 | error, | 2140 | 0 | }, | 2141 | 0 | prototype: self.inner.into_prototype(), | 2142 | 0 | }; | 2143 | 0 | } | 2144 | 0 |
| 2145 | 0 | HostVm::LogEmit(LogEmit { | 2146 | 0 | inner: self.inner, | 2147 | 0 | log_entry: LogEmitInner::Utf8 { str_ptr, str_size }, | 2148 | 0 | }) | 2149 | | } | 2150 | | HostFunction::ext_misc_print_hex_version_1 => { | 2151 | 0 | let (data_ptr, data_size) = expect_pointer_size_raw!(0); | 2152 | 0 | HostVm::LogEmit(LogEmit { | 2153 | 0 | inner: self.inner, | 2154 | 0 | log_entry: LogEmitInner::Hex { | 2155 | 0 | data_ptr, | 2156 | 0 | data_size, | 2157 | 0 | }, | 2158 | 0 | }) | 2159 | | } | 2160 | | HostFunction::ext_misc_runtime_version_version_1 => { | 2161 | 0 | let (wasm_blob_ptr, wasm_blob_size) = expect_pointer_size_raw!(0); | 2162 | 0 | HostVm::CallRuntimeVersion(CallRuntimeVersion { | 2163 | 0 | inner: self.inner, | 2164 | 0 | wasm_blob_ptr, | 2165 | 0 | wasm_blob_size, | 2166 | 0 | }) | 2167 | | } | 2168 | | HostFunction::ext_allocator_malloc_version_1 => { | 2169 | 11.7k | let size = expect_u32!(0); | 2170 | | | 2171 | 11.7k | let ptr = match self.inner.alloc(host_fn.name(), size) { | 2172 | 11.7k | Ok(p) => p, | 2173 | 0 | Err(error) => { | 2174 | 0 | return HostVm::Error { | 2175 | 0 | error, | 2176 | 0 | prototype: self.inner.into_prototype(), | 2177 | 0 | } | 2178 | | } | 2179 | | }; | 2180 | | | 2181 | 11.7k | let ptr_i32 = i32::from_ne_bytes(ptr.to_ne_bytes()); | 2182 | 11.7k | HostVm::ReadyToRun(ReadyToRun { | 2183 | 11.7k | resume_value: Some(vm::WasmValue::I32(ptr_i32)), | 2184 | 11.7k | inner: self.inner, | 2185 | 11.7k | }) | 2186 | | } | 2187 | | HostFunction::ext_allocator_free_version_1 => { | 2188 | 14.3k | let pointer = expect_u32!(0); | 2189 | 14.3k | match self.inner.allocator.deallocate( | 2190 | 14.3k | &mut MemAccess { | 2191 | 14.3k | vm: MemAccessVm::Running(&mut self.inner.vm), | 2192 | 14.3k | memory_total_pages: self.inner.common.memory_total_pages, | 2193 | 14.3k | }, | 2194 | 14.3k | pointer, | 2195 | 14.3k | ) { | 2196 | 14.3k | Ok(()) => {} | 2197 | | Err(_) => { | 2198 | 0 | return HostVm::Error { | 2199 | 0 | error: Error::FreeError { pointer }, | 2200 | 0 | prototype: self.inner.into_prototype(), | 2201 | 0 | } | 2202 | | } | 2203 | | }; | 2204 | | | 2205 | 14.3k | HostVm::ReadyToRun(ReadyToRun { | 2206 | 14.3k | resume_value: None, | 2207 | 14.3k | inner: self.inner, | 2208 | 14.3k | }) | 2209 | | } | 2210 | | HostFunction::ext_logging_log_version_1 => { | 2211 | 0 | let log_level = expect_u32!(0); | 2212 | | | 2213 | 0 | let (target_str_ptr, target_str_size) = expect_pointer_size_raw!(1); | 2214 | 0 | let target_utf8_check = str::from_utf8( | 2215 | 0 | self.inner | 2216 | 0 | .vm | 2217 | 0 | .read_memory(target_str_ptr, target_str_size) | 2218 | 0 | .unwrap_or_else(|_| unreachable!()) | 2219 | 0 | .as_ref(), | 2220 | 0 | ) | 2221 | 0 | .map(|_| ()); | 2222 | 0 | if let Err(error) = target_utf8_check { | 2223 | 0 | return HostVm::Error { | 2224 | 0 | error: Error::Utf8Error { | 2225 | 0 | function: host_fn.name(), | 2226 | 0 | param_num: 1, | 2227 | 0 | error, | 2228 | 0 | }, | 2229 | 0 | prototype: self.inner.into_prototype(), | 2230 | 0 | }; | 2231 | 0 | } | 2232 | | | 2233 | 0 | let (msg_str_ptr, msg_str_size) = expect_pointer_size_raw!(2); | 2234 | 0 | let msg_utf8_check = str::from_utf8( | 2235 | 0 | self.inner | 2236 | 0 | .vm | 2237 | 0 | .read_memory(msg_str_ptr, msg_str_size) | 2238 | 0 | .unwrap_or_else(|_| unreachable!()) | 2239 | 0 | .as_ref(), | 2240 | 0 | ) | 2241 | 0 | .map(|_| ()); | 2242 | 0 | if let Err(error) = msg_utf8_check { | 2243 | 0 | return HostVm::Error { | 2244 | 0 | error: Error::Utf8Error { | 2245 | 0 | function: host_fn.name(), | 2246 | 0 | param_num: 2, | 2247 | 0 | error, | 2248 | 0 | }, | 2249 | 0 | prototype: self.inner.into_prototype(), | 2250 | 0 | }; | 2251 | 0 | } | 2252 | 0 |
| 2253 | 0 | HostVm::LogEmit(LogEmit { | 2254 | 0 | inner: self.inner, | 2255 | 0 | log_entry: LogEmitInner::Log { | 2256 | 0 | log_level, | 2257 | 0 | target_str_ptr, | 2258 | 0 | target_str_size, | 2259 | 0 | msg_str_ptr, | 2260 | 0 | msg_str_size, | 2261 | 0 | }, | 2262 | 0 | }) | 2263 | | } | 2264 | | HostFunction::ext_logging_max_level_version_1 => { | 2265 | 9 | HostVm::GetMaxLogLevel(GetMaxLogLevel { inner: self.inner }) | 2266 | | } | 2267 | | HostFunction::ext_panic_handler_abort_on_panic_version_1 => { | 2268 | 0 | let message = { | 2269 | 0 | let message_bytes = expect_pointer_size!(0); | 2270 | 0 | str::from_utf8(message_bytes.as_ref()).map(|msg| msg.to_owned()) | 2271 | 0 | }; | 2272 | 0 |
| 2273 | 0 | match message { | 2274 | 0 | Ok(message) => HostVm::Error { | 2275 | 0 | error: Error::AbortOnPanic { message }, | 2276 | 0 | prototype: self.inner.into_prototype(), | 2277 | 0 | }, | 2278 | 0 | Err(error) => HostVm::Error { | 2279 | 0 | error: Error::Utf8Error { | 2280 | 0 | function: host_fn.name(), | 2281 | 0 | param_num: 0, | 2282 | 0 | error, | 2283 | 0 | }, | 2284 | 0 | prototype: self.inner.into_prototype(), | 2285 | 0 | }, | 2286 | | } | 2287 | | } | 2288 | | } | 2289 | 29.2k | } |
_RNvMs2_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_10ReadyToRun8run_once Line | Count | Source | 749 | 5.20k | fn run_once(mut self) -> HostVm { | 750 | | // `vm::ExecOutcome::Interrupted` is by far the variant that requires the most | 751 | | // handling code. As such, special-case all other variants before. | 752 | 5.20k | let (id, params5.07k ) = match self.inner.vm.run(self.resume_value) { | 753 | 5.07k | Ok(vm::ExecOutcome::Interrupted { id, params }) => (id, params), | 754 | | | 755 | | Ok(vm::ExecOutcome::Finished { | 756 | 127 | return_value: Ok(Some(vm::WasmValue::I64(ret))), | 757 | 127 | }) => { | 758 | 127 | // Wasm virtual machine has successfully returned. | 759 | 127 | | 760 | 127 | if self.inner.storage_transaction_depth > 0 { | 761 | 0 | return HostVm::Error { | 762 | 0 | prototype: self.inner.into_prototype(), | 763 | 0 | error: Error::FinishedWithPendingTransaction, | 764 | 0 | }; | 765 | 127 | } | 766 | 127 | | 767 | 127 | // Turn the `i64` into a `u64`, not changing any bit. | 768 | 127 | let ret = u64::from_ne_bytes(ret.to_ne_bytes()); | 769 | 127 | | 770 | 127 | // According to the runtime environment specification, the return value is two | 771 | 127 | // consecutive I32s representing the length and size of the SCALE-encoded | 772 | 127 | // return value. | 773 | 127 | let value_size = u32::try_from(ret >> 32).unwrap_or_else(|_| unreachable!()); | 774 | 127 | let value_ptr = u32::try_from(ret & 0xffff_ffff).unwrap_or_else(|_| unreachable!()); | 775 | 127 | | 776 | 127 | if value_size.saturating_add(value_ptr) | 777 | 127 | <= u32::from(self.inner.vm.memory_size()) * 64 * 1024 | 778 | | { | 779 | 127 | return HostVm::Finished(Finished { | 780 | 127 | inner: self.inner, | 781 | 127 | value_ptr, | 782 | 127 | value_size, | 783 | 127 | }); | 784 | 0 | } | 785 | 0 | let error = Error::ReturnedPtrOutOfRange { | 786 | 0 | pointer: value_ptr, | 787 | 0 | size: value_size, | 788 | 0 | memory_size: u32::from(self.inner.vm.memory_size()) * 64 * 1024, | 789 | 0 | }; | 790 | 0 |
| 791 | 0 | return HostVm::Error { | 792 | 0 | prototype: self.inner.into_prototype(), | 793 | 0 | error, | 794 | 0 | }; | 795 | | } | 796 | | | 797 | | Ok(vm::ExecOutcome::Finished { | 798 | 0 | return_value: Ok(return_value), | 799 | 0 | }) => { | 800 | 0 | // The Wasm function has successfully returned, but the specs require that it | 801 | 0 | // returns a `i64`. | 802 | 0 | return HostVm::Error { | 803 | 0 | prototype: self.inner.into_prototype(), | 804 | 0 | error: Error::BadReturnValue { | 805 | 0 | actual: return_value.map(|v| v.ty()), | 806 | 0 | }, | 807 | 0 | }; | 808 | | } | 809 | | | 810 | | Ok(vm::ExecOutcome::Finished { | 811 | 0 | return_value: Err(err), | 812 | 0 | }) => { | 813 | 0 | return HostVm::Error { | 814 | 0 | error: Error::Trap(err), | 815 | 0 | prototype: self.inner.into_prototype(), | 816 | 0 | } | 817 | | } | 818 | | | 819 | | Err(vm::RunErr::BadValueTy { .. }) => { | 820 | | // Tried to inject back the value returned by a host function, but it doesn't | 821 | | // match what the Wasm code expects. Given that we check the host function | 822 | | // signatures at initialization, this indicates a bug in this implementation. | 823 | 0 | unreachable!() | 824 | | } | 825 | | | 826 | | Err(vm::RunErr::Poisoned) => { | 827 | | // Can only happen if there's a bug somewhere. | 828 | 0 | unreachable!() | 829 | | } | 830 | | }; | 831 | | | 832 | | // The Wasm code has called an host_fn. The `id` is a value that we passed | 833 | | // at initialization, and corresponds to an index in `registered_functions`. | 834 | 5.07k | let host_fn = match self.inner.common.registered_functions.get(id) { | 835 | 5.07k | Some(FunctionImport::Resolved(f)) => *f, | 836 | 0 | Some(FunctionImport::Unresolved { name, module }) => { | 837 | 0 | return HostVm::Error { | 838 | 0 | error: Error::UnresolvedFunctionCalled { | 839 | 0 | function: name.clone(), | 840 | 0 | module_name: module.clone(), | 841 | 0 | }, | 842 | 0 | prototype: self.inner.into_prototype(), | 843 | 0 | }; | 844 | | } | 845 | 0 | None => unreachable!(), | 846 | | }; | 847 | | | 848 | | // Passed a parameter index. Produces an `impl AsRef<[u8]>`. | 849 | | macro_rules! expect_pointer_size { | 850 | | ($num:expr) => {{ | 851 | | let val = match ¶ms[$num] { | 852 | | vm::WasmValue::I64(v) => u64::from_ne_bytes(v.to_ne_bytes()), | 853 | | // The signatures are checked at initialization and the Wasm VM ensures that | 854 | | // the proper parameter types are provided. | 855 | | _ => unreachable!(), | 856 | | }; | 857 | | | 858 | | let len = u32::try_from(val >> 32).unwrap_or_else(|_| unreachable!()); | 859 | | let ptr = u32::try_from(val & 0xffffffff).unwrap_or_else(|_| unreachable!()); | 860 | | | 861 | | let result = self.inner.vm.read_memory(ptr, len); | 862 | | match result { | 863 | | Ok(v) => v, | 864 | | Err(vm::OutOfBoundsError) => { | 865 | | drop(result); | 866 | | return HostVm::Error { | 867 | | error: Error::ParamOutOfRange { | 868 | | function: host_fn.name(), | 869 | | param_num: $num, | 870 | | pointer: ptr, | 871 | | length: len, | 872 | | }, | 873 | | prototype: self.inner.into_prototype(), | 874 | | }; | 875 | | } | 876 | | } | 877 | | }}; | 878 | | } | 879 | | | 880 | | macro_rules! expect_pointer_size_raw { | 881 | | ($num:expr) => {{ | 882 | | let val = match ¶ms[$num] { | 883 | | vm::WasmValue::I64(v) => u64::from_ne_bytes(v.to_ne_bytes()), | 884 | | // The signatures are checked at initialization and the Wasm VM ensures that | 885 | | // the proper parameter types are provided. | 886 | | _ => unreachable!(), | 887 | | }; | 888 | | | 889 | | let len = u32::try_from(val >> 32).unwrap_or_else(|_| unreachable!()); | 890 | | let ptr = u32::try_from(val & 0xffffffff).unwrap_or_else(|_| unreachable!()); | 891 | | | 892 | | if len.saturating_add(ptr) > u32::from(self.inner.vm.memory_size()) * 64 * 1024 { | 893 | | return HostVm::Error { | 894 | | error: Error::ParamOutOfRange { | 895 | | function: host_fn.name(), | 896 | | param_num: $num, | 897 | | pointer: ptr, | 898 | | length: len, | 899 | | }, | 900 | | prototype: self.inner.into_prototype(), | 901 | | }; | 902 | | } | 903 | | | 904 | | (ptr, len) | 905 | | }}; | 906 | | } | 907 | | | 908 | | macro_rules! expect_pointer_constant_size { | 909 | | ($num:expr, $size:expr) => {{ | 910 | | let ptr = match params[$num] { | 911 | | vm::WasmValue::I32(v) => u32::from_ne_bytes(v.to_ne_bytes()), | 912 | | // The signatures are checked at initialization and the Wasm VM ensures that | 913 | | // the proper parameter types are provided. | 914 | | _ => unreachable!(), | 915 | | }; | 916 | | | 917 | | let result = self.inner.vm.read_memory(ptr, $size); | 918 | | match result { | 919 | | Ok(v) => { | 920 | | *<&[u8; $size]>::try_from(v.as_ref()).unwrap_or_else(|_| unreachable!()) | 921 | | } | 922 | | Err(vm::OutOfBoundsError) => { | 923 | | drop(result); | 924 | | return HostVm::Error { | 925 | | error: Error::ParamOutOfRange { | 926 | | function: host_fn.name(), | 927 | | param_num: $num, | 928 | | pointer: ptr, | 929 | | length: $size, | 930 | | }, | 931 | | prototype: self.inner.into_prototype(), | 932 | | }; | 933 | | } | 934 | | } | 935 | | }}; | 936 | | } | 937 | | | 938 | | macro_rules! expect_pointer_constant_size_raw { | 939 | | ($num:expr, $size:expr) => {{ | 940 | | let ptr = match params[$num] { | 941 | | vm::WasmValue::I32(v) => u32::from_ne_bytes(v.to_ne_bytes()), | 942 | | // The signatures are checked at initialization and the Wasm VM ensures that | 943 | | // the proper parameter types are provided. | 944 | | _ => unreachable!(), | 945 | | }; | 946 | | | 947 | | if u32::saturating_add($size, ptr) | 948 | | > u32::from(self.inner.vm.memory_size()) * 64 * 1024 | 949 | | { | 950 | | return HostVm::Error { | 951 | | error: Error::ParamOutOfRange { | 952 | | function: host_fn.name(), | 953 | | param_num: $num, | 954 | | pointer: ptr, | 955 | | length: $size, | 956 | | }, | 957 | | prototype: self.inner.into_prototype(), | 958 | | }; | 959 | | } | 960 | | | 961 | | ptr | 962 | | }}; | 963 | | } | 964 | | | 965 | | macro_rules! expect_u32 { | 966 | | ($num:expr) => {{ | 967 | | match ¶ms[$num] { | 968 | | vm::WasmValue::I32(v) => u32::from_ne_bytes(v.to_ne_bytes()), | 969 | | // The signatures are checked at initialization and the Wasm VM ensures that | 970 | | // the proper parameter types are provided. | 971 | | _ => unreachable!(), | 972 | | } | 973 | | }}; | 974 | | } | 975 | | | 976 | | macro_rules! expect_offchain_storage_kind { | 977 | | ($num:expr) => {{ | 978 | | match ¶ms[$num] { | 979 | | // `0` indicates `StorageKind::PERSISTENT`, the only kind of offchain | 980 | | // storage that is available. | 981 | | vm::WasmValue::I32(0) => true, | 982 | | // `1` indicates `StorageKind::LOCAL`, which is valid but has never been | 983 | | // implemented in Substrate. | 984 | | vm::WasmValue::I32(1) => false, | 985 | | vm::WasmValue::I32(_) => { | 986 | | return HostVm::Error { | 987 | | error: Error::ParamDecodeError, | 988 | | prototype: self.inner.into_prototype(), | 989 | | } | 990 | | } | 991 | | // The signatures are checked at initialization and the Wasm VM ensures that | 992 | | // the proper parameter types are provided. | 993 | | _ => unreachable!(), | 994 | | } | 995 | | }}; | 996 | | } | 997 | | | 998 | | macro_rules! expect_state_version { | 999 | | ($num:expr) => {{ | 1000 | | match ¶ms[$num] { | 1001 | | vm::WasmValue::I32(0) => TrieEntryVersion::V0, | 1002 | | vm::WasmValue::I32(1) => TrieEntryVersion::V1, | 1003 | | vm::WasmValue::I32(_) => { | 1004 | | return HostVm::Error { | 1005 | | error: Error::ParamDecodeError, | 1006 | | prototype: self.inner.into_prototype(), | 1007 | | } | 1008 | | } | 1009 | | // The signatures are checked at initialization and the Wasm VM ensures that | 1010 | | // the proper parameter types are provided. | 1011 | | _ => unreachable!(), | 1012 | | } | 1013 | | }}; | 1014 | | } | 1015 | | | 1016 | | // TODO: implement all functions and remove this macro | 1017 | | macro_rules! host_fn_not_implemented { | 1018 | | () => {{ | 1019 | | return HostVm::Error { | 1020 | | error: Error::HostFunctionNotImplemented { | 1021 | | function: host_fn.name(), | 1022 | | }, | 1023 | | prototype: self.inner.into_prototype(), | 1024 | | }; | 1025 | | }}; | 1026 | | } | 1027 | | | 1028 | | // Handle the function calls. | 1029 | | // Some of these enum variants simply change the state of `self`, while most of them | 1030 | | // instead return an `ExternalVm` to the user. | 1031 | 5.07k | match host_fn { | 1032 | | HostFunction::ext_storage_set_version_1 => { | 1033 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1034 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(1); | 1035 | 0 | HostVm::ExternalStorageSet(ExternalStorageSet { | 1036 | 0 | key_ptr, | 1037 | 0 | key_size, | 1038 | 0 | child_trie_ptr_size: None, | 1039 | 0 | value: Some((value_ptr, value_size)), | 1040 | 0 | inner: self.inner, | 1041 | 0 | }) | 1042 | | } | 1043 | | HostFunction::ext_storage_get_version_1 => { | 1044 | 84 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1045 | 84 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1046 | 84 | key_ptr, | 1047 | 84 | key_size, | 1048 | 84 | child_trie_ptr_size: None, | 1049 | 84 | calling: id, | 1050 | 84 | value_out_ptr: None, | 1051 | 84 | offset: 0, | 1052 | 84 | max_size: u32::MAX, | 1053 | 84 | inner: self.inner, | 1054 | 84 | }) | 1055 | | } | 1056 | | HostFunction::ext_storage_read_version_1 => { | 1057 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1058 | 0 | let (value_out_ptr, value_out_size) = expect_pointer_size_raw!(1); | 1059 | 0 | let offset = expect_u32!(2); | 1060 | 0 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1061 | 0 | key_ptr, | 1062 | 0 | key_size, | 1063 | 0 | child_trie_ptr_size: None, | 1064 | 0 | calling: id, | 1065 | 0 | value_out_ptr: Some(value_out_ptr), | 1066 | 0 | offset, | 1067 | 0 | max_size: value_out_size, | 1068 | 0 | inner: self.inner, | 1069 | 0 | }) | 1070 | | } | 1071 | | HostFunction::ext_storage_clear_version_1 => { | 1072 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1073 | 0 | HostVm::ExternalStorageSet(ExternalStorageSet { | 1074 | 0 | key_ptr, | 1075 | 0 | key_size, | 1076 | 0 | child_trie_ptr_size: None, | 1077 | 0 | value: None, | 1078 | 0 | inner: self.inner, | 1079 | 0 | }) | 1080 | | } | 1081 | | HostFunction::ext_storage_exists_version_1 => { | 1082 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1083 | 0 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1084 | 0 | key_ptr, | 1085 | 0 | key_size, | 1086 | 0 | child_trie_ptr_size: None, | 1087 | 0 | calling: id, | 1088 | 0 | value_out_ptr: None, | 1089 | 0 | offset: 0, | 1090 | 0 | max_size: 0, | 1091 | 0 | inner: self.inner, | 1092 | 0 | }) | 1093 | | } | 1094 | | HostFunction::ext_storage_clear_prefix_version_1 => { | 1095 | 0 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(0); | 1096 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1097 | 0 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), | 1098 | 0 | child_trie_ptr_size: None, | 1099 | 0 | inner: self.inner, | 1100 | 0 | max_keys_to_remove: None, | 1101 | 0 | calling: id, | 1102 | 0 | }) | 1103 | | } | 1104 | | HostFunction::ext_storage_clear_prefix_version_2 => { | 1105 | 0 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(0); | 1106 | | | 1107 | 0 | let max_keys_to_remove = { | 1108 | 0 | let input = expect_pointer_size!(1); | 1109 | 0 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = | 1110 | 0 | nom::combinator::all_consuming(util::nom_option_decode( | 1111 | 0 | nom::number::streaming::le_u32, | 1112 | 0 | ))(input.as_ref()) | 1113 | 0 | .map(|(_, parse_result)| parse_result); | 1114 | 0 |
| 1115 | 0 | match parsing_result { | 1116 | 0 | Ok(val) => Ok(val), | 1117 | 0 | Err(_) => Err(()), | 1118 | | } | 1119 | | }; | 1120 | | | 1121 | 0 | let max_keys_to_remove = match max_keys_to_remove { | 1122 | 0 | Ok(l) => l, | 1123 | | Err(()) => { | 1124 | 0 | return HostVm::Error { | 1125 | 0 | error: Error::ParamDecodeError, | 1126 | 0 | prototype: self.inner.into_prototype(), | 1127 | 0 | }; | 1128 | | } | 1129 | | }; | 1130 | | | 1131 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1132 | 0 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), | 1133 | 0 | child_trie_ptr_size: None, | 1134 | 0 | inner: self.inner, | 1135 | 0 | max_keys_to_remove, | 1136 | 0 | calling: id, | 1137 | 0 | }) | 1138 | | } | 1139 | | HostFunction::ext_storage_root_version_1 => { | 1140 | 0 | HostVm::ExternalStorageRoot(ExternalStorageRoot { | 1141 | 0 | inner: self.inner, | 1142 | 0 | calling: id, | 1143 | 0 | child_trie_ptr_size: None, | 1144 | 0 | }) | 1145 | | } | 1146 | | HostFunction::ext_storage_root_version_2 => { | 1147 | | // The `ext_storage_root_version_2` host function gets passed as parameter the | 1148 | | // state version of the runtime. This is in fact completely unnecessary as the | 1149 | | // same information is found in the runtime specification, and this parameter | 1150 | | // should be considered as a historical accident. We verify that the version | 1151 | | // provided as parameter is the same as the one in the specification. | 1152 | 0 | let version_param = expect_state_version!(0); | 1153 | 0 | let version_spec = self | 1154 | 0 | .inner | 1155 | 0 | .common | 1156 | 0 | .runtime_version | 1157 | 0 | .as_ref() | 1158 | 0 | .unwrap_or_else(|| unreachable!()) | 1159 | 0 | .decode() | 1160 | 0 | .state_version | 1161 | 0 | .unwrap_or(TrieEntryVersion::V0); | 1162 | 0 |
| 1163 | 0 | if version_param != version_spec { | 1164 | 0 | return HostVm::Error { | 1165 | 0 | error: Error::StateVersionMismatch { | 1166 | 0 | parameter: version_param, | 1167 | 0 | specification: version_spec, | 1168 | 0 | }, | 1169 | 0 | prototype: self.inner.into_prototype(), | 1170 | 0 | }; | 1171 | 0 | } | 1172 | 0 |
| 1173 | 0 | HostVm::ExternalStorageRoot(ExternalStorageRoot { | 1174 | 0 | inner: self.inner, | 1175 | 0 | calling: id, | 1176 | 0 | child_trie_ptr_size: None, | 1177 | 0 | }) | 1178 | | } | 1179 | | HostFunction::ext_storage_changes_root_version_1 => { | 1180 | | // The changes trie is an obsolete attempt at having a second trie containing, for | 1181 | | // each storage item, the latest block height where this item has been modified. | 1182 | | // When this function returns `None`, it indicates that the changes trie is | 1183 | | // disabled. While this function used to be called by the runtimes of | 1184 | | // Westend/Polkadot/Kusama (and maybe others), it has never returned anything else | 1185 | | // but `None`. The entire changes trie mechanism was ultimately removed in | 1186 | | // October 2021. | 1187 | | // This function is no longer called by recent runtimes, but must be preserved for | 1188 | | // backwards compatibility. | 1189 | 0 | self.inner.alloc_write_and_return_pointer_size( | 1190 | 0 | HostFunction::ext_storage_changes_root_version_1.name(), | 1191 | 0 | iter::once(&[0][..]), | 1192 | 0 | ) | 1193 | | } | 1194 | | HostFunction::ext_storage_next_key_version_1 => { | 1195 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1196 | 0 | HostVm::ExternalStorageNextKey(ExternalStorageNextKey { | 1197 | 0 | key_ptr, | 1198 | 0 | key_size, | 1199 | 0 | child_trie_ptr_size: None, | 1200 | 0 | inner: self.inner, | 1201 | 0 | }) | 1202 | | } | 1203 | | HostFunction::ext_storage_append_version_1 => { | 1204 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1205 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(1); | 1206 | 0 | HostVm::ExternalStorageAppend(ExternalStorageAppend { | 1207 | 0 | key_ptr, | 1208 | 0 | key_size, | 1209 | 0 | value_ptr, | 1210 | 0 | value_size, | 1211 | 0 | inner: self.inner, | 1212 | 0 | }) | 1213 | | } | 1214 | | HostFunction::ext_storage_start_transaction_version_1 => { | 1215 | | // TODO: a maximum depth is important in order to prevent a malicious runtime from crashing the client, but the depth needs to be the same as in Substrate; figure out | 1216 | 0 | self.inner.storage_transaction_depth += 1; | 1217 | 0 | HostVm::StartStorageTransaction(StartStorageTransaction { inner: self.inner }) | 1218 | | } | 1219 | | HostFunction::ext_storage_rollback_transaction_version_1 => { | 1220 | 0 | if self.inner.storage_transaction_depth == 0 { | 1221 | 0 | return HostVm::Error { | 1222 | 0 | error: Error::NoActiveTransaction, | 1223 | 0 | prototype: self.inner.into_prototype(), | 1224 | 0 | }; | 1225 | 0 | } | 1226 | 0 |
| 1227 | 0 | self.inner.storage_transaction_depth -= 1; | 1228 | 0 | HostVm::EndStorageTransaction { | 1229 | 0 | resume: EndStorageTransaction { inner: self.inner }, | 1230 | 0 | rollback: true, | 1231 | 0 | } | 1232 | | } | 1233 | | HostFunction::ext_storage_commit_transaction_version_1 => { | 1234 | 0 | if self.inner.storage_transaction_depth == 0 { | 1235 | 0 | return HostVm::Error { | 1236 | 0 | error: Error::NoActiveTransaction, | 1237 | 0 | prototype: self.inner.into_prototype(), | 1238 | 0 | }; | 1239 | 0 | } | 1240 | 0 |
| 1241 | 0 | self.inner.storage_transaction_depth -= 1; | 1242 | 0 | HostVm::EndStorageTransaction { | 1243 | 0 | resume: EndStorageTransaction { inner: self.inner }, | 1244 | 0 | rollback: false, | 1245 | 0 | } | 1246 | | } | 1247 | | HostFunction::ext_storage_proof_size_storage_proof_size_version_1 => { | 1248 | 0 | match self.inner.storage_proof_size_behavior { | 1249 | 0 | StorageProofSizeBehavior::ConstantReturnValue(value) => { | 1250 | 0 | HostVm::ReadyToRun(ReadyToRun { | 1251 | 0 | inner: self.inner, | 1252 | 0 | resume_value: Some(vm::WasmValue::I64(i64::from_ne_bytes( | 1253 | 0 | value.to_ne_bytes(), | 1254 | 0 | ))), | 1255 | 0 | }) | 1256 | | } | 1257 | 0 | StorageProofSizeBehavior::Unimplemented => HostVm::Error { | 1258 | 0 | error: Error::HostFunctionNotImplemented { | 1259 | 0 | function: host_fn.name(), | 1260 | 0 | }, | 1261 | 0 | prototype: self.inner.into_prototype(), | 1262 | 0 | }, | 1263 | | } | 1264 | | } | 1265 | | HostFunction::ext_default_child_storage_get_version_1 => { | 1266 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1267 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1268 | 0 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1269 | 0 | key_ptr, | 1270 | 0 | key_size, | 1271 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1272 | 0 | calling: id, | 1273 | 0 | value_out_ptr: None, | 1274 | 0 | offset: 0, | 1275 | 0 | max_size: u32::MAX, | 1276 | 0 | inner: self.inner, | 1277 | 0 | }) | 1278 | | } | 1279 | | HostFunction::ext_default_child_storage_read_version_1 => { | 1280 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1281 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1282 | 0 | let (value_out_ptr, value_out_size) = expect_pointer_size_raw!(2); | 1283 | 0 | let offset = expect_u32!(3); | 1284 | 0 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1285 | 0 | key_ptr, | 1286 | 0 | key_size, | 1287 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1288 | 0 | calling: id, | 1289 | 0 | value_out_ptr: Some(value_out_ptr), | 1290 | 0 | offset, | 1291 | 0 | max_size: value_out_size, | 1292 | 0 | inner: self.inner, | 1293 | 0 | }) | 1294 | | } | 1295 | | HostFunction::ext_default_child_storage_storage_kill_version_1 => { | 1296 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1297 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1298 | 0 | prefix_ptr_size: None, | 1299 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1300 | 0 | inner: self.inner, | 1301 | 0 | max_keys_to_remove: None, | 1302 | 0 | calling: id, | 1303 | 0 | }) | 1304 | | } | 1305 | | HostFunction::ext_default_child_storage_storage_kill_version_2 | 1306 | | | HostFunction::ext_default_child_storage_storage_kill_version_3 => { | 1307 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1308 | | | 1309 | 0 | let max_keys_to_remove = { | 1310 | 0 | let input = expect_pointer_size!(1); | 1311 | 0 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = | 1312 | 0 | nom::combinator::all_consuming(util::nom_option_decode( | 1313 | 0 | nom::number::streaming::le_u32, | 1314 | 0 | ))(input.as_ref()) | 1315 | 0 | .map(|(_, parse_result)| parse_result); | 1316 | 0 |
| 1317 | 0 | match parsing_result { | 1318 | 0 | Ok(val) => Ok(val), | 1319 | 0 | Err(_) => Err(()), | 1320 | | } | 1321 | | }; | 1322 | | | 1323 | 0 | let max_keys_to_remove = match max_keys_to_remove { | 1324 | 0 | Ok(l) => l, | 1325 | | Err(()) => { | 1326 | 0 | return HostVm::Error { | 1327 | 0 | error: Error::ParamDecodeError, | 1328 | 0 | prototype: self.inner.into_prototype(), | 1329 | 0 | }; | 1330 | | } | 1331 | | }; | 1332 | | | 1333 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1334 | 0 | prefix_ptr_size: None, | 1335 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1336 | 0 | inner: self.inner, | 1337 | 0 | max_keys_to_remove, | 1338 | 0 | calling: id, | 1339 | 0 | }) | 1340 | | } | 1341 | | HostFunction::ext_default_child_storage_clear_prefix_version_1 => { | 1342 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1343 | 0 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(1); | 1344 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1345 | 0 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), | 1346 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1347 | 0 | inner: self.inner, | 1348 | 0 | max_keys_to_remove: None, | 1349 | 0 | calling: id, | 1350 | 0 | }) | 1351 | | } | 1352 | | HostFunction::ext_default_child_storage_clear_prefix_version_2 => { | 1353 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1354 | 0 | let (prefix_ptr, prefix_size) = expect_pointer_size_raw!(1); | 1355 | | | 1356 | 0 | let max_keys_to_remove = { | 1357 | 0 | let input = expect_pointer_size!(2); | 1358 | 0 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = | 1359 | 0 | nom::combinator::all_consuming(util::nom_option_decode( | 1360 | 0 | nom::number::streaming::le_u32, | 1361 | 0 | ))(input.as_ref()) | 1362 | 0 | .map(|(_, parse_result)| parse_result); | 1363 | 0 |
| 1364 | 0 | match parsing_result { | 1365 | 0 | Ok(val) => Ok(val), | 1366 | 0 | Err(_) => Err(()), | 1367 | | } | 1368 | | }; | 1369 | | | 1370 | 0 | let max_keys_to_remove = match max_keys_to_remove { | 1371 | 0 | Ok(l) => l, | 1372 | | Err(()) => { | 1373 | 0 | return HostVm::Error { | 1374 | 0 | error: Error::ParamDecodeError, | 1375 | 0 | prototype: self.inner.into_prototype(), | 1376 | 0 | }; | 1377 | | } | 1378 | | }; | 1379 | | | 1380 | 0 | HostVm::ExternalStorageClearPrefix(ExternalStorageClearPrefix { | 1381 | 0 | prefix_ptr_size: Some((prefix_ptr, prefix_size)), | 1382 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1383 | 0 | inner: self.inner, | 1384 | 0 | max_keys_to_remove, | 1385 | 0 | calling: id, | 1386 | 0 | }) | 1387 | | } | 1388 | | HostFunction::ext_default_child_storage_set_version_1 => { | 1389 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1390 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1391 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(2); | 1392 | 0 | HostVm::ExternalStorageSet(ExternalStorageSet { | 1393 | 0 | key_ptr, | 1394 | 0 | key_size, | 1395 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1396 | 0 | value: Some((value_ptr, value_size)), | 1397 | 0 | inner: self.inner, | 1398 | 0 | }) | 1399 | | } | 1400 | | HostFunction::ext_default_child_storage_clear_version_1 => { | 1401 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1402 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1403 | 0 | HostVm::ExternalStorageSet(ExternalStorageSet { | 1404 | 0 | key_ptr, | 1405 | 0 | key_size, | 1406 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1407 | 0 | value: None, | 1408 | 0 | inner: self.inner, | 1409 | 0 | }) | 1410 | | } | 1411 | | HostFunction::ext_default_child_storage_exists_version_1 => { | 1412 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1413 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1414 | 0 | HostVm::ExternalStorageGet(ExternalStorageGet { | 1415 | 0 | key_ptr, | 1416 | 0 | key_size, | 1417 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1418 | 0 | calling: id, | 1419 | 0 | value_out_ptr: None, | 1420 | 0 | offset: 0, | 1421 | 0 | max_size: 0, | 1422 | 0 | inner: self.inner, | 1423 | 0 | }) | 1424 | | } | 1425 | | HostFunction::ext_default_child_storage_next_key_version_1 => { | 1426 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1427 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1428 | 0 | HostVm::ExternalStorageNextKey(ExternalStorageNextKey { | 1429 | 0 | key_ptr, | 1430 | 0 | key_size, | 1431 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1432 | 0 | inner: self.inner, | 1433 | 0 | }) | 1434 | | } | 1435 | | HostFunction::ext_default_child_storage_root_version_1 => { | 1436 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1437 | 0 | HostVm::ExternalStorageRoot(ExternalStorageRoot { | 1438 | 0 | inner: self.inner, | 1439 | 0 | calling: id, | 1440 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1441 | 0 | }) | 1442 | | } | 1443 | | HostFunction::ext_default_child_storage_root_version_2 => { | 1444 | 0 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0); | 1445 | | | 1446 | | // The `ext_default_child_storage_root_version_2` host function gets passed as | 1447 | | // parameter the state version of the runtime. This is in fact completely | 1448 | | // unnecessary as the same information is found in the runtime specification, and | 1449 | | // this parameter should be considered as a historical accident. We verify that the | 1450 | | // version provided as parameter is the same as the one in the specification. | 1451 | 0 | let version_param = expect_state_version!(1); | 1452 | 0 | let version_spec = self | 1453 | 0 | .inner | 1454 | 0 | .common | 1455 | 0 | .runtime_version | 1456 | 0 | .as_ref() | 1457 | 0 | .unwrap_or_else(|| unreachable!()) | 1458 | 0 | .decode() | 1459 | 0 | .state_version | 1460 | 0 | .unwrap_or(TrieEntryVersion::V0); | 1461 | 0 |
| 1462 | 0 | if version_param != version_spec { | 1463 | 0 | return HostVm::Error { | 1464 | 0 | error: Error::StateVersionMismatch { | 1465 | 0 | parameter: version_param, | 1466 | 0 | specification: version_spec, | 1467 | 0 | }, | 1468 | 0 | prototype: self.inner.into_prototype(), | 1469 | 0 | }; | 1470 | 0 | } | 1471 | 0 |
| 1472 | 0 | HostVm::ExternalStorageRoot(ExternalStorageRoot { | 1473 | 0 | inner: self.inner, | 1474 | 0 | calling: id, | 1475 | 0 | child_trie_ptr_size: Some((child_trie_ptr, child_trie_size)), | 1476 | 0 | }) | 1477 | | } | 1478 | 0 | HostFunction::ext_crypto_ed25519_public_keys_version_1 => host_fn_not_implemented!(), | 1479 | 0 | HostFunction::ext_crypto_ed25519_generate_version_1 => host_fn_not_implemented!(), | 1480 | 0 | HostFunction::ext_crypto_ed25519_sign_version_1 => host_fn_not_implemented!(), | 1481 | | HostFunction::ext_crypto_ed25519_verify_version_1 | 1482 | | | HostFunction::ext_crypto_ed25519_batch_verify_version_1 => { | 1483 | 0 | let is_batch_verification = matches!( | 1484 | 0 | host_fn, | 1485 | | HostFunction::ext_crypto_ed25519_batch_verify_version_1 | 1486 | | ); | 1487 | | | 1488 | 0 | if is_batch_verification && self.inner.signatures_batch_verification.is_none() { | 1489 | 0 | return HostVm::Error { | 1490 | 0 | error: Error::BatchVerifyWithoutStarting, | 1491 | 0 | prototype: self.inner.into_prototype(), | 1492 | 0 | }; | 1493 | 0 | } | 1494 | | | 1495 | 0 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); | 1496 | | HostVm::SignatureVerification(SignatureVerification { | 1497 | 0 | algorithm: SignatureVerificationAlgorithm::Ed25519, | 1498 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 64), | 1499 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 32), | 1500 | 0 | message_ptr, | 1501 | 0 | message_size, | 1502 | 0 | inner: self.inner, | 1503 | 0 | is_batch_verification, | 1504 | | }) | 1505 | | } | 1506 | 0 | HostFunction::ext_crypto_sr25519_public_keys_version_1 => host_fn_not_implemented!(), | 1507 | 0 | HostFunction::ext_crypto_sr25519_generate_version_1 => host_fn_not_implemented!(), | 1508 | 0 | HostFunction::ext_crypto_sr25519_sign_version_1 => host_fn_not_implemented!(), | 1509 | | HostFunction::ext_crypto_sr25519_verify_version_1 | 1510 | | | HostFunction::ext_crypto_sr25519_batch_verify_version_1 => { | 1511 | 0 | let is_batch_verification = matches!( | 1512 | 0 | host_fn, | 1513 | | HostFunction::ext_crypto_sr25519_batch_verify_version_1 | 1514 | | ); | 1515 | | | 1516 | 0 | if is_batch_verification && self.inner.signatures_batch_verification.is_none() { | 1517 | 0 | return HostVm::Error { | 1518 | 0 | error: Error::BatchVerifyWithoutStarting, | 1519 | 0 | prototype: self.inner.into_prototype(), | 1520 | 0 | }; | 1521 | 0 | } | 1522 | | | 1523 | 0 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); | 1524 | | HostVm::SignatureVerification(SignatureVerification { | 1525 | 0 | algorithm: SignatureVerificationAlgorithm::Sr25519V1, | 1526 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 64), | 1527 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 32), | 1528 | 0 | message_ptr, | 1529 | 0 | message_size, | 1530 | 0 | inner: self.inner, | 1531 | 0 | is_batch_verification, | 1532 | | }) | 1533 | | } | 1534 | | HostFunction::ext_crypto_sr25519_verify_version_2 => { | 1535 | 0 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); | 1536 | | HostVm::SignatureVerification(SignatureVerification { | 1537 | 0 | algorithm: SignatureVerificationAlgorithm::Sr25519V2, | 1538 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 64), | 1539 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 32), | 1540 | 0 | message_ptr, | 1541 | 0 | message_size, | 1542 | 0 | inner: self.inner, | 1543 | | is_batch_verification: false, | 1544 | | }) | 1545 | | } | 1546 | 0 | HostFunction::ext_crypto_ecdsa_generate_version_1 => host_fn_not_implemented!(), | 1547 | | HostFunction::ext_crypto_ecdsa_sign_version_1 => { | 1548 | | // NOTE: safe to unwrap here because we supply the nn to blake2b fn | 1549 | 0 | let data = <[u8; 32]>::try_from( | 1550 | 0 | blake2_rfc::blake2b::blake2b(32, &[], expect_pointer_size!(0).as_ref()) | 1551 | 0 | .as_bytes(), | 1552 | 0 | ) | 1553 | 0 | .unwrap_or_else(|_| unreachable!()); | 1554 | 0 | let message = libsecp256k1::Message::parse(&data); | 1555 | | | 1556 | 0 | if let Ok(sc) = | 1557 | 0 | libsecp256k1::SecretKey::parse(&expect_pointer_constant_size!(1, 32)) | 1558 | | { | 1559 | 0 | let (sig, ri) = libsecp256k1::sign(&message, &sc); | 1560 | 0 |
| 1561 | 0 | // NOTE: the function returns 2 slices: signature (64 bytes) and recovery ID (1 byte; AS A SLICE) | 1562 | 0 | self.inner.alloc_write_and_return_pointer( | 1563 | 0 | host_fn.name(), | 1564 | 0 | [&sig.serialize()[..], &[ri.serialize()]].into_iter(), | 1565 | 0 | ) | 1566 | | } else { | 1567 | 0 | HostVm::Error { | 1568 | 0 | error: Error::ParamDecodeError, | 1569 | 0 | prototype: self.inner.into_prototype(), | 1570 | 0 | } | 1571 | | } | 1572 | | } | 1573 | 0 | HostFunction::ext_crypto_ecdsa_public_keys_version_1 => host_fn_not_implemented!(), | 1574 | | HostFunction::ext_crypto_ecdsa_verify_version_1 | 1575 | | | HostFunction::ext_crypto_ecdsa_batch_verify_version_1 => { | 1576 | 0 | let is_batch_verification = matches!( | 1577 | 0 | host_fn, | 1578 | | HostFunction::ext_crypto_ecdsa_batch_verify_version_1 | 1579 | | ); | 1580 | | | 1581 | 0 | if is_batch_verification && self.inner.signatures_batch_verification.is_none() { | 1582 | 0 | return HostVm::Error { | 1583 | 0 | error: Error::BatchVerifyWithoutStarting, | 1584 | 0 | prototype: self.inner.into_prototype(), | 1585 | 0 | }; | 1586 | 0 | } | 1587 | | | 1588 | 0 | let (message_ptr, message_size) = expect_pointer_size_raw!(1); | 1589 | | HostVm::SignatureVerification(SignatureVerification { | 1590 | 0 | algorithm: SignatureVerificationAlgorithm::Ecdsa, | 1591 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 65), | 1592 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 33), | 1593 | 0 | message_ptr, | 1594 | 0 | message_size, | 1595 | 0 | inner: self.inner, | 1596 | 0 | is_batch_verification, | 1597 | | }) | 1598 | | } | 1599 | 0 | HostFunction::ext_crypto_ecdsa_verify_version_2 => host_fn_not_implemented!(), | 1600 | | HostFunction::ext_crypto_ecdsa_sign_prehashed_version_1 => { | 1601 | | // TODO: seems misimplemented, see https://spec.polkadot.network/#id-ext_crypto_ecdsa_sign_prehashed | 1602 | 0 | let message = libsecp256k1::Message::parse(&expect_pointer_constant_size!(0, 32)); | 1603 | | | 1604 | 0 | if let Ok(sc) = | 1605 | 0 | libsecp256k1::SecretKey::parse(&expect_pointer_constant_size!(1, 32)) | 1606 | | { | 1607 | 0 | let (sig, ri) = libsecp256k1::sign(&message, &sc); | 1608 | 0 |
| 1609 | 0 | // NOTE: the function returns 2 slices: signature (64 bytes) and recovery ID (1 byte; AS A SLICE) | 1610 | 0 | self.inner.alloc_write_and_return_pointer( | 1611 | 0 | host_fn.name(), | 1612 | 0 | [&sig.serialize()[..], &[ri.serialize()]].into_iter(), | 1613 | 0 | ) | 1614 | | } else { | 1615 | 0 | HostVm::Error { | 1616 | 0 | error: Error::ParamDecodeError, | 1617 | 0 | prototype: self.inner.into_prototype(), | 1618 | 0 | } | 1619 | | } | 1620 | | } | 1621 | | HostFunction::ext_crypto_ecdsa_verify_prehashed_version_1 => { | 1622 | | HostVm::SignatureVerification(SignatureVerification { | 1623 | 0 | algorithm: SignatureVerificationAlgorithm::EcdsaPrehashed, | 1624 | 0 | signature_ptr: expect_pointer_constant_size_raw!(0, 65), | 1625 | 0 | public_key_ptr: expect_pointer_constant_size_raw!(2, 33), | 1626 | 0 | message_ptr: expect_pointer_constant_size_raw!(1, 32), | 1627 | | message_size: 32, | 1628 | 0 | inner: self.inner, | 1629 | | is_batch_verification: false, | 1630 | | }) | 1631 | | } | 1632 | | | 1633 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_version_1 | 1634 | | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_version_2 => { | 1635 | 0 | let sig = expect_pointer_constant_size!(0, 65); | 1636 | 0 | let msg = expect_pointer_constant_size!(1, 32); | 1637 | 0 | let is_v2 = matches!( | 1638 | 0 | host_fn, | 1639 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_version_2 | 1640 | | ); | 1641 | | | 1642 | 0 | let result = { | 1643 | 0 | let rs = if is_v2 { | 1644 | 0 | libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) | 1645 | | } else { | 1646 | 0 | libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64]) | 1647 | | }; | 1648 | | | 1649 | 0 | if let Ok(rs) = rs { | 1650 | 0 | let v = libsecp256k1::RecoveryId::parse(if sig[64] > 26 { | 1651 | 0 | sig[64] - 27 | 1652 | | } else { | 1653 | 0 | sig[64] | 1654 | | }); | 1655 | | | 1656 | 0 | if let Ok(v) = v { | 1657 | 0 | let pubkey = libsecp256k1::recover( | 1658 | 0 | &libsecp256k1::Message::parse_slice(&msg) | 1659 | 0 | .unwrap_or_else(|_| unreachable!()), | 1660 | 0 | &rs, | 1661 | 0 | &v, | 1662 | 0 | ); | 1663 | | | 1664 | 0 | if let Ok(pubkey) = pubkey { | 1665 | 0 | let mut res = Vec::with_capacity(65); | 1666 | 0 | res.push(0); | 1667 | 0 | res.extend_from_slice(&pubkey.serialize()[1..65]); | 1668 | 0 | res | 1669 | | } else { | 1670 | 0 | vec![1, 2] | 1671 | | } | 1672 | | } else { | 1673 | 0 | vec![1, 1] | 1674 | | } | 1675 | | } else { | 1676 | 0 | vec![1, 0] | 1677 | | } | 1678 | | }; | 1679 | | | 1680 | 0 | self.inner | 1681 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&result)) | 1682 | | } | 1683 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_compressed_version_1 | 1684 | | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_compressed_version_2 => { | 1685 | 0 | let sig = expect_pointer_constant_size!(0, 65); | 1686 | 0 | let msg = expect_pointer_constant_size!(1, 32); | 1687 | 0 | let is_v2 = matches!( | 1688 | 0 | host_fn, | 1689 | | HostFunction::ext_crypto_secp256k1_ecdsa_recover_compressed_version_2 | 1690 | | ); | 1691 | | | 1692 | 0 | let result = { | 1693 | 0 | let rs = if is_v2 { | 1694 | 0 | libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) | 1695 | | } else { | 1696 | 0 | libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64]) | 1697 | | }; | 1698 | | | 1699 | 0 | if let Ok(rs) = rs { | 1700 | 0 | let v = libsecp256k1::RecoveryId::parse(if sig[64] > 26 { | 1701 | 0 | sig[64] - 27 | 1702 | | } else { | 1703 | 0 | sig[64] | 1704 | | }); | 1705 | | | 1706 | 0 | if let Ok(v) = v { | 1707 | 0 | let pubkey = libsecp256k1::recover( | 1708 | 0 | &libsecp256k1::Message::parse_slice(&msg) | 1709 | 0 | .unwrap_or_else(|_| unreachable!()), | 1710 | 0 | &rs, | 1711 | 0 | &v, | 1712 | 0 | ); | 1713 | | | 1714 | 0 | if let Ok(pubkey) = pubkey { | 1715 | 0 | let mut res = Vec::with_capacity(34); | 1716 | 0 | res.push(0); | 1717 | 0 | res.extend_from_slice(&pubkey.serialize_compressed()); | 1718 | 0 | res | 1719 | | } else { | 1720 | 0 | vec![1, 2] | 1721 | | } | 1722 | | } else { | 1723 | 0 | vec![1, 1] | 1724 | | } | 1725 | | } else { | 1726 | 0 | vec![1, 0] | 1727 | | } | 1728 | | }; | 1729 | | | 1730 | 0 | self.inner | 1731 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&result)) | 1732 | | } | 1733 | | HostFunction::ext_crypto_start_batch_verify_version_1 => { | 1734 | 0 | if self.inner.signatures_batch_verification.is_some() { | 1735 | 0 | return HostVm::Error { | 1736 | 0 | error: Error::AlreadyBatchVerify, | 1737 | 0 | prototype: self.inner.into_prototype(), | 1738 | 0 | }; | 1739 | 0 | } | 1740 | 0 |
| 1741 | 0 | self.inner.signatures_batch_verification = Some(true); | 1742 | 0 |
| 1743 | 0 | HostVm::ReadyToRun(ReadyToRun { | 1744 | 0 | resume_value: None, | 1745 | 0 | inner: self.inner, | 1746 | 0 | }) | 1747 | | } | 1748 | | HostFunction::ext_crypto_finish_batch_verify_version_1 => { | 1749 | 0 | let Some(outcome) = self.inner.signatures_batch_verification.take() else { | 1750 | 0 | return HostVm::Error { | 1751 | 0 | error: Error::NoBatchVerify, | 1752 | 0 | prototype: self.inner.into_prototype(), | 1753 | 0 | }; | 1754 | | }; | 1755 | | | 1756 | | HostVm::ReadyToRun(ReadyToRun { | 1757 | 0 | resume_value: Some(vm::WasmValue::I32(if outcome { 1 } else { 0 })), | 1758 | 0 | inner: self.inner, | 1759 | | }) | 1760 | | } | 1761 | | HostFunction::ext_hashing_keccak_256_version_1 => { | 1762 | 0 | let hash = | 1763 | 0 | <sha3::Keccak256 as sha3::Digest>::digest(expect_pointer_size!(0).as_ref()); | 1764 | 0 | self.inner | 1765 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash)) | 1766 | | } | 1767 | | HostFunction::ext_hashing_keccak_512_version_1 => { | 1768 | 0 | let hash = | 1769 | 0 | <sha3::Keccak512 as sha3::Digest>::digest(expect_pointer_size!(0).as_ref()); | 1770 | 0 | self.inner | 1771 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash)) | 1772 | | } | 1773 | | HostFunction::ext_hashing_sha2_256_version_1 => { | 1774 | 0 | let hash = <sha2::Sha256 as sha2::Digest>::digest(expect_pointer_size!(0).as_ref()); | 1775 | 0 | self.inner | 1776 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&hash)) | 1777 | | } | 1778 | | HostFunction::ext_hashing_blake2_128_version_1 => { | 1779 | 0 | let out = { | 1780 | 0 | let data = expect_pointer_size!(0); | 1781 | 0 | blake2_rfc::blake2b::blake2b(16, &[], data.as_ref()) | 1782 | 0 | }; | 1783 | 0 |
| 1784 | 0 | self.inner | 1785 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(out.as_bytes())) | 1786 | | } | 1787 | | HostFunction::ext_hashing_blake2_256_version_1 => { | 1788 | 0 | let out = { | 1789 | 0 | let data = expect_pointer_size!(0); | 1790 | 0 | blake2_rfc::blake2b::blake2b(32, &[], data.as_ref()) | 1791 | 0 | }; | 1792 | 0 |
| 1793 | 0 | self.inner | 1794 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(out.as_bytes())) | 1795 | | } | 1796 | | HostFunction::ext_hashing_twox_64_version_1 => { | 1797 | 0 | let mut h0 = twox_hash::XxHash::with_seed(0); | 1798 | 0 | { | 1799 | 0 | let data = expect_pointer_size!(0); | 1800 | 0 | h0.write(data.as_ref()); | 1801 | 0 | } | 1802 | 0 | let r0 = h0.finish(); | 1803 | 0 |
| 1804 | 0 | self.inner | 1805 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&r0.to_le_bytes())) | 1806 | | } | 1807 | | HostFunction::ext_hashing_twox_128_version_1 => { | 1808 | 84 | let mut h0 = twox_hash::XxHash::with_seed(0); | 1809 | 84 | let mut h1 = twox_hash::XxHash::with_seed(1); | 1810 | 84 | { | 1811 | 84 | let data = expect_pointer_size!(0); | 1812 | 84 | let data = data.as_ref(); | 1813 | 84 | h0.write(data); | 1814 | 84 | h1.write(data); | 1815 | 84 | } | 1816 | 84 | let r0 = h0.finish(); | 1817 | 84 | let r1 = h1.finish(); | 1818 | 84 | | 1819 | 84 | self.inner.alloc_write_and_return_pointer( | 1820 | 84 | host_fn.name(), | 1821 | 84 | iter::once(&r0.to_le_bytes()).chain(iter::once(&r1.to_le_bytes())), | 1822 | 84 | ) | 1823 | | } | 1824 | | HostFunction::ext_hashing_twox_256_version_1 => { | 1825 | 0 | let mut h0 = twox_hash::XxHash::with_seed(0); | 1826 | 0 | let mut h1 = twox_hash::XxHash::with_seed(1); | 1827 | 0 | let mut h2 = twox_hash::XxHash::with_seed(2); | 1828 | 0 | let mut h3 = twox_hash::XxHash::with_seed(3); | 1829 | 0 | { | 1830 | 0 | let data = expect_pointer_size!(0); | 1831 | 0 | let data = data.as_ref(); | 1832 | 0 | h0.write(data); | 1833 | 0 | h1.write(data); | 1834 | 0 | h2.write(data); | 1835 | 0 | h3.write(data); | 1836 | 0 | } | 1837 | 0 | let r0 = h0.finish(); | 1838 | 0 | let r1 = h1.finish(); | 1839 | 0 | let r2 = h2.finish(); | 1840 | 0 | let r3 = h3.finish(); | 1841 | 0 |
| 1842 | 0 | self.inner.alloc_write_and_return_pointer( | 1843 | 0 | host_fn.name(), | 1844 | 0 | iter::once(&r0.to_le_bytes()) | 1845 | 0 | .chain(iter::once(&r1.to_le_bytes())) | 1846 | 0 | .chain(iter::once(&r2.to_le_bytes())) | 1847 | 0 | .chain(iter::once(&r3.to_le_bytes())), | 1848 | 0 | ) | 1849 | | } | 1850 | | HostFunction::ext_offchain_index_set_version_1 => { | 1851 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1852 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(1); | 1853 | 0 | HostVm::ExternalOffchainIndexSet(ExternalOffchainIndexSet { | 1854 | 0 | key_ptr, | 1855 | 0 | key_size, | 1856 | 0 | value: Some((value_ptr, value_size)), | 1857 | 0 | inner: self.inner, | 1858 | 0 | }) | 1859 | | } | 1860 | | HostFunction::ext_offchain_index_clear_version_1 => { | 1861 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(0); | 1862 | 0 | HostVm::ExternalOffchainIndexSet(ExternalOffchainIndexSet { | 1863 | 0 | key_ptr, | 1864 | 0 | key_size, | 1865 | 0 | value: None, | 1866 | 0 | inner: self.inner, | 1867 | 0 | }) | 1868 | | } | 1869 | 0 | HostFunction::ext_offchain_is_validator_version_1 => HostVm::ReadyToRun(ReadyToRun { | 1870 | 0 | inner: self.inner, | 1871 | 0 | resume_value: Some(vm::WasmValue::I32(1)), // TODO: ask the API user | 1872 | 0 | }), | 1873 | | HostFunction::ext_offchain_submit_transaction_version_1 => { | 1874 | 0 | let (tx_ptr, tx_size) = expect_pointer_size_raw!(0); | 1875 | 0 | HostVm::OffchainSubmitTransaction(OffchainSubmitTransaction { | 1876 | 0 | inner: self.inner, | 1877 | 0 | calling: id, | 1878 | 0 | tx_ptr, | 1879 | 0 | tx_size, | 1880 | 0 | }) | 1881 | | } | 1882 | | HostFunction::ext_offchain_network_state_version_1 => { | 1883 | 0 | host_fn_not_implemented!() | 1884 | | } | 1885 | | HostFunction::ext_offchain_timestamp_version_1 => { | 1886 | 0 | HostVm::OffchainTimestamp(OffchainTimestamp { inner: self.inner }) | 1887 | | } | 1888 | | HostFunction::ext_offchain_sleep_until_version_1 => { | 1889 | 0 | host_fn_not_implemented!() | 1890 | | } | 1891 | | HostFunction::ext_offchain_random_seed_version_1 => { | 1892 | 0 | HostVm::OffchainRandomSeed(OffchainRandomSeed { | 1893 | 0 | inner: self.inner, | 1894 | 0 | calling: id, | 1895 | 0 | }) | 1896 | | } | 1897 | | HostFunction::ext_offchain_local_storage_set_version_1 => { | 1898 | 0 | if expect_offchain_storage_kind!(0) { | 1899 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1900 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(2); | 1901 | 0 | HostVm::ExternalOffchainStorageSet(ExternalOffchainStorageSet { | 1902 | 0 | key_ptr, | 1903 | 0 | key_size, | 1904 | 0 | value: Some((value_ptr, value_size)), | 1905 | 0 | old_value: None, | 1906 | 0 | inner: self.inner, | 1907 | 0 | }) | 1908 | | } else { | 1909 | 0 | HostVm::ReadyToRun(ReadyToRun { | 1910 | 0 | inner: self.inner, | 1911 | 0 | resume_value: None, | 1912 | 0 | }) | 1913 | | } | 1914 | | } | 1915 | | HostFunction::ext_offchain_local_storage_compare_and_set_version_1 => { | 1916 | 0 | if expect_offchain_storage_kind!(0) { | 1917 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1918 | 0 | let (old_value_ptr, old_value_size) = expect_pointer_size_raw!(2); | 1919 | 0 | let (value_ptr, value_size) = expect_pointer_size_raw!(3); | 1920 | 0 | HostVm::ExternalOffchainStorageSet(ExternalOffchainStorageSet { | 1921 | 0 | key_ptr, | 1922 | 0 | key_size, | 1923 | 0 | value: Some((value_ptr, value_size)), | 1924 | 0 | old_value: Some((old_value_ptr, old_value_size)), | 1925 | 0 | inner: self.inner, | 1926 | 0 | }) | 1927 | | } else { | 1928 | 0 | HostVm::ReadyToRun(ReadyToRun { | 1929 | 0 | inner: self.inner, | 1930 | 0 | resume_value: Some(vm::WasmValue::I32(0)), | 1931 | 0 | }) | 1932 | | } | 1933 | | } | 1934 | | HostFunction::ext_offchain_local_storage_get_version_1 => { | 1935 | 0 | if expect_offchain_storage_kind!(0) { | 1936 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1937 | 0 | HostVm::ExternalOffchainStorageGet(ExternalOffchainStorageGet { | 1938 | 0 | key_ptr, | 1939 | 0 | key_size, | 1940 | 0 | calling: id, | 1941 | 0 | inner: self.inner, | 1942 | 0 | }) | 1943 | | } else { | 1944 | | // Write a SCALE-encoded `None`. | 1945 | 0 | self.inner | 1946 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&[0])) | 1947 | | } | 1948 | | } | 1949 | | HostFunction::ext_offchain_local_storage_clear_version_1 => { | 1950 | 0 | if expect_offchain_storage_kind!(0) { | 1951 | 0 | let (key_ptr, key_size) = expect_pointer_size_raw!(1); | 1952 | 0 | HostVm::ExternalOffchainStorageSet(ExternalOffchainStorageSet { | 1953 | 0 | key_ptr, | 1954 | 0 | key_size, | 1955 | 0 | value: None, | 1956 | 0 | old_value: None, | 1957 | 0 | inner: self.inner, | 1958 | 0 | }) | 1959 | | } else { | 1960 | 0 | HostVm::ReadyToRun(ReadyToRun { | 1961 | 0 | inner: self.inner, | 1962 | 0 | resume_value: None, | 1963 | 0 | }) | 1964 | | } | 1965 | | } | 1966 | 0 | HostFunction::ext_offchain_http_request_start_version_1 => host_fn_not_implemented!(), | 1967 | | HostFunction::ext_offchain_http_request_add_header_version_1 => { | 1968 | 0 | host_fn_not_implemented!() | 1969 | | } | 1970 | | HostFunction::ext_offchain_http_request_write_body_version_1 => { | 1971 | 0 | host_fn_not_implemented!() | 1972 | | } | 1973 | 0 | HostFunction::ext_offchain_http_response_wait_version_1 => host_fn_not_implemented!(), | 1974 | | HostFunction::ext_offchain_http_response_headers_version_1 => { | 1975 | 0 | host_fn_not_implemented!() | 1976 | | } | 1977 | | HostFunction::ext_offchain_http_response_read_body_version_1 => { | 1978 | 0 | host_fn_not_implemented!() | 1979 | | } | 1980 | | HostFunction::ext_trie_blake2_256_root_version_1 | 1981 | | | HostFunction::ext_trie_blake2_256_root_version_2 | 1982 | | | HostFunction::ext_trie_keccak_256_root_version_1 | 1983 | | | HostFunction::ext_trie_keccak_256_root_version_2 => { | 1984 | 0 | let state_version = if matches!( | 1985 | 0 | host_fn, | 1986 | | HostFunction::ext_trie_blake2_256_root_version_2 | 1987 | | | HostFunction::ext_trie_keccak_256_root_version_2 | 1988 | | ) { | 1989 | 0 | expect_state_version!(1) | 1990 | | } else { | 1991 | 0 | TrieEntryVersion::V0 | 1992 | | }; | 1993 | | | 1994 | 0 | let result = { | 1995 | 0 | let input = expect_pointer_size!(0); | 1996 | 0 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = | 1997 | 0 | nom::combinator::all_consuming(nom::combinator::flat_map( | 1998 | 0 | crate::util::nom_scale_compact_usize, | 1999 | 0 | |num_elems| { | 2000 | | nom::multi::many_m_n( | 2001 | | num_elems, | 2002 | | num_elems, | 2003 | | nom::sequence::tuple(( | 2004 | | nom::combinator::flat_map( | 2005 | | crate::util::nom_scale_compact_usize, | 2006 | | nom::bytes::streaming::take, | 2007 | | ), | 2008 | | nom::combinator::flat_map( | 2009 | | crate::util::nom_scale_compact_usize, | 2010 | | nom::bytes::streaming::take, | 2011 | | ), | 2012 | | )), | 2013 | | ) | 2014 | 0 | }, | 2015 | 0 | ))(input.as_ref()) | 2016 | 0 | .map(|(_, parse_result)| parse_result); | 2017 | 0 |
| 2018 | 0 | match parsing_result { | 2019 | 0 | Ok(elements) => Ok(trie::trie_root( | 2020 | 0 | state_version, | 2021 | 0 | if matches!( | 2022 | 0 | host_fn, | 2023 | | HostFunction::ext_trie_blake2_256_root_version_1 | 2024 | | | HostFunction::ext_trie_blake2_256_root_version_2 | 2025 | | ) { | 2026 | 0 | trie::HashFunction::Blake2 | 2027 | | } else { | 2028 | 0 | trie::HashFunction::Keccak256 | 2029 | | }, | 2030 | 0 | &elements[..], | 2031 | | )), | 2032 | 0 | Err(_) => Err(()), | 2033 | | } | 2034 | | }; | 2035 | | | 2036 | 0 | match result { | 2037 | 0 | Ok(out) => self | 2038 | 0 | .inner | 2039 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&out)), | 2040 | 0 | Err(()) => HostVm::Error { | 2041 | 0 | error: Error::ParamDecodeError, | 2042 | 0 | prototype: self.inner.into_prototype(), | 2043 | 0 | }, | 2044 | | } | 2045 | | } | 2046 | | HostFunction::ext_trie_blake2_256_ordered_root_version_1 | 2047 | | | HostFunction::ext_trie_blake2_256_ordered_root_version_2 | 2048 | | | HostFunction::ext_trie_keccak_256_ordered_root_version_1 | 2049 | | | HostFunction::ext_trie_keccak_256_ordered_root_version_2 => { | 2050 | 0 | let state_version = if matches!( | 2051 | 0 | host_fn, | 2052 | | HostFunction::ext_trie_blake2_256_ordered_root_version_2 | 2053 | | | HostFunction::ext_trie_keccak_256_ordered_root_version_2 | 2054 | | ) { | 2055 | 0 | expect_state_version!(1) | 2056 | | } else { | 2057 | 0 | TrieEntryVersion::V0 | 2058 | | }; | 2059 | | | 2060 | 0 | let result = { | 2061 | 0 | let input = expect_pointer_size!(0); | 2062 | 0 | let parsing_result: Result<_, nom::Err<(&[u8], nom::error::ErrorKind)>> = | 2063 | 0 | nom::combinator::all_consuming(nom::combinator::flat_map( | 2064 | 0 | crate::util::nom_scale_compact_usize, | 2065 | 0 | |num_elems| { | 2066 | | nom::multi::many_m_n( | 2067 | | num_elems, | 2068 | | num_elems, | 2069 | | nom::combinator::flat_map( | 2070 | | crate::util::nom_scale_compact_usize, | 2071 | | nom::bytes::streaming::take, | 2072 | | ), | 2073 | | ) | 2074 | 0 | }, | 2075 | 0 | ))(input.as_ref()) | 2076 | 0 | .map(|(_, parse_result)| parse_result); | 2077 | 0 |
| 2078 | 0 | match parsing_result { | 2079 | 0 | Ok(elements) => Ok(trie::ordered_root( | 2080 | 0 | state_version, | 2081 | 0 | if matches!( | 2082 | 0 | host_fn, | 2083 | | HostFunction::ext_trie_blake2_256_ordered_root_version_1 | 2084 | | | HostFunction::ext_trie_blake2_256_ordered_root_version_2 | 2085 | | ) { | 2086 | 0 | trie::HashFunction::Blake2 | 2087 | | } else { | 2088 | 0 | trie::HashFunction::Keccak256 | 2089 | | }, | 2090 | 0 | &elements[..], | 2091 | | )), | 2092 | 0 | Err(_) => Err(()), | 2093 | | } | 2094 | | }; | 2095 | | | 2096 | 0 | match result { | 2097 | 0 | Ok(out) => self | 2098 | 0 | .inner | 2099 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(&out)), | 2100 | 0 | Err(()) => HostVm::Error { | 2101 | 0 | error: Error::ParamDecodeError, | 2102 | 0 | prototype: self.inner.into_prototype(), | 2103 | 0 | }, | 2104 | | } | 2105 | | } | 2106 | 0 | HostFunction::ext_trie_blake2_256_verify_proof_version_1 => host_fn_not_implemented!(), | 2107 | 0 | HostFunction::ext_trie_blake2_256_verify_proof_version_2 => host_fn_not_implemented!(), | 2108 | 0 | HostFunction::ext_trie_keccak_256_verify_proof_version_1 => host_fn_not_implemented!(), | 2109 | 0 | HostFunction::ext_trie_keccak_256_verify_proof_version_2 => host_fn_not_implemented!(), | 2110 | | HostFunction::ext_misc_print_num_version_1 => { | 2111 | 0 | let num = match params[0] { | 2112 | 0 | vm::WasmValue::I64(v) => u64::from_ne_bytes(v.to_ne_bytes()), | 2113 | | // The signatures are checked at initialization and the Wasm VM ensures that | 2114 | | // the proper parameter types are provided. | 2115 | 0 | _ => unreachable!(), | 2116 | | }; | 2117 | | | 2118 | 0 | HostVm::LogEmit(LogEmit { | 2119 | 0 | inner: self.inner, | 2120 | 0 | log_entry: LogEmitInner::Num(num), | 2121 | 0 | }) | 2122 | | } | 2123 | | HostFunction::ext_misc_print_utf8_version_1 => { | 2124 | 0 | let (str_ptr, str_size) = expect_pointer_size_raw!(0); | 2125 | | | 2126 | 0 | let utf8_check = str::from_utf8( | 2127 | 0 | self.inner | 2128 | 0 | .vm | 2129 | 0 | .read_memory(str_ptr, str_size) | 2130 | 0 | .unwrap_or_else(|_| unreachable!()) | 2131 | 0 | .as_ref(), | 2132 | 0 | ) | 2133 | 0 | .map(|_| ()); | 2134 | 0 | if let Err(error) = utf8_check { | 2135 | 0 | return HostVm::Error { | 2136 | 0 | error: Error::Utf8Error { | 2137 | 0 | function: host_fn.name(), | 2138 | 0 | param_num: 2, | 2139 | 0 | error, | 2140 | 0 | }, | 2141 | 0 | prototype: self.inner.into_prototype(), | 2142 | 0 | }; | 2143 | 0 | } | 2144 | 0 |
| 2145 | 0 | HostVm::LogEmit(LogEmit { | 2146 | 0 | inner: self.inner, | 2147 | 0 | log_entry: LogEmitInner::Utf8 { str_ptr, str_size }, | 2148 | 0 | }) | 2149 | | } | 2150 | | HostFunction::ext_misc_print_hex_version_1 => { | 2151 | 0 | let (data_ptr, data_size) = expect_pointer_size_raw!(0); | 2152 | 0 | HostVm::LogEmit(LogEmit { | 2153 | 0 | inner: self.inner, | 2154 | 0 | log_entry: LogEmitInner::Hex { | 2155 | 0 | data_ptr, | 2156 | 0 | data_size, | 2157 | 0 | }, | 2158 | 0 | }) | 2159 | | } | 2160 | | HostFunction::ext_misc_runtime_version_version_1 => { | 2161 | 0 | let (wasm_blob_ptr, wasm_blob_size) = expect_pointer_size_raw!(0); | 2162 | 0 | HostVm::CallRuntimeVersion(CallRuntimeVersion { | 2163 | 0 | inner: self.inner, | 2164 | 0 | wasm_blob_ptr, | 2165 | 0 | wasm_blob_size, | 2166 | 0 | }) | 2167 | | } | 2168 | | HostFunction::ext_allocator_malloc_version_1 => { | 2169 | 2.37k | let size = expect_u32!(0); | 2170 | | | 2171 | 2.37k | let ptr = match self.inner.alloc(host_fn.name(), size) { | 2172 | 2.37k | Ok(p) => p, | 2173 | 0 | Err(error) => { | 2174 | 0 | return HostVm::Error { | 2175 | 0 | error, | 2176 | 0 | prototype: self.inner.into_prototype(), | 2177 | 0 | } | 2178 | | } | 2179 | | }; | 2180 | | | 2181 | 2.37k | let ptr_i32 = i32::from_ne_bytes(ptr.to_ne_bytes()); | 2182 | 2.37k | HostVm::ReadyToRun(ReadyToRun { | 2183 | 2.37k | resume_value: Some(vm::WasmValue::I32(ptr_i32)), | 2184 | 2.37k | inner: self.inner, | 2185 | 2.37k | }) | 2186 | | } | 2187 | | HostFunction::ext_allocator_free_version_1 => { | 2188 | 2.41k | let pointer = expect_u32!(0); | 2189 | 2.41k | match self.inner.allocator.deallocate( | 2190 | 2.41k | &mut MemAccess { | 2191 | 2.41k | vm: MemAccessVm::Running(&mut self.inner.vm), | 2192 | 2.41k | memory_total_pages: self.inner.common.memory_total_pages, | 2193 | 2.41k | }, | 2194 | 2.41k | pointer, | 2195 | 2.41k | ) { | 2196 | 2.41k | Ok(()) => {} | 2197 | | Err(_) => { | 2198 | 0 | return HostVm::Error { | 2199 | 0 | error: Error::FreeError { pointer }, | 2200 | 0 | prototype: self.inner.into_prototype(), | 2201 | 0 | } | 2202 | | } | 2203 | | }; | 2204 | | | 2205 | 2.41k | HostVm::ReadyToRun(ReadyToRun { | 2206 | 2.41k | resume_value: None, | 2207 | 2.41k | inner: self.inner, | 2208 | 2.41k | }) | 2209 | | } | 2210 | | HostFunction::ext_logging_log_version_1 => { | 2211 | 0 | let log_level = expect_u32!(0); | 2212 | | | 2213 | 0 | let (target_str_ptr, target_str_size) = expect_pointer_size_raw!(1); | 2214 | 0 | let target_utf8_check = str::from_utf8( | 2215 | 0 | self.inner | 2216 | 0 | .vm | 2217 | 0 | .read_memory(target_str_ptr, target_str_size) | 2218 | 0 | .unwrap_or_else(|_| unreachable!()) | 2219 | 0 | .as_ref(), | 2220 | 0 | ) | 2221 | 0 | .map(|_| ()); | 2222 | 0 | if let Err(error) = target_utf8_check { | 2223 | 0 | return HostVm::Error { | 2224 | 0 | error: Error::Utf8Error { | 2225 | 0 | function: host_fn.name(), | 2226 | 0 | param_num: 1, | 2227 | 0 | error, | 2228 | 0 | }, | 2229 | 0 | prototype: self.inner.into_prototype(), | 2230 | 0 | }; | 2231 | 0 | } | 2232 | | | 2233 | 0 | let (msg_str_ptr, msg_str_size) = expect_pointer_size_raw!(2); | 2234 | 0 | let msg_utf8_check = str::from_utf8( | 2235 | 0 | self.inner | 2236 | 0 | .vm | 2237 | 0 | .read_memory(msg_str_ptr, msg_str_size) | 2238 | 0 | .unwrap_or_else(|_| unreachable!()) | 2239 | 0 | .as_ref(), | 2240 | 0 | ) | 2241 | 0 | .map(|_| ()); | 2242 | 0 | if let Err(error) = msg_utf8_check { | 2243 | 0 | return HostVm::Error { | 2244 | 0 | error: Error::Utf8Error { | 2245 | 0 | function: host_fn.name(), | 2246 | 0 | param_num: 2, | 2247 | 0 | error, | 2248 | 0 | }, | 2249 | 0 | prototype: self.inner.into_prototype(), | 2250 | 0 | }; | 2251 | 0 | } | 2252 | 0 |
| 2253 | 0 | HostVm::LogEmit(LogEmit { | 2254 | 0 | inner: self.inner, | 2255 | 0 | log_entry: LogEmitInner::Log { | 2256 | 0 | log_level, | 2257 | 0 | target_str_ptr, | 2258 | 0 | target_str_size, | 2259 | 0 | msg_str_ptr, | 2260 | 0 | msg_str_size, | 2261 | 0 | }, | 2262 | 0 | }) | 2263 | | } | 2264 | | HostFunction::ext_logging_max_level_version_1 => { | 2265 | 127 | HostVm::GetMaxLogLevel(GetMaxLogLevel { inner: self.inner }) | 2266 | | } | 2267 | | HostFunction::ext_panic_handler_abort_on_panic_version_1 => { | 2268 | 0 | let message = { | 2269 | 0 | let message_bytes = expect_pointer_size!(0); | 2270 | 0 | str::from_utf8(message_bytes.as_ref()).map(|msg| msg.to_owned()) | 2271 | 0 | }; | 2272 | 0 |
| 2273 | 0 | match message { | 2274 | 0 | Ok(message) => HostVm::Error { | 2275 | 0 | error: Error::AbortOnPanic { message }, | 2276 | 0 | prototype: self.inner.into_prototype(), | 2277 | 0 | }, | 2278 | 0 | Err(error) => HostVm::Error { | 2279 | 0 | error: Error::Utf8Error { | 2280 | 0 | function: host_fn.name(), | 2281 | 0 | param_num: 0, | 2282 | 0 | error, | 2283 | 0 | }, | 2284 | 0 | prototype: self.inner.into_prototype(), | 2285 | 0 | }, | 2286 | | } | 2287 | | } | 2288 | | } | 2289 | 5.20k | } |
|
2290 | | } |
2291 | | |
2292 | | impl fmt::Debug for ReadyToRun { |
2293 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2294 | 0 | f.debug_tuple("ReadyToRun").finish() |
2295 | 0 | } Unexecuted instantiation: _RNvXs3_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_10ReadyToRunNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs3_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_10ReadyToRunNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
2296 | | } |
2297 | | |
2298 | | /// Function execution has succeeded. Contains the return value of the call. |
2299 | | /// |
2300 | | /// The trie root hash of all the child tries must be recalculated and written to the main trie |
2301 | | /// similar to when a [`ExternalStorageRoot`] with a `child_trie` of `None` is generated. See the |
2302 | | /// documentation of [`ExternalStorageRoot`]. |
2303 | | pub struct Finished { |
2304 | | inner: Box<Inner>, |
2305 | | |
2306 | | /// Pointer to the value returned by the VM. Guaranteed to be in range. |
2307 | | value_ptr: u32, |
2308 | | /// Size of the value returned by the VM. Guaranteed to be in range. |
2309 | | value_size: u32, |
2310 | | } |
2311 | | |
2312 | | impl Finished { |
2313 | | /// Returns the value the called function has returned. |
2314 | 158 | pub fn value(&'_ self) -> impl AsRef<[u8]> + '_ { |
2315 | 158 | self.inner |
2316 | 158 | .vm |
2317 | 158 | .read_memory(self.value_ptr, self.value_size) |
2318 | 158 | .unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvMs4_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_8Finished5value0Bb_ Unexecuted instantiation: _RNCNvMs4_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_8Finished5value0Bb_ |
2319 | 158 | } _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_8Finished5value Line | Count | Source | 2314 | 31 | pub fn value(&'_ self) -> impl AsRef<[u8]> + '_ { | 2315 | 31 | self.inner | 2316 | 31 | .vm | 2317 | 31 | .read_memory(self.value_ptr, self.value_size) | 2318 | 31 | .unwrap_or_else(|_| unreachable!()) | 2319 | 31 | } |
_RNvMs4_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_8Finished5value Line | Count | Source | 2314 | 127 | pub fn value(&'_ self) -> impl AsRef<[u8]> + '_ { | 2315 | 127 | self.inner | 2316 | 127 | .vm | 2317 | 127 | .read_memory(self.value_ptr, self.value_size) | 2318 | 127 | .unwrap_or_else(|_| unreachable!()) | 2319 | 127 | } |
|
2320 | | |
2321 | | /// Turns the virtual machine back into a prototype. |
2322 | 135 | pub fn into_prototype(self) -> HostVmPrototype { |
2323 | 135 | self.inner.into_prototype() |
2324 | 135 | } _RNvMs4_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_8Finished14into_prototype Line | Count | Source | 2322 | 9 | pub fn into_prototype(self) -> HostVmPrototype { | 2323 | 9 | self.inner.into_prototype() | 2324 | 9 | } |
_RNvMs4_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_8Finished14into_prototype Line | Count | Source | 2322 | 126 | pub fn into_prototype(self) -> HostVmPrototype { | 2323 | 126 | self.inner.into_prototype() | 2324 | 126 | } |
|
2325 | | } |
2326 | | |
2327 | | impl fmt::Debug for Finished { |
2328 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2329 | 0 | f.debug_tuple("Finished").finish() |
2330 | 0 | } Unexecuted instantiation: _RNvXs5_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_8FinishedNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs5_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_8FinishedNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
2331 | | } |
2332 | | |
2333 | | /// Must provide the value of a storage entry. |
2334 | | pub struct ExternalStorageGet { |
2335 | | inner: Box<Inner>, |
2336 | | |
2337 | | /// Function currently being called by the Wasm code. Refers to an index within |
2338 | | /// [`VmCommon::registered_functions`]. Guaranteed to be [`FunctionImport::Resolved`̀]. |
2339 | | calling: usize, |
2340 | | |
2341 | | /// Used only for the `ext_storage_read_version_1` function. Stores the pointer where the |
2342 | | /// output should be stored. |
2343 | | value_out_ptr: Option<u32>, |
2344 | | |
2345 | | /// Pointer to the key whose value must be loaded. Guaranteed to be in range. |
2346 | | key_ptr: u32, |
2347 | | /// Size of the key whose value must be loaded. Guaranteed to be in range. |
2348 | | key_size: u32, |
2349 | | /// Pointer and size to the default child trie. `None` if main trie. Guaranteed to be in range. |
2350 | | child_trie_ptr_size: Option<(u32, u32)>, |
2351 | | /// Offset within the value that the Wasm VM requires. |
2352 | | offset: u32, |
2353 | | /// Maximum size that the Wasm VM would accept. |
2354 | | max_size: u32, |
2355 | | } |
2356 | | |
2357 | | impl ExternalStorageGet { |
2358 | | /// Returns the key whose value must be provided back with [`ExternalStorageGet::resume`]. |
2359 | 2.90k | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
2360 | 2.90k | self.inner |
2361 | 2.90k | .vm |
2362 | 2.90k | .read_memory(self.key_ptr, self.key_size) |
2363 | 2.90k | .unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageGet3key0Bb_ Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageGet3key0Bb_ |
2364 | 2.90k | } _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageGet3key Line | Count | Source | 2359 | 2.73k | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { | 2360 | 2.73k | self.inner | 2361 | 2.73k | .vm | 2362 | 2.73k | .read_memory(self.key_ptr, self.key_size) | 2363 | 2.73k | .unwrap_or_else(|_| unreachable!()) | 2364 | 2.73k | } |
_RNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageGet3key Line | Count | Source | 2359 | 168 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { | 2360 | 168 | self.inner | 2361 | 168 | .vm | 2362 | 168 | .read_memory(self.key_ptr, self.key_size) | 2363 | 168 | .unwrap_or_else(|_| unreachable!()) | 2364 | 168 | } |
|
2365 | | |
2366 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
2367 | 811 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
2368 | 811 | if let Some((child_trie_ptr, child_trie_size12 )) = self.child_trie_ptr_size { |
2369 | 12 | let child_trie = self |
2370 | 12 | .inner |
2371 | 12 | .vm |
2372 | 12 | .read_memory(child_trie_ptr, child_trie_size) |
2373 | 12 | .unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageGet10child_trie0Bb_ Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageGet10child_trie0Bb_ |
2374 | 12 | Some(child_trie) |
2375 | | } else { |
2376 | 799 | None |
2377 | | } |
2378 | 811 | } _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageGet10child_trie Line | Count | Source | 2367 | 727 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { | 2368 | 727 | if let Some((child_trie_ptr, child_trie_size12 )) = self.child_trie_ptr_size { | 2369 | 12 | let child_trie = self | 2370 | 12 | .inner | 2371 | 12 | .vm | 2372 | 12 | .read_memory(child_trie_ptr, child_trie_size) | 2373 | 12 | .unwrap_or_else(|_| unreachable!()); | 2374 | 12 | Some(child_trie) | 2375 | | } else { | 2376 | 715 | None | 2377 | | } | 2378 | 727 | } |
_RNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageGet10child_trie Line | Count | Source | 2367 | 84 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { | 2368 | 84 | if let Some((child_trie_ptr, child_trie_size0 )) = self.child_trie_ptr_size { | 2369 | 0 | let child_trie = self | 2370 | 0 | .inner | 2371 | 0 | .vm | 2372 | 0 | .read_memory(child_trie_ptr, child_trie_size) | 2373 | 0 | .unwrap_or_else(|_| unreachable!()); | 2374 | 0 | Some(child_trie) | 2375 | | } else { | 2376 | 84 | None | 2377 | | } | 2378 | 84 | } |
|
2379 | | |
2380 | | /// Offset within the value that is requested. |
2381 | 0 | pub fn offset(&self) -> u32 { |
2382 | 0 | self.offset |
2383 | 0 | } Unexecuted instantiation: _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageGet6offset Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageGet6offset |
2384 | | |
2385 | | /// Maximum size of the value to pass back. |
2386 | | /// |
2387 | | /// > **Note**: This can be 0 if we only want to know whether a value exists. |
2388 | 0 | pub fn max_size(&self) -> u32 { |
2389 | 0 | self.max_size |
2390 | 0 | } Unexecuted instantiation: _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageGet8max_size Unexecuted instantiation: _RNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageGet8max_size |
2391 | | |
2392 | | /// Same as [`ExternalStorageGet::resume`], but passes the full value, without taking the |
2393 | | /// offset and maximum size into account. |
2394 | | /// |
2395 | | /// This is a convenient function that automatically applies the offset and maximum size, to |
2396 | | /// use when the full storage value is already present in memory. |
2397 | 687 | pub fn resume_full_value(self, value: Option<&[u8]>) -> HostVm { |
2398 | 687 | if let Some(value598 ) = value { |
2399 | 598 | if usize::try_from(self.offset).unwrap_or_else(|_| unreachable!()0 ) < value.len() { Unexecuted instantiation: _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageGet17resume_full_value0Bb_ Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageGet17resume_full_value0Bb_ |
2400 | 598 | let value_slice = |
2401 | 598 | &value[usize::try_from(self.offset).unwrap_or_else(|_| unreachable!()0 )..]; Unexecuted instantiation: _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageGet17resume_full_values_0Bb_ Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageGet17resume_full_values_0Bb_ |
2402 | 598 | if usize::try_from(self.max_size).unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageGet17resume_full_values0_0Bb_ Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageGet17resume_full_values0_0Bb_ |
2403 | 598 | < value_slice.len() |
2404 | | { |
2405 | 10 | let value_slice = &value_slice |
2406 | 10 | [..usize::try_from(self.max_size).unwrap_or_else(|_| unreachable!()0 )]; Unexecuted instantiation: _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageGet17resume_full_values1_0Bb_ Unexecuted instantiation: _RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageGet17resume_full_values1_0Bb_ |
2407 | 10 | self.resume(Some((value_slice, value.len()))) |
2408 | | } else { |
2409 | 588 | self.resume(Some((value_slice, value.len()))) |
2410 | | } |
2411 | | } else { |
2412 | 0 | self.resume(Some((&[], value.len()))) |
2413 | | } |
2414 | | } else { |
2415 | 89 | self.resume(None) |
2416 | | } |
2417 | 687 | } _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageGet17resume_full_value Line | Count | Source | 2397 | 603 | pub fn resume_full_value(self, value: Option<&[u8]>) -> HostVm { | 2398 | 603 | if let Some(value514 ) = value { | 2399 | 514 | if usize::try_from(self.offset).unwrap_or_else(|_| unreachable!()) < value.len() { | 2400 | 514 | let value_slice = | 2401 | 514 | &value[usize::try_from(self.offset).unwrap_or_else(|_| unreachable!())..]; | 2402 | 514 | if usize::try_from(self.max_size).unwrap_or_else(|_| unreachable!()) | 2403 | 514 | < value_slice.len() | 2404 | | { | 2405 | 10 | let value_slice = &value_slice | 2406 | 10 | [..usize::try_from(self.max_size).unwrap_or_else(|_| unreachable!())]; | 2407 | 10 | self.resume(Some((value_slice, value.len()))) | 2408 | | } else { | 2409 | 504 | self.resume(Some((value_slice, value.len()))) | 2410 | | } | 2411 | | } else { | 2412 | 0 | self.resume(Some((&[], value.len()))) | 2413 | | } | 2414 | | } else { | 2415 | 89 | self.resume(None) | 2416 | | } | 2417 | 603 | } |
_RNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageGet17resume_full_value Line | Count | Source | 2397 | 84 | pub fn resume_full_value(self, value: Option<&[u8]>) -> HostVm { | 2398 | 84 | if let Some(value) = value { | 2399 | 84 | if usize::try_from(self.offset).unwrap_or_else(|_| unreachable!()) < value.len() { | 2400 | 84 | let value_slice = | 2401 | 84 | &value[usize::try_from(self.offset).unwrap_or_else(|_| unreachable!())..]; | 2402 | 84 | if usize::try_from(self.max_size).unwrap_or_else(|_| unreachable!()) | 2403 | 84 | < value_slice.len() | 2404 | | { | 2405 | 0 | let value_slice = &value_slice | 2406 | 0 | [..usize::try_from(self.max_size).unwrap_or_else(|_| unreachable!())]; | 2407 | 0 | self.resume(Some((value_slice, value.len()))) | 2408 | | } else { | 2409 | 84 | self.resume(Some((value_slice, value.len()))) | 2410 | | } | 2411 | | } else { | 2412 | 0 | self.resume(Some((&[], value.len()))) | 2413 | | } | 2414 | | } else { | 2415 | 0 | self.resume(None) | 2416 | | } | 2417 | 84 | } |
|
2418 | | |
2419 | | /// Writes the storage value in the Wasm VM's memory and prepares the virtual machine to |
2420 | | /// resume execution. |
2421 | | /// |
2422 | | /// The value to provide must be the value of that key starting at the offset returned by |
2423 | | /// [`ExternalStorageGet::offset`]. If the offset is out of range, an empty slice must be |
2424 | | /// passed. |
2425 | | /// |
2426 | | /// If `Some`, the total size of the value, without taking [`ExternalStorageGet::offset`] or |
2427 | | /// [`ExternalStorageGet::max_size`] into account, must additionally be provided. |
2428 | | /// |
2429 | | /// If [`ExternalStorageGet::child_trie`] returns `Some` but the child trie doesn't exist, |
2430 | | /// then `None` must be provided. |
2431 | | /// |
2432 | | /// The value must not be longer than what [`ExternalStorageGet::max_size`] returns. |
2433 | | /// |
2434 | | /// # Panic |
2435 | | /// |
2436 | | /// Panics if the value is longer than what [`ExternalStorageGet::max_size`] returns. |
2437 | | /// |
2438 | 687 | pub fn resume(self, value: Option<(&[u8], usize)>) -> HostVm { |
2439 | 687 | self.resume_vectored( |
2440 | 687 | value |
2441 | 687 | .as_ref() |
2442 | 687 | .map(|(value, size)| (iter::once(&value[..]), *size)598 ), _RNCNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageGet6resume0Bb_ Line | Count | Source | 2442 | 514 | .map(|(value, size)| (iter::once(&value[..]), *size)), |
_RNCNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageGet6resume0Bb_ Line | Count | Source | 2442 | 84 | .map(|(value, size)| (iter::once(&value[..]), *size)), |
|
2443 | 687 | ) |
2444 | 687 | } _RNvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageGet6resume Line | Count | Source | 2438 | 603 | pub fn resume(self, value: Option<(&[u8], usize)>) -> HostVm { | 2439 | 603 | self.resume_vectored( | 2440 | 603 | value | 2441 | 603 | .as_ref() | 2442 | 603 | .map(|(value, size)| (iter::once(&value[..]), *size)), | 2443 | 603 | ) | 2444 | 603 | } |
_RNvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageGet6resume Line | Count | Source | 2438 | 84 | pub fn resume(self, value: Option<(&[u8], usize)>) -> HostVm { | 2439 | 84 | self.resume_vectored( | 2440 | 84 | value | 2441 | 84 | .as_ref() | 2442 | 84 | .map(|(value, size)| (iter::once(&value[..]), *size)), | 2443 | 84 | ) | 2444 | 84 | } |
|
2445 | | |
2446 | | /// Similar to [`ExternalStorageGet::resume`], but allows passing the value as a list of |
2447 | | /// buffers whose concatenation forms the actual value. |
2448 | | /// |
2449 | | /// If `Some`, the total size of the value, without taking [`ExternalStorageGet::offset`] or |
2450 | | /// [`ExternalStorageGet::max_size`] into account, must additionally be provided. |
2451 | | /// |
2452 | | /// # Panic |
2453 | | /// |
2454 | | /// See [`ExternalStorageGet::resume`]. |
2455 | | /// |
2456 | 687 | pub fn resume_vectored( |
2457 | 687 | mut self, |
2458 | 687 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>> + Clone, usize)>, |
2459 | 687 | ) -> HostVm { |
2460 | 687 | let host_fn = match self.inner.common.registered_functions[self.calling] { |
2461 | 687 | FunctionImport::Resolved(f) => f, |
2462 | 0 | FunctionImport::Unresolved { .. } => unreachable!(), |
2463 | | }; |
2464 | | |
2465 | 687 | match host_fn { |
2466 | | HostFunction::ext_storage_get_version_1 |
2467 | | | HostFunction::ext_default_child_storage_get_version_1 => { |
2468 | 657 | if let Some((value, value_total_len588 )) = value { |
2469 | | // Writing `Some(value)`. |
2470 | 588 | debug_assert_eq!( |
2471 | 588 | value.clone().fold(0, |a, b| a + b.as_ref().len()), _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEs3_0Bc_ Line | Count | Source | 2471 | 504 | value.clone().fold(0, |a, b| a + b.as_ref().len()), |
_RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EEs3_0Bc_ Line | Count | Source | 2471 | 84 | value.clone().fold(0, |a, b| a + b.as_ref().len()), |
|
2472 | | value_total_len |
2473 | | ); |
2474 | 588 | let value_len_enc = util::encode_scale_compact_usize(value_total_len); |
2475 | 588 | self.inner.alloc_write_and_return_pointer_size( |
2476 | 588 | host_fn.name(), |
2477 | 588 | iter::once(&[1][..]) |
2478 | 588 | .chain(iter::once(value_len_enc.as_ref())) |
2479 | 588 | .map(either::Left) |
2480 | 588 | .chain(value.map(either::Right)), |
2481 | 588 | ) |
2482 | | } else { |
2483 | | // Write a SCALE-encoded `None`. |
2484 | 69 | self.inner |
2485 | 69 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&[0])) |
2486 | | } |
2487 | | } |
2488 | | HostFunction::ext_storage_read_version_1 |
2489 | | | HostFunction::ext_default_child_storage_read_version_1 => { |
2490 | 14 | let outcome = if let Some((value, value_total_len2 )) = value { |
2491 | 2 | let mut remaining_max_allowed = |
2492 | 2 | usize::try_from(self.max_size).unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredppE0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredppE0Bc_ |
2493 | 2 | let mut offset = self.value_out_ptr.unwrap_or_else(|| unreachable!()0 ); Unexecuted instantiation: _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEs_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EEs_0Bc_ |
2494 | 4 | for value2 in value { |
2495 | 2 | let value = value.as_ref(); |
2496 | 2 | assert!(value.len() <= remaining_max_allowed); |
2497 | 2 | remaining_max_allowed -= value.len(); |
2498 | 2 | self.inner |
2499 | 2 | .vm |
2500 | 2 | .write_memory(offset, value) |
2501 | 2 | .unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEs0_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EEs0_0Bc_ |
2502 | 2 | offset += u32::try_from(value.len()).unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEs1_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EEs1_0Bc_ |
2503 | | } |
2504 | | |
2505 | | // Note: the https://github.com/paritytech/substrate/pull/7084 PR has changed |
2506 | | // the meaning of this return value. |
2507 | 2 | Some( |
2508 | 2 | u32::try_from(value_total_len).unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEs2_0Bc_ Unexecuted instantiation: _RNCINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EEs2_0Bc_ |
2509 | 2 | - self.offset, |
2510 | 2 | ) |
2511 | | } else { |
2512 | 12 | None |
2513 | | }; |
2514 | | |
2515 | 14 | return self.inner.alloc_write_and_return_pointer_size( |
2516 | 14 | host_fn.name(), |
2517 | 14 | if let Some(outcome2 ) = outcome { |
2518 | 2 | either::Left( |
2519 | 2 | iter::once(either::Left([1u8])) |
2520 | 2 | .chain(iter::once(either::Right(outcome.to_le_bytes()))), |
2521 | 2 | ) |
2522 | | } else { |
2523 | 12 | either::Right(iter::once(either::Left([0u8]))) |
2524 | | }, |
2525 | | ); |
2526 | | } |
2527 | | HostFunction::ext_storage_exists_version_1 |
2528 | | | HostFunction::ext_default_child_storage_exists_version_1 => { |
2529 | | HostVm::ReadyToRun(ReadyToRun { |
2530 | 16 | inner: self.inner, |
2531 | 16 | resume_value: Some(if value.is_some() { |
2532 | 8 | vm::WasmValue::I32(1) |
2533 | | } else { |
2534 | 8 | vm::WasmValue::I32(0) |
2535 | | }), |
2536 | | }) |
2537 | | } |
2538 | 0 | _ => unreachable!(), |
2539 | | } |
2540 | 687 | } _RINvMs6_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1p_EEBa_ Line | Count | Source | 2456 | 603 | pub fn resume_vectored( | 2457 | 603 | mut self, | 2458 | 603 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>> + Clone, usize)>, | 2459 | 603 | ) -> HostVm { | 2460 | 603 | let host_fn = match self.inner.common.registered_functions[self.calling] { | 2461 | 603 | FunctionImport::Resolved(f) => f, | 2462 | 0 | FunctionImport::Unresolved { .. } => unreachable!(), | 2463 | | }; | 2464 | | | 2465 | 603 | match host_fn { | 2466 | | HostFunction::ext_storage_get_version_1 | 2467 | | | HostFunction::ext_default_child_storage_get_version_1 => { | 2468 | 573 | if let Some((value, value_total_len504 )) = value { | 2469 | | // Writing `Some(value)`. | 2470 | 504 | debug_assert_eq!( | 2471 | 504 | value.clone().fold(0, |a, b| a + b.as_ref().len()), | 2472 | | value_total_len | 2473 | | ); | 2474 | 504 | let value_len_enc = util::encode_scale_compact_usize(value_total_len); | 2475 | 504 | self.inner.alloc_write_and_return_pointer_size( | 2476 | 504 | host_fn.name(), | 2477 | 504 | iter::once(&[1][..]) | 2478 | 504 | .chain(iter::once(value_len_enc.as_ref())) | 2479 | 504 | .map(either::Left) | 2480 | 504 | .chain(value.map(either::Right)), | 2481 | 504 | ) | 2482 | | } else { | 2483 | | // Write a SCALE-encoded `None`. | 2484 | 69 | self.inner | 2485 | 69 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&[0])) | 2486 | | } | 2487 | | } | 2488 | | HostFunction::ext_storage_read_version_1 | 2489 | | | HostFunction::ext_default_child_storage_read_version_1 => { | 2490 | 14 | let outcome = if let Some((value, value_total_len2 )) = value { | 2491 | 2 | let mut remaining_max_allowed = | 2492 | 2 | usize::try_from(self.max_size).unwrap_or_else(|_| unreachable!()); | 2493 | 2 | let mut offset = self.value_out_ptr.unwrap_or_else(|| unreachable!()); | 2494 | 4 | for value2 in value { | 2495 | 2 | let value = value.as_ref(); | 2496 | 2 | assert!(value.len() <= remaining_max_allowed); | 2497 | 2 | remaining_max_allowed -= value.len(); | 2498 | 2 | self.inner | 2499 | 2 | .vm | 2500 | 2 | .write_memory(offset, value) | 2501 | 2 | .unwrap_or_else(|_| unreachable!()); | 2502 | 2 | offset += u32::try_from(value.len()).unwrap_or_else(|_| unreachable!()); | 2503 | | } | 2504 | | | 2505 | | // Note: the https://github.com/paritytech/substrate/pull/7084 PR has changed | 2506 | | // the meaning of this return value. | 2507 | 2 | Some( | 2508 | 2 | u32::try_from(value_total_len).unwrap_or_else(|_| unreachable!()) | 2509 | 2 | - self.offset, | 2510 | 2 | ) | 2511 | | } else { | 2512 | 12 | None | 2513 | | }; | 2514 | | | 2515 | 14 | return self.inner.alloc_write_and_return_pointer_size( | 2516 | 14 | host_fn.name(), | 2517 | 14 | if let Some(outcome2 ) = outcome { | 2518 | 2 | either::Left( | 2519 | 2 | iter::once(either::Left([1u8])) | 2520 | 2 | .chain(iter::once(either::Right(outcome.to_le_bytes()))), | 2521 | 2 | ) | 2522 | | } else { | 2523 | 12 | either::Right(iter::once(either::Left([0u8]))) | 2524 | | }, | 2525 | | ); | 2526 | | } | 2527 | | HostFunction::ext_storage_exists_version_1 | 2528 | | | HostFunction::ext_default_child_storage_exists_version_1 => { | 2529 | | HostVm::ReadyToRun(ReadyToRun { | 2530 | 16 | inner: self.inner, | 2531 | 16 | resume_value: Some(if value.is_some() { | 2532 | 8 | vm::WasmValue::I32(1) | 2533 | | } else { | 2534 | 8 | vm::WasmValue::I32(0) | 2535 | | }), | 2536 | | }) | 2537 | | } | 2538 | 0 | _ => unreachable!(), | 2539 | | } | 2540 | 603 | } |
_RINvMs6_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_18ExternalStorageGet15resume_vectoredRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEBa_ Line | Count | Source | 2456 | 84 | pub fn resume_vectored( | 2457 | 84 | mut self, | 2458 | 84 | value: Option<(impl Iterator<Item = impl AsRef<[u8]>> + Clone, usize)>, | 2459 | 84 | ) -> HostVm { | 2460 | 84 | let host_fn = match self.inner.common.registered_functions[self.calling] { | 2461 | 84 | FunctionImport::Resolved(f) => f, | 2462 | 0 | FunctionImport::Unresolved { .. } => unreachable!(), | 2463 | | }; | 2464 | | | 2465 | 84 | match host_fn { | 2466 | | HostFunction::ext_storage_get_version_1 | 2467 | | | HostFunction::ext_default_child_storage_get_version_1 => { | 2468 | 84 | if let Some((value, value_total_len)) = value { | 2469 | | // Writing `Some(value)`. | 2470 | 84 | debug_assert_eq!( | 2471 | 84 | value.clone().fold(0, |a, b| a + b.as_ref().len()), | 2472 | | value_total_len | 2473 | | ); | 2474 | 84 | let value_len_enc = util::encode_scale_compact_usize(value_total_len); | 2475 | 84 | self.inner.alloc_write_and_return_pointer_size( | 2476 | 84 | host_fn.name(), | 2477 | 84 | iter::once(&[1][..]) | 2478 | 84 | .chain(iter::once(value_len_enc.as_ref())) | 2479 | 84 | .map(either::Left) | 2480 | 84 | .chain(value.map(either::Right)), | 2481 | 84 | ) | 2482 | | } else { | 2483 | | // Write a SCALE-encoded `None`. | 2484 | 0 | self.inner | 2485 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&[0])) | 2486 | | } | 2487 | | } | 2488 | | HostFunction::ext_storage_read_version_1 | 2489 | | | HostFunction::ext_default_child_storage_read_version_1 => { | 2490 | 0 | let outcome = if let Some((value, value_total_len)) = value { | 2491 | 0 | let mut remaining_max_allowed = | 2492 | 0 | usize::try_from(self.max_size).unwrap_or_else(|_| unreachable!()); | 2493 | 0 | let mut offset = self.value_out_ptr.unwrap_or_else(|| unreachable!()); | 2494 | 0 | for value in value { | 2495 | 0 | let value = value.as_ref(); | 2496 | 0 | assert!(value.len() <= remaining_max_allowed); | 2497 | 0 | remaining_max_allowed -= value.len(); | 2498 | 0 | self.inner | 2499 | 0 | .vm | 2500 | 0 | .write_memory(offset, value) | 2501 | 0 | .unwrap_or_else(|_| unreachable!()); | 2502 | 0 | offset += u32::try_from(value.len()).unwrap_or_else(|_| unreachable!()); | 2503 | | } | 2504 | | | 2505 | | // Note: the https://github.com/paritytech/substrate/pull/7084 PR has changed | 2506 | | // the meaning of this return value. | 2507 | 0 | Some( | 2508 | 0 | u32::try_from(value_total_len).unwrap_or_else(|_| unreachable!()) | 2509 | 0 | - self.offset, | 2510 | 0 | ) | 2511 | | } else { | 2512 | 0 | None | 2513 | | }; | 2514 | | | 2515 | 0 | return self.inner.alloc_write_and_return_pointer_size( | 2516 | 0 | host_fn.name(), | 2517 | 0 | if let Some(outcome) = outcome { | 2518 | 0 | either::Left( | 2519 | 0 | iter::once(either::Left([1u8])) | 2520 | 0 | .chain(iter::once(either::Right(outcome.to_le_bytes()))), | 2521 | 0 | ) | 2522 | | } else { | 2523 | 0 | either::Right(iter::once(either::Left([0u8]))) | 2524 | | }, | 2525 | | ); | 2526 | | } | 2527 | | HostFunction::ext_storage_exists_version_1 | 2528 | | | HostFunction::ext_default_child_storage_exists_version_1 => { | 2529 | | HostVm::ReadyToRun(ReadyToRun { | 2530 | 0 | inner: self.inner, | 2531 | 0 | resume_value: Some(if value.is_some() { | 2532 | 0 | vm::WasmValue::I32(1) | 2533 | | } else { | 2534 | 0 | vm::WasmValue::I32(0) | 2535 | | }), | 2536 | | }) | 2537 | | } | 2538 | 0 | _ => unreachable!(), | 2539 | | } | 2540 | 84 | } |
|
2541 | | } |
2542 | | |
2543 | | impl fmt::Debug for ExternalStorageGet { |
2544 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2545 | 0 | f.debug_tuple("ExternalStorageGet").finish() |
2546 | 0 | } Unexecuted instantiation: _RNvXs7_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageGetNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs7_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageGetNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
2547 | | } |
2548 | | |
2549 | | /// Must set the value of a storage entry. |
2550 | | /// |
2551 | | /// If [`ExternalStorageSet::child_trie`] return `None` and [`ExternalStorageSet::key`] |
2552 | | /// returns a key that starts with `:child_storage:`, then the write must be silently ignored. |
2553 | | /// |
2554 | | /// If [`ExternalStorageSet::child_trie`] and [`ExternalStorageSet::value`] return `Some` and the |
2555 | | /// child trie doesn't exist, it must implicitly be created. |
2556 | | /// If [`ExternalStorageSet::child_trie`] returns `Some` and [`ExternalStorageSet::value`] |
2557 | | /// returns `None` and this is the last entry in the child trie, it must implicitly be destroyed. |
2558 | | pub struct ExternalStorageSet { |
2559 | | inner: Box<Inner>, |
2560 | | |
2561 | | /// Pointer to the key whose value must be set. Guaranteed to be in range. |
2562 | | key_ptr: u32, |
2563 | | /// Size of the key whose value must be set. Guaranteed to be in range. |
2564 | | key_size: u32, |
2565 | | /// Pointer and size to the default child trie key. `None` if main trie. Guaranteed to be |
2566 | | /// in range. |
2567 | | child_trie_ptr_size: Option<(u32, u32)>, |
2568 | | |
2569 | | /// Pointer and size of the value to set. `None` for clearing. Guaranteed to be in range. |
2570 | | value: Option<(u32, u32)>, |
2571 | | } |
2572 | | |
2573 | | impl ExternalStorageSet { |
2574 | | /// Returns the key whose value must be set. |
2575 | 746 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
2576 | 746 | self.inner |
2577 | 746 | .vm |
2578 | 746 | .read_memory(self.key_ptr, self.key_size) |
2579 | 746 | .unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageSet3key0Bb_ Unexecuted instantiation: _RNCNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageSet3key0Bb_ |
2580 | 746 | } _RNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageSet3key Line | Count | Source | 2575 | 746 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { | 2576 | 746 | self.inner | 2577 | 746 | .vm | 2578 | 746 | .read_memory(self.key_ptr, self.key_size) | 2579 | 746 | .unwrap_or_else(|_| unreachable!()) | 2580 | 746 | } |
Unexecuted instantiation: _RNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageSet3key |
2581 | | |
2582 | | /// If `Some`, write to the given child trie. If `None`, write to the main trie. |
2583 | | /// |
2584 | | /// If [`ExternalStorageSet::value`] returns `Some` and the child trie doesn't exist, it must |
2585 | | /// implicitly be created. |
2586 | | /// If [`ExternalStorageSet::value`] returns `None` and this is the last entry in the child |
2587 | | /// trie, it must implicitly be destroyed. |
2588 | 1.12k | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
2589 | 1.12k | match &self.child_trie_ptr_size { |
2590 | 12 | Some((ptr, size)) => { |
2591 | 12 | let child_trie = self |
2592 | 12 | .inner |
2593 | 12 | .vm |
2594 | 12 | .read_memory(*ptr, *size) |
2595 | 12 | .unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageSet10child_trie0Bb_ Unexecuted instantiation: _RNCNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageSet10child_trie0Bb_ |
2596 | 12 | Some(child_trie) |
2597 | | } |
2598 | 1.11k | None => None, |
2599 | | } |
2600 | 1.12k | } _RNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageSet10child_trie Line | Count | Source | 2588 | 1.12k | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { | 2589 | 1.12k | match &self.child_trie_ptr_size { | 2590 | 12 | Some((ptr, size)) => { | 2591 | 12 | let child_trie = self | 2592 | 12 | .inner | 2593 | 12 | .vm | 2594 | 12 | .read_memory(*ptr, *size) | 2595 | 12 | .unwrap_or_else(|_| unreachable!()); | 2596 | 12 | Some(child_trie) | 2597 | | } | 2598 | 1.11k | None => None, | 2599 | | } | 2600 | 1.12k | } |
Unexecuted instantiation: _RNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageSet10child_trie |
2601 | | |
2602 | | /// Returns the value to set. |
2603 | | /// |
2604 | | /// If `None` is returned, the key should be removed from the storage entirely. |
2605 | 375 | pub fn value(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
2606 | 375 | self.value.map(|(ptr, size)| { |
2607 | 304 | self.inner |
2608 | 304 | .vm |
2609 | 304 | .read_memory(ptr, size) |
2610 | 304 | .unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNCNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB9_18ExternalStorageSet5value00Bd_ Unexecuted instantiation: _RNCNCNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB9_18ExternalStorageSet5value00Bd_ |
2611 | 375 | }) _RNCNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageSet5value0Bb_ Line | Count | Source | 2606 | 304 | self.value.map(|(ptr, size)| { | 2607 | 304 | self.inner | 2608 | 304 | .vm | 2609 | 304 | .read_memory(ptr, size) | 2610 | 304 | .unwrap_or_else(|_| unreachable!()) | 2611 | 304 | }) |
Unexecuted instantiation: _RNCNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageSet5value0Bb_ |
2612 | 375 | } _RNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageSet5value Line | Count | Source | 2605 | 375 | pub fn value(&'_ self) -> Option<impl AsRef<[u8]> + '_> { | 2606 | 375 | self.value.map(|(ptr, size)| { | 2607 | | self.inner | 2608 | | .vm | 2609 | | .read_memory(ptr, size) | 2610 | | .unwrap_or_else(|_| unreachable!()) | 2611 | 375 | }) | 2612 | 375 | } |
Unexecuted instantiation: _RNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageSet5value |
2613 | | |
2614 | | /// Returns the state trie version indicated by the runtime. |
2615 | | /// |
2616 | | /// This information should be stored alongside with the storage value and is necessary in |
2617 | | /// order to properly build the trie and thus the trie root node hash. |
2618 | 0 | pub fn state_trie_version(&self) -> TrieEntryVersion { |
2619 | 0 | self.inner |
2620 | 0 | .common |
2621 | 0 | .runtime_version |
2622 | 0 | .as_ref() |
2623 | 0 | .unwrap_or_else(|| unreachable!()) Unexecuted instantiation: _RNCNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18ExternalStorageSet18state_trie_version0Bb_ Unexecuted instantiation: _RNCNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18ExternalStorageSet18state_trie_version0Bb_ |
2624 | 0 | .decode() |
2625 | 0 | .state_version |
2626 | 0 | .unwrap_or(TrieEntryVersion::V0) |
2627 | 0 | } Unexecuted instantiation: _RNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageSet18state_trie_version Unexecuted instantiation: _RNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageSet18state_trie_version |
2628 | | |
2629 | | /// Resumes execution after having set the value. |
2630 | 375 | pub fn resume(self) -> HostVm { |
2631 | 375 | HostVm::ReadyToRun(ReadyToRun { |
2632 | 375 | inner: self.inner, |
2633 | 375 | resume_value: None, |
2634 | 375 | }) |
2635 | 375 | } _RNvMs8_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageSet6resume Line | Count | Source | 2630 | 375 | pub fn resume(self) -> HostVm { | 2631 | 375 | HostVm::ReadyToRun(ReadyToRun { | 2632 | 375 | inner: self.inner, | 2633 | 375 | resume_value: None, | 2634 | 375 | }) | 2635 | 375 | } |
Unexecuted instantiation: _RNvMs8_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageSet6resume |
2636 | | } |
2637 | | |
2638 | | impl fmt::Debug for ExternalStorageSet { |
2639 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2640 | 0 | f.debug_tuple("ExternalStorageSet").finish() |
2641 | 0 | } Unexecuted instantiation: _RNvXs9_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18ExternalStorageSetNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXs9_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18ExternalStorageSetNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
2642 | | } |
2643 | | |
2644 | | /// Must load a storage value, treat it as if it was a SCALE-encoded container, and put `value` |
2645 | | /// at the end of the container, increasing the number of elements. |
2646 | | /// |
2647 | | /// If [`ExternalStorageAppend::child_trie`] return `Some` and the child trie doesn't exist, it |
2648 | | /// must implicitly be created. |
2649 | | /// |
2650 | | /// If [`ExternalStorageAppend::child_trie`] return `None` and [`ExternalStorageAppend::key`] |
2651 | | /// returns a key that starts with `:child_storage:`, then the write must be silently ignored. |
2652 | | /// |
2653 | | /// If there isn't any existing value of if the existing value isn't actually a SCALE-encoded |
2654 | | /// container, store a 1-size container with the `value`. |
2655 | | /// |
2656 | | /// # Details |
2657 | | /// |
2658 | | /// The SCALE encoding encodes containers as a SCALE-compact-encoded length followed with the |
2659 | | /// SCALE-encoded items one after the other. For example, a container of two elements is stored |
2660 | | /// as the number `2` followed with the two items. |
2661 | | /// |
2662 | | /// This change consists in taking an existing value and assuming that it is a SCALE-encoded |
2663 | | /// container. This can be done as decoding a SCALE-compact-encoded number at the start of |
2664 | | /// the existing encoded value. One most then increments that number and puts `value` at the |
2665 | | /// end of the encoded value. |
2666 | | /// |
2667 | | /// It is not necessary to decode `value` as is assumed that is already encoded in the same |
2668 | | /// way as the other items in the container. |
2669 | | pub struct ExternalStorageAppend { |
2670 | | inner: Box<Inner>, |
2671 | | |
2672 | | /// Pointer to the key whose value must be set. Guaranteed to be in range. |
2673 | | key_ptr: u32, |
2674 | | /// Size of the key whose value must be set. Guaranteed to be in range. |
2675 | | key_size: u32, |
2676 | | |
2677 | | /// Pointer to the value to append. Guaranteed to be in range. |
2678 | | value_ptr: u32, |
2679 | | /// Size of the value to append. Guaranteed to be in range. |
2680 | | value_size: u32, |
2681 | | } |
2682 | | |
2683 | | impl ExternalStorageAppend { |
2684 | | /// Returns the key whose value must be set. |
2685 | 221 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
2686 | 221 | self.inner |
2687 | 221 | .vm |
2688 | 221 | .read_memory(self.key_ptr, self.key_size) |
2689 | 221 | .unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvMsa_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21ExternalStorageAppend3key0Bb_ Unexecuted instantiation: _RNCNvMsa_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21ExternalStorageAppend3key0Bb_ |
2690 | 221 | } _RNvMsa_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21ExternalStorageAppend3key Line | Count | Source | 2685 | 221 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { | 2686 | 221 | self.inner | 2687 | 221 | .vm | 2688 | 221 | .read_memory(self.key_ptr, self.key_size) | 2689 | 221 | .unwrap_or_else(|_| unreachable!()) | 2690 | 221 | } |
Unexecuted instantiation: _RNvMsa_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21ExternalStorageAppend3key |
2691 | | |
2692 | | /// If `Some`, write to the given child trie. If `None`, write to the main trie. |
2693 | | /// |
2694 | | /// If this returns `Some` and the child trie doesn't exist, it must implicitly be created. |
2695 | | /// |
2696 | | /// > **Note**: At the moment, this function always returns None, as there is no host function |
2697 | | /// > that appends to a child trie storage. |
2698 | 228 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
2699 | 228 | // Note that there is no equivalent of this host function for child tries. |
2700 | 228 | None::<&'static [u8]> |
2701 | 228 | } _RNvMsa_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21ExternalStorageAppend10child_trie Line | Count | Source | 2698 | 228 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { | 2699 | 228 | // Note that there is no equivalent of this host function for child tries. | 2700 | 228 | None::<&'static [u8]> | 2701 | 228 | } |
Unexecuted instantiation: _RNvMsa_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21ExternalStorageAppend10child_trie |
2702 | | |
2703 | | /// Returns the value to append. |
2704 | 71 | pub fn value(&'_ self) -> impl AsRef<[u8]> + '_ { |
2705 | 71 | self.inner |
2706 | 71 | .vm |
2707 | 71 | .read_memory(self.value_ptr, self.value_size) |
2708 | 71 | .unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvMsa_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21ExternalStorageAppend5value0Bb_ Unexecuted instantiation: _RNCNvMsa_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21ExternalStorageAppend5value0Bb_ |
2709 | 71 | } _RNvMsa_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21ExternalStorageAppend5value Line | Count | Source | 2704 | 71 | pub fn value(&'_ self) -> impl AsRef<[u8]> + '_ { | 2705 | 71 | self.inner | 2706 | 71 | .vm | 2707 | 71 | .read_memory(self.value_ptr, self.value_size) | 2708 | 71 | .unwrap_or_else(|_| unreachable!()) | 2709 | 71 | } |
Unexecuted instantiation: _RNvMsa_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21ExternalStorageAppend5value |
2710 | | |
2711 | | /// Resumes execution after having set the value. |
2712 | 71 | pub fn resume(self) -> HostVm { |
2713 | 71 | HostVm::ReadyToRun(ReadyToRun { |
2714 | 71 | inner: self.inner, |
2715 | 71 | resume_value: None, |
2716 | 71 | }) |
2717 | 71 | } _RNvMsa_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21ExternalStorageAppend6resume Line | Count | Source | 2712 | 71 | pub fn resume(self) -> HostVm { | 2713 | 71 | HostVm::ReadyToRun(ReadyToRun { | 2714 | 71 | inner: self.inner, | 2715 | 71 | resume_value: None, | 2716 | 71 | }) | 2717 | 71 | } |
Unexecuted instantiation: _RNvMsa_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21ExternalStorageAppend6resume |
2718 | | } |
2719 | | |
2720 | | impl fmt::Debug for ExternalStorageAppend { |
2721 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2722 | 0 | f.debug_tuple("ExternalStorageAppend").finish() |
2723 | 0 | } Unexecuted instantiation: _RNvXsb_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21ExternalStorageAppendNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsb_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21ExternalStorageAppendNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
2724 | | } |
2725 | | |
2726 | | /// Must remove from the storage keys which start with a certain prefix. Use |
2727 | | /// [`ExternalStorageClearPrefix::max_keys_to_remove`] to determine the maximum number of keys |
2728 | | /// to remove. |
2729 | | /// |
2730 | | /// If [`ExternalStorageClearPrefix::child_trie`] returns `Some` and all the entries of the child |
2731 | | /// trie are removed, the child trie must implicitly be destroyed. |
2732 | | /// |
2733 | | /// If [`ExternalStorageClearPrefix::child_trie`] return `None` and the prefix returned by |
2734 | | /// [`ExternalStorageClearPrefix::prefix`] intersects with `:child_storage:`, then the clearing |
2735 | | /// must be silently ignored. |
2736 | | pub struct ExternalStorageClearPrefix { |
2737 | | inner: Box<Inner>, |
2738 | | /// Function currently being called by the Wasm code. Refers to an index within |
2739 | | /// [`VmCommon::registered_functions`]. Guaranteed to be [`FunctionImport::Resolved`̀]. |
2740 | | calling: usize, |
2741 | | |
2742 | | /// Pointer and size to the prefix. `None` if `&[]`. Guaranteed to be in range. |
2743 | | prefix_ptr_size: Option<(u32, u32)>, |
2744 | | /// Pointer and size to the default child trie. `None` if main trie. Guaranteed to be in range. |
2745 | | child_trie_ptr_size: Option<(u32, u32)>, |
2746 | | |
2747 | | /// Maximum number of keys to remove. |
2748 | | max_keys_to_remove: Option<u32>, |
2749 | | } |
2750 | | |
2751 | | impl ExternalStorageClearPrefix { |
2752 | | /// Returns the prefix whose keys must be removed. |
2753 | 35 | pub fn prefix(&'_ self) -> impl AsRef<[u8]> + '_ { |
2754 | 35 | if let Some((prefix_ptr, prefix_size31 )) = self.prefix_ptr_size { |
2755 | 31 | either::Left( |
2756 | 31 | self.inner |
2757 | 31 | .vm |
2758 | 31 | .read_memory(prefix_ptr, prefix_size) |
2759 | 31 | .unwrap_or_else(|_| unreachable!()0 ), Unexecuted instantiation: _RNCNvMsc_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_26ExternalStorageClearPrefix6prefix0Bb_ Unexecuted instantiation: _RNCNvMsc_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_26ExternalStorageClearPrefix6prefix0Bb_ |
2760 | 31 | ) |
2761 | | } else { |
2762 | 4 | either::Right(&[][..]) |
2763 | | } |
2764 | 35 | } _RNvMsc_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalStorageClearPrefix6prefix Line | Count | Source | 2753 | 35 | pub fn prefix(&'_ self) -> impl AsRef<[u8]> + '_ { | 2754 | 35 | if let Some((prefix_ptr, prefix_size31 )) = self.prefix_ptr_size { | 2755 | 31 | either::Left( | 2756 | 31 | self.inner | 2757 | 31 | .vm | 2758 | 31 | .read_memory(prefix_ptr, prefix_size) | 2759 | 31 | .unwrap_or_else(|_| unreachable!()), | 2760 | 31 | ) | 2761 | | } else { | 2762 | 4 | either::Right(&[][..]) | 2763 | | } | 2764 | 35 | } |
Unexecuted instantiation: _RNvMsc_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalStorageClearPrefix6prefix |
2765 | | |
2766 | | /// If `Some`, write to the given child trie. If `None`, write to the main trie. |
2767 | | /// |
2768 | | /// If [`ExternalStorageClearPrefix::child_trie`] returns `Some` and all the entries of the |
2769 | | /// child trie are removed, the child trie must implicitly be destroyed. |
2770 | 49 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
2771 | 49 | if let Some((child_trie_ptr, child_trie_size7 )) = self.child_trie_ptr_size { |
2772 | 7 | let child_trie = self |
2773 | 7 | .inner |
2774 | 7 | .vm |
2775 | 7 | .read_memory(child_trie_ptr, child_trie_size) |
2776 | 7 | .unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCNvMsc_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_26ExternalStorageClearPrefix10child_trie0Bb_ Unexecuted instantiation: _RNCNvMsc_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_26ExternalStorageClearPrefix10child_trie0Bb_ |
2777 | 7 | Some(child_trie) |
2778 | | } else { |
2779 | 42 | None |
2780 | | } |
2781 | 49 | } _RNvMsc_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalStorageClearPrefix10child_trie Line | Count | Source | 2770 | 49 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { | 2771 | 49 | if let Some((child_trie_ptr, child_trie_size7 )) = self.child_trie_ptr_size { | 2772 | 7 | let child_trie = self | 2773 | 7 | .inner | 2774 | 7 | .vm | 2775 | 7 | .read_memory(child_trie_ptr, child_trie_size) | 2776 | 7 | .unwrap_or_else(|_| unreachable!()); | 2777 | 7 | Some(child_trie) | 2778 | | } else { | 2779 | 42 | None | 2780 | | } | 2781 | 49 | } |
Unexecuted instantiation: _RNvMsc_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalStorageClearPrefix10child_trie |
2782 | | |
2783 | | /// Returns the maximum number of keys to remove. `None` means "infinity". |
2784 | 9 | pub fn max_keys_to_remove(&self) -> Option<u32> { |
2785 | 9 | self.max_keys_to_remove |
2786 | 9 | } _RNvMsc_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalStorageClearPrefix18max_keys_to_remove Line | Count | Source | 2784 | 9 | pub fn max_keys_to_remove(&self) -> Option<u32> { | 2785 | 9 | self.max_keys_to_remove | 2786 | 9 | } |
Unexecuted instantiation: _RNvMsc_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalStorageClearPrefix18max_keys_to_remove |
2787 | | |
2788 | | /// Resumes execution after having cleared the values. |
2789 | | /// |
2790 | | /// Must be passed how many keys have been cleared, and whether some keys remaining to be |
2791 | | /// cleared. |
2792 | 6 | pub fn resume(self, num_cleared: u32, some_keys_remain: bool) -> HostVm { |
2793 | 6 | let host_fn = match self.inner.common.registered_functions[self.calling] { |
2794 | 6 | FunctionImport::Resolved(f) => f, |
2795 | 0 | FunctionImport::Unresolved { .. } => unreachable!(), |
2796 | | }; |
2797 | | |
2798 | 6 | match host_fn { |
2799 | | HostFunction::ext_storage_clear_prefix_version_1 |
2800 | | | HostFunction::ext_default_child_storage_clear_prefix_version_1 |
2801 | | | HostFunction::ext_default_child_storage_storage_kill_version_1 => { |
2802 | 1 | HostVm::ReadyToRun(ReadyToRun { |
2803 | 1 | inner: self.inner, |
2804 | 1 | resume_value: None, |
2805 | 1 | }) |
2806 | | } |
2807 | | HostFunction::ext_default_child_storage_storage_kill_version_2 => { |
2808 | | HostVm::ReadyToRun(ReadyToRun { |
2809 | 0 | inner: self.inner, |
2810 | 0 | resume_value: Some(vm::WasmValue::I32(if some_keys_remain { 0 } else { 1 })), |
2811 | | }) |
2812 | | } |
2813 | | HostFunction::ext_storage_clear_prefix_version_2 |
2814 | | | HostFunction::ext_default_child_storage_clear_prefix_version_2 |
2815 | | | HostFunction::ext_default_child_storage_storage_kill_version_3 => { |
2816 | 5 | self.inner.alloc_write_and_return_pointer_size( |
2817 | 5 | host_fn.name(), |
2818 | 5 | [ |
2819 | 5 | either::Left(if some_keys_remain { [1u8]0 } else { [0u8] }), |
2820 | 5 | either::Right(num_cleared.to_le_bytes()), |
2821 | 5 | ] |
2822 | 5 | .into_iter(), |
2823 | | ) |
2824 | | } |
2825 | 0 | _ => unreachable!(), |
2826 | | } |
2827 | 6 | } _RNvMsc_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalStorageClearPrefix6resume Line | Count | Source | 2792 | 6 | pub fn resume(self, num_cleared: u32, some_keys_remain: bool) -> HostVm { | 2793 | 6 | let host_fn = match self.inner.common.registered_functions[self.calling] { | 2794 | 6 | FunctionImport::Resolved(f) => f, | 2795 | 0 | FunctionImport::Unresolved { .. } => unreachable!(), | 2796 | | }; | 2797 | | | 2798 | 6 | match host_fn { | 2799 | | HostFunction::ext_storage_clear_prefix_version_1 | 2800 | | | HostFunction::ext_default_child_storage_clear_prefix_version_1 | 2801 | | | HostFunction::ext_default_child_storage_storage_kill_version_1 => { | 2802 | 1 | HostVm::ReadyToRun(ReadyToRun { | 2803 | 1 | inner: self.inner, | 2804 | 1 | resume_value: None, | 2805 | 1 | }) | 2806 | | } | 2807 | | HostFunction::ext_default_child_storage_storage_kill_version_2 => { | 2808 | | HostVm::ReadyToRun(ReadyToRun { | 2809 | 0 | inner: self.inner, | 2810 | 0 | resume_value: Some(vm::WasmValue::I32(if some_keys_remain { 0 } else { 1 })), | 2811 | | }) | 2812 | | } | 2813 | | HostFunction::ext_storage_clear_prefix_version_2 | 2814 | | | HostFunction::ext_default_child_storage_clear_prefix_version_2 | 2815 | | | HostFunction::ext_default_child_storage_storage_kill_version_3 => { | 2816 | 5 | self.inner.alloc_write_and_return_pointer_size( | 2817 | 5 | host_fn.name(), | 2818 | 5 | [ | 2819 | 5 | either::Left(if some_keys_remain { [1u8]0 } else { [0u8] }), | 2820 | 5 | either::Right(num_cleared.to_le_bytes()), | 2821 | 5 | ] | 2822 | 5 | .into_iter(), | 2823 | | ) | 2824 | | } | 2825 | 0 | _ => unreachable!(), | 2826 | | } | 2827 | 6 | } |
Unexecuted instantiation: _RNvMsc_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalStorageClearPrefix6resume |
2828 | | } |
2829 | | |
2830 | | impl fmt::Debug for ExternalStorageClearPrefix { |
2831 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2832 | 0 | f.debug_tuple("ExternalStorageClearPrefix").finish() |
2833 | 0 | } Unexecuted instantiation: _RNvXsd_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalStorageClearPrefixNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsd_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalStorageClearPrefixNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
2834 | | } |
2835 | | |
2836 | | /// Must provide the trie root hash of the storage and write the trie root hash of child tries |
2837 | | /// to the main trie. |
2838 | | /// |
2839 | | /// If [`ExternalStorageRoot::child_trie`] returns `Some` and the child trie is non-empty, the |
2840 | | /// trie root hash of the child trie must also be written to the main trie at the key |
2841 | | /// `concat(":child_storage:default:", child_trie)`. |
2842 | | /// If [`ExternalStorageRoot::child_trie`] returns `Some` and the child trie is empty, the entry |
2843 | | /// in the main trie at the key `concat(":child_storage:default:", child_trie)` must be removed. |
2844 | | /// |
2845 | | /// If [`ExternalStorageRoot::child_trie`] returns `None`, the same operation as above must be |
2846 | | /// done for every single child trie that has been modified in one way or the other during the |
2847 | | /// runtime call. |
2848 | | pub struct ExternalStorageRoot { |
2849 | | inner: Box<Inner>, |
2850 | | |
2851 | | /// Function currently being called by the Wasm code. Refers to an index within |
2852 | | /// [`VmCommon::registered_functions`]. Guaranteed to be [`FunctionImport::Resolved`̀]. |
2853 | | calling: usize, |
2854 | | |
2855 | | /// Pointer and size of the child trie, if any. Guaranteed to be in range. |
2856 | | child_trie_ptr_size: Option<(u32, u32)>, |
2857 | | } |
2858 | | |
2859 | | impl ExternalStorageRoot { |
2860 | | /// Returns the child trie whose root hash must be provided. `None` for the main trie. |
2861 | 20 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
2862 | 20 | if let Some((ptr, size0 )) = self.child_trie_ptr_size { |
2863 | 0 | let child_trie = self |
2864 | 0 | .inner |
2865 | 0 | .vm |
2866 | 0 | .read_memory(ptr, size) |
2867 | 0 | .unwrap_or_else(|_| unreachable!()); Unexecuted instantiation: _RNCNvMse_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_19ExternalStorageRoot10child_trie0Bb_ Unexecuted instantiation: _RNCNvMse_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_19ExternalStorageRoot10child_trie0Bb_ |
2868 | 0 | Some(child_trie) |
2869 | | } else { |
2870 | 20 | None |
2871 | | } |
2872 | 20 | } _RNvMse_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_19ExternalStorageRoot10child_trie Line | Count | Source | 2861 | 20 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { | 2862 | 20 | if let Some((ptr, size0 )) = self.child_trie_ptr_size { | 2863 | 0 | let child_trie = self | 2864 | 0 | .inner | 2865 | 0 | .vm | 2866 | 0 | .read_memory(ptr, size) | 2867 | 0 | .unwrap_or_else(|_| unreachable!()); | 2868 | 0 | Some(child_trie) | 2869 | | } else { | 2870 | 20 | None | 2871 | | } | 2872 | 20 | } |
Unexecuted instantiation: _RNvMse_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_19ExternalStorageRoot10child_trie |
2873 | | |
2874 | | /// Writes the trie root hash to the Wasm VM and prepares it for resume. |
2875 | | /// |
2876 | | /// If [`ExternalStorageRoot::child_trie`] returns `Some` but the child trie doesn't exist, |
2877 | | /// the root hash of an empty trie must be provided. |
2878 | 5 | pub fn resume(self, hash: &[u8; 32]) -> HostVm { |
2879 | 5 | let host_fn = match self.inner.common.registered_functions[self.calling] { |
2880 | 5 | FunctionImport::Resolved(f) => f, |
2881 | 0 | FunctionImport::Unresolved { .. } => unreachable!(), |
2882 | | }; |
2883 | | |
2884 | 5 | self.inner |
2885 | 5 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(hash)) |
2886 | 5 | } _RNvMse_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_19ExternalStorageRoot6resume Line | Count | Source | 2878 | 5 | pub fn resume(self, hash: &[u8; 32]) -> HostVm { | 2879 | 5 | let host_fn = match self.inner.common.registered_functions[self.calling] { | 2880 | 5 | FunctionImport::Resolved(f) => f, | 2881 | 0 | FunctionImport::Unresolved { .. } => unreachable!(), | 2882 | | }; | 2883 | | | 2884 | 5 | self.inner | 2885 | 5 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(hash)) | 2886 | 5 | } |
Unexecuted instantiation: _RNvMse_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_19ExternalStorageRoot6resume |
2887 | | } |
2888 | | |
2889 | | impl fmt::Debug for ExternalStorageRoot { |
2890 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2891 | 0 | f.debug_tuple("ExternalStorageRoot").finish() |
2892 | 0 | } Unexecuted instantiation: _RNvXsf_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_19ExternalStorageRootNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsf_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_19ExternalStorageRootNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
2893 | | } |
2894 | | |
2895 | | /// Must provide the storage key that follows, in lexicographic order, a specific one. |
2896 | | pub struct ExternalStorageNextKey { |
2897 | | inner: Box<Inner>, |
2898 | | |
2899 | | /// Pointer to the key whose follow-up must be found. Guaranteed to be in range. |
2900 | | key_ptr: u32, |
2901 | | /// Size of the key whose follow-up must be found. Guaranteed to be in range. |
2902 | | key_size: u32, |
2903 | | /// Pointer and size of the child trie, if any. Guaranteed to be in range. |
2904 | | child_trie_ptr_size: Option<(u32, u32)>, |
2905 | | } |
2906 | | |
2907 | | impl ExternalStorageNextKey { |
2908 | | /// Returns the key whose following key must be returned. |
2909 | 2 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
2910 | 2 | self.inner |
2911 | 2 | .vm |
2912 | 2 | .read_memory(self.key_ptr, self.key_size) |
2913 | 2 | .unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvMsg_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_22ExternalStorageNextKey3key0Bb_ Unexecuted instantiation: _RNCNvMsg_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_22ExternalStorageNextKey3key0Bb_ |
2914 | 2 | } _RNvMsg_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_22ExternalStorageNextKey3key Line | Count | Source | 2909 | 2 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { | 2910 | 2 | self.inner | 2911 | 2 | .vm | 2912 | 2 | .read_memory(self.key_ptr, self.key_size) | 2913 | 2 | .unwrap_or_else(|_| unreachable!()) | 2914 | 2 | } |
Unexecuted instantiation: _RNvMsg_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_22ExternalStorageNextKey3key |
2915 | | |
2916 | | /// If `Some`, read from the given child trie. If `None`, read from the main trie. |
2917 | 3 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
2918 | 3 | if let Some((child_trie_ptr, child_trie_size0 )) = self.child_trie_ptr_size { |
2919 | 0 | let child_trie = self |
2920 | 0 | .inner |
2921 | 0 | .vm |
2922 | 0 | .read_memory(child_trie_ptr, child_trie_size) |
2923 | 0 | .unwrap_or_else(|_| unreachable!()); Unexecuted instantiation: _RNCNvMsg_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_22ExternalStorageNextKey10child_trie0Bb_ Unexecuted instantiation: _RNCNvMsg_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_22ExternalStorageNextKey10child_trie0Bb_ |
2924 | 0 | Some(child_trie) |
2925 | | } else { |
2926 | 3 | None |
2927 | | } |
2928 | 3 | } _RNvMsg_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_22ExternalStorageNextKey10child_trie Line | Count | Source | 2917 | 3 | pub fn child_trie(&'_ self) -> Option<impl AsRef<[u8]> + '_> { | 2918 | 3 | if let Some((child_trie_ptr, child_trie_size0 )) = self.child_trie_ptr_size { | 2919 | 0 | let child_trie = self | 2920 | 0 | .inner | 2921 | 0 | .vm | 2922 | 0 | .read_memory(child_trie_ptr, child_trie_size) | 2923 | 0 | .unwrap_or_else(|_| unreachable!()); | 2924 | 0 | Some(child_trie) | 2925 | | } else { | 2926 | 3 | None | 2927 | | } | 2928 | 3 | } |
Unexecuted instantiation: _RNvMsg_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_22ExternalStorageNextKey10child_trie |
2929 | | |
2930 | | /// Writes the follow-up key in the Wasm VM memory and prepares it for execution. |
2931 | | /// |
2932 | | /// Must be passed `None` if the key is the last one in the storage or if |
2933 | | /// [`ExternalStorageNextKey`] returns `Some` and the child trie doesn't exist. |
2934 | 1 | pub fn resume(self, follow_up: Option<&[u8]>) -> HostVm { |
2935 | 1 | let key = self |
2936 | 1 | .inner |
2937 | 1 | .vm |
2938 | 1 | .read_memory(self.key_ptr, self.key_size) |
2939 | 1 | .unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCNvMsg_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_22ExternalStorageNextKey6resume0Bb_ Unexecuted instantiation: _RNCNvMsg_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_22ExternalStorageNextKey6resume0Bb_ |
2940 | 1 | |
2941 | 1 | match follow_up { |
2942 | 1 | Some(next) => { |
2943 | 1 | debug_assert!(key.as_ref() < next); |
2944 | | |
2945 | 1 | let value_len_enc = util::encode_scale_compact_usize(next.len()); |
2946 | 1 | drop(key); |
2947 | 1 | self.inner.alloc_write_and_return_pointer_size( |
2948 | 1 | HostFunction::ext_storage_next_key_version_1.name(), // TODO: no |
2949 | 1 | iter::once(&[1][..]) |
2950 | 1 | .chain(iter::once(value_len_enc.as_ref())) |
2951 | 1 | .chain(iter::once(next)), |
2952 | 1 | ) |
2953 | | } |
2954 | | None => { |
2955 | | // Write a SCALE-encoded `None`. |
2956 | 0 | drop(key); |
2957 | 0 | self.inner.alloc_write_and_return_pointer_size( |
2958 | 0 | HostFunction::ext_storage_next_key_version_1.name(), // TODO: no |
2959 | 0 | iter::once(&[0]), |
2960 | 0 | ) |
2961 | | } |
2962 | | } |
2963 | 1 | } _RNvMsg_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_22ExternalStorageNextKey6resume Line | Count | Source | 2934 | 1 | pub fn resume(self, follow_up: Option<&[u8]>) -> HostVm { | 2935 | 1 | let key = self | 2936 | 1 | .inner | 2937 | 1 | .vm | 2938 | 1 | .read_memory(self.key_ptr, self.key_size) | 2939 | 1 | .unwrap_or_else(|_| unreachable!()); | 2940 | 1 | | 2941 | 1 | match follow_up { | 2942 | 1 | Some(next) => { | 2943 | 1 | debug_assert!(key.as_ref() < next); | 2944 | | | 2945 | 1 | let value_len_enc = util::encode_scale_compact_usize(next.len()); | 2946 | 1 | drop(key); | 2947 | 1 | self.inner.alloc_write_and_return_pointer_size( | 2948 | 1 | HostFunction::ext_storage_next_key_version_1.name(), // TODO: no | 2949 | 1 | iter::once(&[1][..]) | 2950 | 1 | .chain(iter::once(value_len_enc.as_ref())) | 2951 | 1 | .chain(iter::once(next)), | 2952 | 1 | ) | 2953 | | } | 2954 | | None => { | 2955 | | // Write a SCALE-encoded `None`. | 2956 | 0 | drop(key); | 2957 | 0 | self.inner.alloc_write_and_return_pointer_size( | 2958 | 0 | HostFunction::ext_storage_next_key_version_1.name(), // TODO: no | 2959 | 0 | iter::once(&[0]), | 2960 | 0 | ) | 2961 | | } | 2962 | | } | 2963 | 1 | } |
Unexecuted instantiation: _RNvMsg_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_22ExternalStorageNextKey6resume |
2964 | | } |
2965 | | |
2966 | | impl fmt::Debug for ExternalStorageNextKey { |
2967 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2968 | 0 | f.debug_tuple("ExternalStorageNextKey").finish() |
2969 | 0 | } Unexecuted instantiation: _RNvXsh_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_22ExternalStorageNextKeyNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsh_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_22ExternalStorageNextKeyNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
2970 | | } |
2971 | | |
2972 | | /// Must verify whether a signature is correct. |
2973 | | pub struct SignatureVerification { |
2974 | | inner: Box<Inner>, |
2975 | | /// Which cryptographic algorithm. |
2976 | | algorithm: SignatureVerificationAlgorithm, |
2977 | | /// Pointer to the signature. The size of the signature depends on the algorithm. Guaranteed |
2978 | | /// to be in range. |
2979 | | signature_ptr: u32, |
2980 | | /// Pointer to the public key. The size of the public key depends on the algorithm. Guaranteed |
2981 | | /// to be in range. |
2982 | | public_key_ptr: u32, |
2983 | | /// Pointer to the message. Guaranteed to be in range. |
2984 | | message_ptr: u32, |
2985 | | /// Size of the message. Guaranteed to be in range. |
2986 | | message_size: u32, |
2987 | | /// `true` if the host function is a batch verification function. |
2988 | | is_batch_verification: bool, |
2989 | | } |
2990 | | |
2991 | | enum SignatureVerificationAlgorithm { |
2992 | | Ed25519, |
2993 | | Sr25519V1, |
2994 | | Sr25519V2, |
2995 | | Ecdsa, |
2996 | | EcdsaPrehashed, |
2997 | | } |
2998 | | |
2999 | | impl SignatureVerification { |
3000 | | /// Returns the message that the signature is expected to sign. |
3001 | 6 | pub fn message(&'_ self) -> impl AsRef<[u8]> + '_ { |
3002 | 6 | self.inner |
3003 | 6 | .vm |
3004 | 6 | .read_memory(self.message_ptr, self.message_size) |
3005 | 6 | .unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21SignatureVerification7message0Bb_ Unexecuted instantiation: _RNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21SignatureVerification7message0Bb_ |
3006 | 6 | } _RNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21SignatureVerification7message Line | Count | Source | 3001 | 6 | pub fn message(&'_ self) -> impl AsRef<[u8]> + '_ { | 3002 | 6 | self.inner | 3003 | 6 | .vm | 3004 | 6 | .read_memory(self.message_ptr, self.message_size) | 3005 | 6 | .unwrap_or_else(|_| unreachable!()) | 3006 | 6 | } |
Unexecuted instantiation: _RNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21SignatureVerification7message |
3007 | | |
3008 | | /// Returns the signature. |
3009 | | /// |
3010 | | /// > **Note**: Be aware that this signature is untrusted input and might not be part of the |
3011 | | /// > set of valid signatures. |
3012 | 6 | pub fn signature(&'_ self) -> impl AsRef<[u8]> + '_ { |
3013 | 6 | let signature_size = match self.algorithm { |
3014 | 0 | SignatureVerificationAlgorithm::Ed25519 => 64, |
3015 | 0 | SignatureVerificationAlgorithm::Sr25519V1 => 64, |
3016 | 6 | SignatureVerificationAlgorithm::Sr25519V2 => 64, |
3017 | 0 | SignatureVerificationAlgorithm::Ecdsa => 65, |
3018 | 0 | SignatureVerificationAlgorithm::EcdsaPrehashed => 65, |
3019 | | }; |
3020 | | |
3021 | 6 | self.inner |
3022 | 6 | .vm |
3023 | 6 | .read_memory(self.signature_ptr, signature_size) |
3024 | 6 | .unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21SignatureVerification9signature0Bb_ Unexecuted instantiation: _RNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21SignatureVerification9signature0Bb_ |
3025 | 6 | } _RNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21SignatureVerification9signature Line | Count | Source | 3012 | 6 | pub fn signature(&'_ self) -> impl AsRef<[u8]> + '_ { | 3013 | 6 | let signature_size = match self.algorithm { | 3014 | 0 | SignatureVerificationAlgorithm::Ed25519 => 64, | 3015 | 0 | SignatureVerificationAlgorithm::Sr25519V1 => 64, | 3016 | 6 | SignatureVerificationAlgorithm::Sr25519V2 => 64, | 3017 | 0 | SignatureVerificationAlgorithm::Ecdsa => 65, | 3018 | 0 | SignatureVerificationAlgorithm::EcdsaPrehashed => 65, | 3019 | | }; | 3020 | | | 3021 | 6 | self.inner | 3022 | 6 | .vm | 3023 | 6 | .read_memory(self.signature_ptr, signature_size) | 3024 | 6 | .unwrap_or_else(|_| unreachable!()) | 3025 | 6 | } |
Unexecuted instantiation: _RNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21SignatureVerification9signature |
3026 | | |
3027 | | /// Returns the public key the signature is against. |
3028 | | /// |
3029 | | /// > **Note**: Be aware that this public key is untrusted input and might not be part of the |
3030 | | /// > set of valid public keys. |
3031 | 6 | pub fn public_key(&'_ self) -> impl AsRef<[u8]> + '_ { |
3032 | 6 | let public_key_size = match self.algorithm { |
3033 | 0 | SignatureVerificationAlgorithm::Ed25519 => 32, |
3034 | 0 | SignatureVerificationAlgorithm::Sr25519V1 => 32, |
3035 | 6 | SignatureVerificationAlgorithm::Sr25519V2 => 32, |
3036 | 0 | SignatureVerificationAlgorithm::Ecdsa => 33, |
3037 | 0 | SignatureVerificationAlgorithm::EcdsaPrehashed => 33, |
3038 | | }; |
3039 | | |
3040 | 6 | self.inner |
3041 | 6 | .vm |
3042 | 6 | .read_memory(self.public_key_ptr, public_key_size) |
3043 | 6 | .unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21SignatureVerification10public_key0Bb_ Unexecuted instantiation: _RNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21SignatureVerification10public_key0Bb_ |
3044 | 6 | } _RNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21SignatureVerification10public_key Line | Count | Source | 3031 | 6 | pub fn public_key(&'_ self) -> impl AsRef<[u8]> + '_ { | 3032 | 6 | let public_key_size = match self.algorithm { | 3033 | 0 | SignatureVerificationAlgorithm::Ed25519 => 32, | 3034 | 0 | SignatureVerificationAlgorithm::Sr25519V1 => 32, | 3035 | 6 | SignatureVerificationAlgorithm::Sr25519V2 => 32, | 3036 | 0 | SignatureVerificationAlgorithm::Ecdsa => 33, | 3037 | 0 | SignatureVerificationAlgorithm::EcdsaPrehashed => 33, | 3038 | | }; | 3039 | | | 3040 | 6 | self.inner | 3041 | 6 | .vm | 3042 | 6 | .read_memory(self.public_key_ptr, public_key_size) | 3043 | 6 | .unwrap_or_else(|_| unreachable!()) | 3044 | 6 | } |
Unexecuted instantiation: _RNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21SignatureVerification10public_key |
3045 | | |
3046 | | /// Verify the signature. Returns `true` if it is valid. |
3047 | 6 | pub fn is_valid(&self) -> bool { |
3048 | 6 | match self.algorithm { |
3049 | | SignatureVerificationAlgorithm::Ed25519 => { |
3050 | 0 | let public_key = |
3051 | 0 | ed25519_zebra::VerificationKey::try_from(self.public_key().as_ref()); |
3052 | | |
3053 | 0 | if let Ok(public_key) = public_key { |
3054 | 0 | let signature = ed25519_zebra::Signature::from( |
3055 | 0 | <[u8; 64]>::try_from(self.signature().as_ref()) |
3056 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21SignatureVerification8is_valid0Bb_ Unexecuted instantiation: _RNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21SignatureVerification8is_valid0Bb_ |
3057 | 0 | ); |
3058 | 0 | public_key |
3059 | 0 | .verify(&signature, self.message().as_ref()) |
3060 | 0 | .is_ok() |
3061 | | } else { |
3062 | 0 | false |
3063 | | } |
3064 | | } |
3065 | | SignatureVerificationAlgorithm::Sr25519V1 => { |
3066 | 0 | schnorrkel::PublicKey::from_bytes(self.public_key().as_ref()).map_or(false, |pk| { |
3067 | 0 | pk.verify_simple_preaudit_deprecated( |
3068 | 0 | b"substrate", |
3069 | 0 | self.message().as_ref(), |
3070 | 0 | self.signature().as_ref(), |
3071 | 0 | ) |
3072 | 0 | .is_ok() |
3073 | 0 | }) Unexecuted instantiation: _RNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids_0Bb_ Unexecuted instantiation: _RNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids_0Bb_ |
3074 | | } |
3075 | | SignatureVerificationAlgorithm::Sr25519V2 => { |
3076 | 6 | schnorrkel::PublicKey::from_bytes(self.public_key().as_ref()).map_or(false, |pk| { |
3077 | 6 | pk.verify_simple( |
3078 | 6 | b"substrate", |
3079 | 6 | self.message().as_ref(), |
3080 | 6 | &schnorrkel::Signature::from_bytes(self.signature().as_ref()) |
3081 | 6 | .unwrap_or_else(|_| unreachable!()0 ), Unexecuted instantiation: _RNCNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB9_21SignatureVerification8is_valids0_00Bd_ Unexecuted instantiation: _RNCNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB9_21SignatureVerification8is_valids0_00Bd_ |
3082 | 6 | ) |
3083 | 6 | .is_ok() |
3084 | 6 | }) _RNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids0_0Bb_ Line | Count | Source | 3076 | 6 | schnorrkel::PublicKey::from_bytes(self.public_key().as_ref()).map_or(false, |pk| { | 3077 | 6 | pk.verify_simple( | 3078 | 6 | b"substrate", | 3079 | 6 | self.message().as_ref(), | 3080 | 6 | &schnorrkel::Signature::from_bytes(self.signature().as_ref()) | 3081 | 6 | .unwrap_or_else(|_| unreachable!()), | 3082 | 6 | ) | 3083 | 6 | .is_ok() | 3084 | 6 | }) |
Unexecuted instantiation: _RNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids0_0Bb_ |
3085 | | } |
3086 | | SignatureVerificationAlgorithm::Ecdsa => { |
3087 | | // NOTE: safe to unwrap here because we supply the nn to blake2b fn |
3088 | 0 | let data = <[u8; 32]>::try_from( |
3089 | 0 | blake2_rfc::blake2b::blake2b(32, &[], self.message().as_ref()).as_bytes(), |
3090 | 0 | ) |
3091 | 0 | .unwrap_or_else(|_| unreachable!()); Unexecuted instantiation: _RNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids1_0Bb_ Unexecuted instantiation: _RNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids1_0Bb_ |
3092 | 0 | let message = libsecp256k1::Message::parse(&data); |
3093 | 0 |
|
3094 | 0 | // signature (64 bytes) + recovery ID (1 byte) |
3095 | 0 | let sig_bytes = self.signature(); |
3096 | 0 | libsecp256k1::Signature::parse_standard_slice(&sig_bytes.as_ref()[..64]) |
3097 | 0 | .and_then(|sig| { |
3098 | 0 | libsecp256k1::RecoveryId::parse(sig_bytes.as_ref()[64]) |
3099 | 0 | .and_then(|ri| libsecp256k1::recover(&message, &sig, &ri)) Unexecuted instantiation: _RNCNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB9_21SignatureVerification8is_valids2_00Bd_ Unexecuted instantiation: _RNCNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB9_21SignatureVerification8is_valids2_00Bd_ |
3100 | 0 | }) Unexecuted instantiation: _RNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids2_0Bb_ Unexecuted instantiation: _RNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids2_0Bb_ |
3101 | 0 | .map_or(false, |actual| { |
3102 | 0 | self.public_key().as_ref()[..] == actual.serialize_compressed()[..] |
3103 | 0 | }) Unexecuted instantiation: _RNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids3_0Bb_ Unexecuted instantiation: _RNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids3_0Bb_ |
3104 | | } |
3105 | | SignatureVerificationAlgorithm::EcdsaPrehashed => { |
3106 | | // We can safely unwrap, as the size is checked when the `SignatureVerification` |
3107 | | // is constructed. |
3108 | 0 | let message = libsecp256k1::Message::parse( |
3109 | 0 | &<[u8; 32]>::try_from(self.message().as_ref()) |
3110 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids4_0Bb_ Unexecuted instantiation: _RNCNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_21SignatureVerification8is_valids4_0Bb_ |
3111 | 0 | ); |
3112 | 0 |
|
3113 | 0 | // signature (64 bytes) + recovery ID (1 byte) |
3114 | 0 | let sig_bytes = self.signature(); |
3115 | 0 | if let Ok(sig) = |
3116 | 0 | libsecp256k1::Signature::parse_standard_slice(&sig_bytes.as_ref()[..64]) |
3117 | | { |
3118 | 0 | if let Ok(ri) = libsecp256k1::RecoveryId::parse(sig_bytes.as_ref()[64]) { |
3119 | 0 | if let Ok(actual) = libsecp256k1::recover(&message, &sig, &ri) { |
3120 | 0 | self.public_key().as_ref()[..] == actual.serialize_compressed()[..] |
3121 | | } else { |
3122 | 0 | false |
3123 | | } |
3124 | | } else { |
3125 | 0 | false |
3126 | | } |
3127 | | } else { |
3128 | 0 | false |
3129 | | } |
3130 | | } |
3131 | | } |
3132 | 6 | } _RNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21SignatureVerification8is_valid Line | Count | Source | 3047 | 6 | pub fn is_valid(&self) -> bool { | 3048 | 6 | match self.algorithm { | 3049 | | SignatureVerificationAlgorithm::Ed25519 => { | 3050 | 0 | let public_key = | 3051 | 0 | ed25519_zebra::VerificationKey::try_from(self.public_key().as_ref()); | 3052 | | | 3053 | 0 | if let Ok(public_key) = public_key { | 3054 | 0 | let signature = ed25519_zebra::Signature::from( | 3055 | 0 | <[u8; 64]>::try_from(self.signature().as_ref()) | 3056 | 0 | .unwrap_or_else(|_| unreachable!()), | 3057 | 0 | ); | 3058 | 0 | public_key | 3059 | 0 | .verify(&signature, self.message().as_ref()) | 3060 | 0 | .is_ok() | 3061 | | } else { | 3062 | 0 | false | 3063 | | } | 3064 | | } | 3065 | | SignatureVerificationAlgorithm::Sr25519V1 => { | 3066 | 0 | schnorrkel::PublicKey::from_bytes(self.public_key().as_ref()).map_or(false, |pk| { | 3067 | | pk.verify_simple_preaudit_deprecated( | 3068 | | b"substrate", | 3069 | | self.message().as_ref(), | 3070 | | self.signature().as_ref(), | 3071 | | ) | 3072 | | .is_ok() | 3073 | 0 | }) | 3074 | | } | 3075 | | SignatureVerificationAlgorithm::Sr25519V2 => { | 3076 | 6 | schnorrkel::PublicKey::from_bytes(self.public_key().as_ref()).map_or(false, |pk| { | 3077 | | pk.verify_simple( | 3078 | | b"substrate", | 3079 | | self.message().as_ref(), | 3080 | | &schnorrkel::Signature::from_bytes(self.signature().as_ref()) | 3081 | | .unwrap_or_else(|_| unreachable!()), | 3082 | | ) | 3083 | | .is_ok() | 3084 | 6 | }) | 3085 | | } | 3086 | | SignatureVerificationAlgorithm::Ecdsa => { | 3087 | | // NOTE: safe to unwrap here because we supply the nn to blake2b fn | 3088 | 0 | let data = <[u8; 32]>::try_from( | 3089 | 0 | blake2_rfc::blake2b::blake2b(32, &[], self.message().as_ref()).as_bytes(), | 3090 | 0 | ) | 3091 | 0 | .unwrap_or_else(|_| unreachable!()); | 3092 | 0 | let message = libsecp256k1::Message::parse(&data); | 3093 | 0 |
| 3094 | 0 | // signature (64 bytes) + recovery ID (1 byte) | 3095 | 0 | let sig_bytes = self.signature(); | 3096 | 0 | libsecp256k1::Signature::parse_standard_slice(&sig_bytes.as_ref()[..64]) | 3097 | 0 | .and_then(|sig| { | 3098 | | libsecp256k1::RecoveryId::parse(sig_bytes.as_ref()[64]) | 3099 | | .and_then(|ri| libsecp256k1::recover(&message, &sig, &ri)) | 3100 | 0 | }) | 3101 | 0 | .map_or(false, |actual| { | 3102 | | self.public_key().as_ref()[..] == actual.serialize_compressed()[..] | 3103 | 0 | }) | 3104 | | } | 3105 | | SignatureVerificationAlgorithm::EcdsaPrehashed => { | 3106 | | // We can safely unwrap, as the size is checked when the `SignatureVerification` | 3107 | | // is constructed. | 3108 | 0 | let message = libsecp256k1::Message::parse( | 3109 | 0 | &<[u8; 32]>::try_from(self.message().as_ref()) | 3110 | 0 | .unwrap_or_else(|_| unreachable!()), | 3111 | 0 | ); | 3112 | 0 |
| 3113 | 0 | // signature (64 bytes) + recovery ID (1 byte) | 3114 | 0 | let sig_bytes = self.signature(); | 3115 | 0 | if let Ok(sig) = | 3116 | 0 | libsecp256k1::Signature::parse_standard_slice(&sig_bytes.as_ref()[..64]) | 3117 | | { | 3118 | 0 | if let Ok(ri) = libsecp256k1::RecoveryId::parse(sig_bytes.as_ref()[64]) { | 3119 | 0 | if let Ok(actual) = libsecp256k1::recover(&message, &sig, &ri) { | 3120 | 0 | self.public_key().as_ref()[..] == actual.serialize_compressed()[..] | 3121 | | } else { | 3122 | 0 | false | 3123 | | } | 3124 | | } else { | 3125 | 0 | false | 3126 | | } | 3127 | | } else { | 3128 | 0 | false | 3129 | | } | 3130 | | } | 3131 | | } | 3132 | 6 | } |
Unexecuted instantiation: _RNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21SignatureVerification8is_valid |
3133 | | |
3134 | | /// Verify the signature and resume execution. |
3135 | 6 | pub fn verify_and_resume(self) -> HostVm { |
3136 | 6 | let success = self.is_valid(); |
3137 | 6 | self.resume(success) |
3138 | 6 | } _RNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21SignatureVerification17verify_and_resume Line | Count | Source | 3135 | 6 | pub fn verify_and_resume(self) -> HostVm { | 3136 | 6 | let success = self.is_valid(); | 3137 | 6 | self.resume(success) | 3138 | 6 | } |
Unexecuted instantiation: _RNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21SignatureVerification17verify_and_resume |
3139 | | |
3140 | | /// Resume the execution assuming that the signature is valid. |
3141 | | /// |
3142 | | /// > **Note**: You are strongly encouraged to call |
3143 | | /// > [`SignatureVerification::verify_and_resume`]. This function is meant to be |
3144 | | /// > used only in debugging situations. |
3145 | 0 | pub fn resume_success(self) -> HostVm { |
3146 | 0 | self.resume(true) |
3147 | 0 | } Unexecuted instantiation: _RNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21SignatureVerification14resume_success Unexecuted instantiation: _RNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21SignatureVerification14resume_success |
3148 | | |
3149 | | /// Resume the execution assuming that the signature is invalid. |
3150 | | /// |
3151 | | /// > **Note**: You are strongly encouraged to call |
3152 | | /// > [`SignatureVerification::verify_and_resume`]. This function is meant to be |
3153 | | /// > used only in debugging situations. |
3154 | 0 | pub fn resume_failed(self) -> HostVm { |
3155 | 0 | self.resume(false) |
3156 | 0 | } Unexecuted instantiation: _RNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21SignatureVerification13resume_failed Unexecuted instantiation: _RNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21SignatureVerification13resume_failed |
3157 | | |
3158 | 6 | fn resume(mut self, success: bool) -> HostVm { |
3159 | 6 | debug_assert!( |
3160 | 6 | !self.is_batch_verification || self.inner.signatures_batch_verification.is_some()0 |
3161 | | ); |
3162 | 6 | if self.is_batch_verification && !success0 { |
3163 | 0 | self.inner.signatures_batch_verification = Some(false); |
3164 | 6 | } |
3165 | | |
3166 | | // All signature-related host functions work the same way in terms of return value. |
3167 | | HostVm::ReadyToRun(ReadyToRun { |
3168 | 6 | resume_value: Some(vm::WasmValue::I32(if success { 1 } else { 00 })), |
3169 | 6 | inner: self.inner, |
3170 | 6 | }) |
3171 | 6 | } _RNvMsi_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21SignatureVerification6resume Line | Count | Source | 3158 | 6 | fn resume(mut self, success: bool) -> HostVm { | 3159 | 6 | debug_assert!( | 3160 | 6 | !self.is_batch_verification || self.inner.signatures_batch_verification.is_some()0 | 3161 | | ); | 3162 | 6 | if self.is_batch_verification && !success0 { | 3163 | 0 | self.inner.signatures_batch_verification = Some(false); | 3164 | 6 | } | 3165 | | | 3166 | | // All signature-related host functions work the same way in terms of return value. | 3167 | | HostVm::ReadyToRun(ReadyToRun { | 3168 | 6 | resume_value: Some(vm::WasmValue::I32(if success { 1 } else { 00 })), | 3169 | 6 | inner: self.inner, | 3170 | 6 | }) | 3171 | 6 | } |
Unexecuted instantiation: _RNvMsi_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21SignatureVerification6resume |
3172 | | } |
3173 | | |
3174 | | impl fmt::Debug for SignatureVerification { |
3175 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3176 | 0 | f.debug_struct("SignatureVerification") |
3177 | 0 | .field("message", &self.message().as_ref()) |
3178 | 0 | .field("signature", &self.signature().as_ref()) |
3179 | 0 | .field("public_key", &self.public_key().as_ref()) |
3180 | 0 | .finish() |
3181 | 0 | } Unexecuted instantiation: _RNvXsj_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21SignatureVerificationNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsj_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21SignatureVerificationNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3182 | | } |
3183 | | |
3184 | | /// Must provide the runtime version obtained by calling the `Core_version` entry point of a Wasm |
3185 | | /// blob. |
3186 | | pub struct CallRuntimeVersion { |
3187 | | inner: Box<Inner>, |
3188 | | |
3189 | | /// Pointer to the wasm code whose runtime version must be provided. Guaranteed to be in range. |
3190 | | wasm_blob_ptr: u32, |
3191 | | /// Size of the wasm code whose runtime version must be provided. Guaranteed to be in range. |
3192 | | wasm_blob_size: u32, |
3193 | | } |
3194 | | |
3195 | | impl CallRuntimeVersion { |
3196 | | /// Returns the Wasm code whose runtime version must be provided. |
3197 | 0 | pub fn wasm_code(&'_ self) -> impl AsRef<[u8]> + '_ { |
3198 | 0 | self.inner |
3199 | 0 | .vm |
3200 | 0 | .read_memory(self.wasm_blob_ptr, self.wasm_blob_size) |
3201 | 0 | .unwrap_or_else(|_| unreachable!()) Unexecuted instantiation: _RNCNvMsk_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_18CallRuntimeVersion9wasm_code0Bb_ Unexecuted instantiation: _RNCNvMsk_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_18CallRuntimeVersion9wasm_code0Bb_ |
3202 | 0 | } Unexecuted instantiation: _RNvMsk_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18CallRuntimeVersion9wasm_code Unexecuted instantiation: _RNvMsk_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18CallRuntimeVersion9wasm_code |
3203 | | |
3204 | | /// Writes the SCALE-encoded runtime version to the memory and prepares for execution. |
3205 | | /// |
3206 | | /// If an error happened during the execution (such as an invalid Wasm binary code), pass |
3207 | | /// an `Err`. |
3208 | 0 | pub fn resume(self, scale_encoded_runtime_version: Result<&[u8], ()>) -> HostVm { |
3209 | 0 | if let Ok(scale_encoded_runtime_version) = scale_encoded_runtime_version { |
3210 | 0 | self.inner.alloc_write_and_return_pointer_size( |
3211 | 0 | HostFunction::ext_misc_runtime_version_version_1.name(), |
3212 | 0 | iter::once(either::Left([1])) |
3213 | 0 | .chain(iter::once(either::Right(either::Left( |
3214 | 0 | util::encode_scale_compact_usize(scale_encoded_runtime_version.len()), |
3215 | 0 | )))) |
3216 | 0 | .chain(iter::once(either::Right(either::Right( |
3217 | 0 | scale_encoded_runtime_version, |
3218 | 0 | )))), |
3219 | 0 | ) |
3220 | | } else { |
3221 | 0 | self.inner.alloc_write_and_return_pointer_size( |
3222 | 0 | HostFunction::ext_misc_runtime_version_version_1.name(), |
3223 | 0 | iter::once([0]), |
3224 | 0 | ) |
3225 | | } |
3226 | 0 | } Unexecuted instantiation: _RNvMsk_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18CallRuntimeVersion6resume Unexecuted instantiation: _RNvMsk_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18CallRuntimeVersion6resume |
3227 | | } |
3228 | | |
3229 | | impl fmt::Debug for CallRuntimeVersion { |
3230 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3231 | 0 | f.debug_tuple("CallRuntimeVersion").finish() |
3232 | 0 | } Unexecuted instantiation: _RNvXsl_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18CallRuntimeVersionNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsl_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18CallRuntimeVersionNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3233 | | } |
3234 | | |
3235 | | /// Must set off-chain index value. |
3236 | | pub struct ExternalOffchainIndexSet { |
3237 | | inner: Box<Inner>, |
3238 | | |
3239 | | /// Pointer to the key whose value must be set. Guaranteed to be in range. |
3240 | | key_ptr: u32, |
3241 | | /// Size of the key whose value must be set. Guaranteed to be in range. |
3242 | | key_size: u32, |
3243 | | |
3244 | | /// Pointer and size of the value to set. `None` for clearing. Guaranteed to be in range. |
3245 | | value: Option<(u32, u32)>, |
3246 | | } |
3247 | | |
3248 | | impl ExternalOffchainIndexSet { |
3249 | | /// Returns the key whose value must be set. |
3250 | 0 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
3251 | 0 | self.inner |
3252 | 0 | .vm |
3253 | 0 | .read_memory(self.key_ptr, self.key_size) |
3254 | 0 | .unwrap_or_else(|_| unreachable!()) Unexecuted instantiation: _RNCNvMsm_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_24ExternalOffchainIndexSet3key0Bb_ Unexecuted instantiation: _RNCNvMsm_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_24ExternalOffchainIndexSet3key0Bb_ |
3255 | 0 | } Unexecuted instantiation: _RNvMsm_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_24ExternalOffchainIndexSet3key Unexecuted instantiation: _RNvMsm_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_24ExternalOffchainIndexSet3key |
3256 | | |
3257 | | /// Returns the value to set. |
3258 | | /// |
3259 | | /// If `None` is returned, the key should be removed from the storage entirely. |
3260 | 0 | pub fn value(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
3261 | 0 | if let Some((ptr, size)) = self.value { |
3262 | 0 | Some( |
3263 | 0 | self.inner |
3264 | 0 | .vm |
3265 | 0 | .read_memory(ptr, size) |
3266 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMsm_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_24ExternalOffchainIndexSet5value0Bb_ Unexecuted instantiation: _RNCNvMsm_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_24ExternalOffchainIndexSet5value0Bb_ |
3267 | 0 | ) |
3268 | | } else { |
3269 | 0 | None |
3270 | | } |
3271 | 0 | } Unexecuted instantiation: _RNvMsm_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_24ExternalOffchainIndexSet5value Unexecuted instantiation: _RNvMsm_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_24ExternalOffchainIndexSet5value |
3272 | | |
3273 | | /// Resumes execution after having set the value. |
3274 | 0 | pub fn resume(self) -> HostVm { |
3275 | 0 | HostVm::ReadyToRun(ReadyToRun { |
3276 | 0 | inner: self.inner, |
3277 | 0 | resume_value: None, |
3278 | 0 | }) |
3279 | 0 | } Unexecuted instantiation: _RNvMsm_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_24ExternalOffchainIndexSet6resume Unexecuted instantiation: _RNvMsm_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_24ExternalOffchainIndexSet6resume |
3280 | | } |
3281 | | |
3282 | | impl fmt::Debug for ExternalOffchainIndexSet { |
3283 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3284 | 0 | f.debug_tuple("ExternalOffchainIndexSet").finish() |
3285 | 0 | } Unexecuted instantiation: _RNvXsn_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_24ExternalOffchainIndexSetNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsn_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_24ExternalOffchainIndexSetNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3286 | | } |
3287 | | |
3288 | | /// Must set the value of the off-chain storage. |
3289 | | pub struct ExternalOffchainStorageSet { |
3290 | | inner: Box<Inner>, |
3291 | | |
3292 | | /// Pointer to the key whose value must be set. Guaranteed to be in range. |
3293 | | key_ptr: u32, |
3294 | | /// Size of the key whose value must be set. Guaranteed to be in range. |
3295 | | key_size: u32, |
3296 | | |
3297 | | /// Pointer and size of the value to set. `None` for clearing. Guaranteed to be in range. |
3298 | | value: Option<(u32, u32)>, |
3299 | | |
3300 | | /// Pointer and size of the old value to compare. Guaranteed to be in range. |
3301 | | old_value: Option<(u32, u32)>, |
3302 | | } |
3303 | | |
3304 | | impl ExternalOffchainStorageSet { |
3305 | | /// Returns the key whose value must be set. |
3306 | 0 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
3307 | 0 | self.inner |
3308 | 0 | .vm |
3309 | 0 | .read_memory(self.key_ptr, self.key_size) |
3310 | 0 | .unwrap_or_else(|_| unreachable!()) Unexecuted instantiation: _RNCNvMso_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_26ExternalOffchainStorageSet3key0Bb_ Unexecuted instantiation: _RNCNvMso_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_26ExternalOffchainStorageSet3key0Bb_ |
3311 | 0 | } Unexecuted instantiation: _RNvMso_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalOffchainStorageSet3key Unexecuted instantiation: _RNvMso_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalOffchainStorageSet3key |
3312 | | |
3313 | | /// Returns the value to set. |
3314 | | /// |
3315 | | /// If `None` is returned, the key should be removed from the storage entirely. |
3316 | 0 | pub fn value(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
3317 | 0 | if let Some((ptr, size)) = self.value { |
3318 | 0 | Some( |
3319 | 0 | self.inner |
3320 | 0 | .vm |
3321 | 0 | .read_memory(ptr, size) |
3322 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMso_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_26ExternalOffchainStorageSet5value0Bb_ Unexecuted instantiation: _RNCNvMso_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_26ExternalOffchainStorageSet5value0Bb_ |
3323 | 0 | ) |
3324 | | } else { |
3325 | 0 | None |
3326 | | } |
3327 | 0 | } Unexecuted instantiation: _RNvMso_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalOffchainStorageSet5value Unexecuted instantiation: _RNvMso_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalOffchainStorageSet5value |
3328 | | |
3329 | | /// Returns the value the current value should be compared against. The operation is a no-op if they don't compare equal. |
3330 | 0 | pub fn old_value(&'_ self) -> Option<impl AsRef<[u8]> + '_> { |
3331 | 0 | if let Some((ptr, size)) = self.old_value { |
3332 | 0 | Some( |
3333 | 0 | self.inner |
3334 | 0 | .vm |
3335 | 0 | .read_memory(ptr, size) |
3336 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMso_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_26ExternalOffchainStorageSet9old_value0Bb_ Unexecuted instantiation: _RNCNvMso_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_26ExternalOffchainStorageSet9old_value0Bb_ |
3337 | 0 | ) |
3338 | | } else { |
3339 | 0 | None |
3340 | | } |
3341 | 0 | } Unexecuted instantiation: _RNvMso_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalOffchainStorageSet9old_value Unexecuted instantiation: _RNvMso_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalOffchainStorageSet9old_value |
3342 | | |
3343 | | /// Resumes execution after having set the value. Must indicate whether a value was written. |
3344 | 0 | pub fn resume(self, replaced: bool) -> HostVm { |
3345 | 0 | if self.old_value.is_some() { |
3346 | | HostVm::ReadyToRun(ReadyToRun { |
3347 | 0 | inner: self.inner, |
3348 | 0 | resume_value: Some(vm::WasmValue::I32(if replaced { 1 } else { 0 })), |
3349 | | }) |
3350 | | } else { |
3351 | 0 | HostVm::ReadyToRun(ReadyToRun { |
3352 | 0 | inner: self.inner, |
3353 | 0 | resume_value: None, |
3354 | 0 | }) |
3355 | | } |
3356 | 0 | } Unexecuted instantiation: _RNvMso_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalOffchainStorageSet6resume Unexecuted instantiation: _RNvMso_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalOffchainStorageSet6resume |
3357 | | } |
3358 | | |
3359 | | impl fmt::Debug for ExternalOffchainStorageSet { |
3360 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3361 | 0 | f.debug_tuple("ExternalOffchainStorageSet").finish() |
3362 | 0 | } Unexecuted instantiation: _RNvXsp_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalOffchainStorageSetNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsp_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalOffchainStorageSetNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3363 | | } |
3364 | | |
3365 | | /// Must get the value of the off-chain storage. |
3366 | | pub struct ExternalOffchainStorageGet { |
3367 | | inner: Box<Inner>, |
3368 | | |
3369 | | /// Function currently being called by the Wasm code. Refers to an index within |
3370 | | /// [`VmCommon::registered_functions`]. Guaranteed to be [`FunctionImport::Resolved`̀]. |
3371 | | calling: usize, |
3372 | | |
3373 | | /// Pointer to the key whose value must be loaded. Guaranteed to be in range. |
3374 | | key_ptr: u32, |
3375 | | /// Size of the key whose value must be loaded. Guaranteed to be in range. |
3376 | | key_size: u32, |
3377 | | } |
3378 | | |
3379 | | impl ExternalOffchainStorageGet { |
3380 | | /// Returns the key whose value must be loaded. |
3381 | 0 | pub fn key(&'_ self) -> impl AsRef<[u8]> + '_ { |
3382 | 0 | self.inner |
3383 | 0 | .vm |
3384 | 0 | .read_memory(self.key_ptr, self.key_size) |
3385 | 0 | .unwrap_or_else(|_| unreachable!()) Unexecuted instantiation: _RNCNvMsq_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_26ExternalOffchainStorageGet3key0Bb_ Unexecuted instantiation: _RNCNvMsq_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_26ExternalOffchainStorageGet3key0Bb_ |
3386 | 0 | } Unexecuted instantiation: _RNvMsq_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalOffchainStorageGet3key Unexecuted instantiation: _RNvMsq_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalOffchainStorageGet3key |
3387 | | |
3388 | | /// Resumes execution after having set the value. |
3389 | 0 | pub fn resume(self, value: Option<&[u8]>) -> HostVm { |
3390 | 0 | let host_fn = match self.inner.common.registered_functions[self.calling] { |
3391 | 0 | FunctionImport::Resolved(f) => f, |
3392 | 0 | FunctionImport::Unresolved { .. } => unreachable!(), |
3393 | | }; |
3394 | | |
3395 | 0 | if let Some(value) = value { |
3396 | 0 | let value_len_enc = util::encode_scale_compact_usize(value.len()); |
3397 | 0 | self.inner.alloc_write_and_return_pointer_size( |
3398 | 0 | host_fn.name(), |
3399 | 0 | iter::once(&[1][..]) |
3400 | 0 | .chain(iter::once(value_len_enc.as_ref())) |
3401 | 0 | .map(either::Left) |
3402 | 0 | .chain(iter::once(value).map(either::Right)), |
3403 | 0 | ) |
3404 | | } else { |
3405 | | // Write a SCALE-encoded `None`. |
3406 | 0 | self.inner |
3407 | 0 | .alloc_write_and_return_pointer_size(host_fn.name(), iter::once(&[0])) |
3408 | | } |
3409 | 0 | } Unexecuted instantiation: _RNvMsq_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalOffchainStorageGet6resume Unexecuted instantiation: _RNvMsq_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalOffchainStorageGet6resume |
3410 | | } |
3411 | | |
3412 | | impl fmt::Debug for ExternalOffchainStorageGet { |
3413 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3414 | 0 | f.debug_tuple("ExternalOffchainStorageGet").finish() |
3415 | 0 | } Unexecuted instantiation: _RNvXsr_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_26ExternalOffchainStorageGetNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsr_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_26ExternalOffchainStorageGetNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3416 | | } |
3417 | | |
3418 | | /// Must return the current UNIX timestamp. |
3419 | | pub struct OffchainTimestamp { |
3420 | | inner: Box<Inner>, |
3421 | | } |
3422 | | |
3423 | | impl OffchainTimestamp { |
3424 | | /// Resumes execution after having set the value. |
3425 | 0 | pub fn resume(self, value: u64) -> HostVm { |
3426 | 0 | HostVm::ReadyToRun(ReadyToRun { |
3427 | 0 | inner: self.inner, |
3428 | 0 | resume_value: Some(vm::WasmValue::I64(i64::from_ne_bytes(value.to_ne_bytes()))), |
3429 | 0 | }) |
3430 | 0 | } Unexecuted instantiation: _RNvMss_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_17OffchainTimestamp6resume Unexecuted instantiation: _RNvMss_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_17OffchainTimestamp6resume |
3431 | | } |
3432 | | |
3433 | | impl fmt::Debug for OffchainTimestamp { |
3434 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3435 | 0 | f.debug_tuple("OffchainTimestamp").finish() |
3436 | 0 | } Unexecuted instantiation: _RNvXst_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_17OffchainTimestampNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXst_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_17OffchainTimestampNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3437 | | } |
3438 | | |
3439 | | /// Must provide a randomly-generate number. |
3440 | | pub struct OffchainRandomSeed { |
3441 | | inner: Box<Inner>, |
3442 | | |
3443 | | /// Function currently being called by the Wasm code. Refers to an index within |
3444 | | /// [`VmCommon::registered_functions`]. Guaranteed to be [`FunctionImport::Resolved`̀]. |
3445 | | calling: usize, |
3446 | | } |
3447 | | |
3448 | | impl OffchainRandomSeed { |
3449 | | /// Resumes execution after having set the value. |
3450 | 0 | pub fn resume(self, value: [u8; 32]) -> HostVm { |
3451 | 0 | let host_fn = match self.inner.common.registered_functions[self.calling] { |
3452 | 0 | FunctionImport::Resolved(f) => f, |
3453 | 0 | FunctionImport::Unresolved { .. } => unreachable!(), |
3454 | | }; |
3455 | 0 | self.inner |
3456 | 0 | .alloc_write_and_return_pointer(host_fn.name(), iter::once(value)) |
3457 | 0 | } Unexecuted instantiation: _RNvMsu_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18OffchainRandomSeed6resume Unexecuted instantiation: _RNvMsu_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18OffchainRandomSeed6resume |
3458 | | } |
3459 | | |
3460 | | impl fmt::Debug for OffchainRandomSeed { |
3461 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3462 | 0 | f.debug_tuple("OffchainRandomSeed").finish() |
3463 | 0 | } Unexecuted instantiation: _RNvXsv_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_18OffchainRandomSeedNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsv_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_18OffchainRandomSeedNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3464 | | } |
3465 | | |
3466 | | /// Must submit an off-chain transaction. |
3467 | | pub struct OffchainSubmitTransaction { |
3468 | | inner: Box<Inner>, |
3469 | | |
3470 | | /// Function currently being called by the Wasm code. Refers to an index within |
3471 | | /// [`VmCommon::registered_functions`]. Guaranteed to be [`FunctionImport::Resolved`̀]. |
3472 | | calling: usize, |
3473 | | |
3474 | | /// Pointer to the transaction whose value must be set. Guaranteed to be in range. |
3475 | | tx_ptr: u32, |
3476 | | |
3477 | | /// Size of the transaction whose value must be set. Guaranteed to be in range. |
3478 | | tx_size: u32, |
3479 | | } |
3480 | | |
3481 | | impl OffchainSubmitTransaction { |
3482 | | /// Returns the SCALE-encoded transaction to submit to the chain. |
3483 | 0 | pub fn transaction(&'_ self) -> impl AsRef<[u8]> + '_ { |
3484 | 0 | self.inner |
3485 | 0 | .vm |
3486 | 0 | .read_memory(self.tx_ptr, self.tx_size) |
3487 | 0 | .unwrap_or_else(|_| unreachable!()) Unexecuted instantiation: _RNCNvMsw_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_25OffchainSubmitTransaction11transaction0Bb_ Unexecuted instantiation: _RNCNvMsw_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_25OffchainSubmitTransaction11transaction0Bb_ |
3488 | 0 | } Unexecuted instantiation: _RNvMsw_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_25OffchainSubmitTransaction11transaction Unexecuted instantiation: _RNvMsw_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_25OffchainSubmitTransaction11transaction |
3489 | | |
3490 | | /// Resumes execution after having submitted the transaction. |
3491 | 0 | pub fn resume(self, success: bool) -> HostVm { |
3492 | 0 | let host_fn = match self.inner.common.registered_functions[self.calling] { |
3493 | 0 | FunctionImport::Resolved(f) => f, |
3494 | 0 | FunctionImport::Unresolved { .. } => unreachable!(), |
3495 | | }; |
3496 | | |
3497 | 0 | self.inner.alloc_write_and_return_pointer_size( |
3498 | 0 | host_fn.name(), |
3499 | 0 | if success { |
3500 | 0 | iter::once(&[0x00]) |
3501 | | } else { |
3502 | 0 | iter::once(&[0x01]) |
3503 | | }, |
3504 | | ) |
3505 | 0 | } Unexecuted instantiation: _RNvMsw_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_25OffchainSubmitTransaction6resume Unexecuted instantiation: _RNvMsw_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_25OffchainSubmitTransaction6resume |
3506 | | } |
3507 | | |
3508 | | impl fmt::Debug for OffchainSubmitTransaction { |
3509 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3510 | 0 | f.debug_tuple("OffchainSubmitTransaction").finish() |
3511 | 0 | } Unexecuted instantiation: _RNvXsx_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_25OffchainSubmitTransactionNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsx_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_25OffchainSubmitTransactionNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3512 | | } |
3513 | | |
3514 | | /// Report about a log entry being emitted. |
3515 | | /// |
3516 | | /// Use [`LogEmit::info`] to obtain what must be printed. |
3517 | | pub struct LogEmit { |
3518 | | inner: Box<Inner>, |
3519 | | log_entry: LogEmitInner, |
3520 | | } |
3521 | | |
3522 | | enum LogEmitInner { |
3523 | | Num(u64), |
3524 | | Utf8 { |
3525 | | /// Pointer to the string. Guaranteed to be in range and to be UTF-8. |
3526 | | str_ptr: u32, |
3527 | | /// Size of the string. Guaranteed to be in range and to be UTF-8. |
3528 | | str_size: u32, |
3529 | | }, |
3530 | | Hex { |
3531 | | /// Pointer to the data. Guaranteed to be in range. |
3532 | | data_ptr: u32, |
3533 | | /// Size of the data. Guaranteed to be in range. |
3534 | | data_size: u32, |
3535 | | }, |
3536 | | Log { |
3537 | | /// Log level. Arbitrary number indicated by runtime, but typically in the `1..=5` range. |
3538 | | log_level: u32, |
3539 | | /// Pointer to the string of the log target. Guaranteed to be in range and to be UTF-8. |
3540 | | target_str_ptr: u32, |
3541 | | /// Size of the string of the log target. Guaranteed to be in range and to be UTF-8. |
3542 | | target_str_size: u32, |
3543 | | /// Pointer to the string of the log message. Guaranteed to be in range and to be UTF-8. |
3544 | | msg_str_ptr: u32, |
3545 | | /// Size of the string of the log message. Guaranteed to be in range and to be UTF-8. |
3546 | | msg_str_size: u32, |
3547 | | }, |
3548 | | } |
3549 | | |
3550 | | impl LogEmit { |
3551 | | /// Returns the data that the runtime would like to print. |
3552 | 0 | pub fn info(&self) -> LogEmitInfo { |
3553 | 0 | match self.log_entry { |
3554 | 0 | LogEmitInner::Num(n) => LogEmitInfo::Num(n), |
3555 | 0 | LogEmitInner::Utf8 { str_ptr, str_size } => LogEmitInfo::Utf8(LogEmitInfoStr { |
3556 | 0 | data: Box::new( |
3557 | 0 | self.inner |
3558 | 0 | .vm |
3559 | 0 | .read_memory(str_ptr, str_size) |
3560 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMsy_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_7LogEmit4info0Bb_ Unexecuted instantiation: _RNCNvMsy_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_7LogEmit4info0Bb_ |
3561 | 0 | ), |
3562 | 0 | }), |
3563 | | LogEmitInner::Hex { |
3564 | 0 | data_ptr, |
3565 | 0 | data_size, |
3566 | 0 | } => LogEmitInfo::Hex(LogEmitInfoHex { |
3567 | 0 | data: Box::new( |
3568 | 0 | self.inner |
3569 | 0 | .vm |
3570 | 0 | .read_memory(data_ptr, data_size) |
3571 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMsy_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_7LogEmit4infos_0Bb_ Unexecuted instantiation: _RNCNvMsy_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_7LogEmit4infos_0Bb_ |
3572 | 0 | ), |
3573 | 0 | }), |
3574 | | LogEmitInner::Log { |
3575 | 0 | msg_str_ptr, |
3576 | 0 | msg_str_size, |
3577 | 0 | target_str_ptr, |
3578 | 0 | target_str_size, |
3579 | 0 | log_level, |
3580 | 0 | } => LogEmitInfo::Log { |
3581 | 0 | log_level, |
3582 | 0 | target: LogEmitInfoStr { |
3583 | 0 | data: Box::new( |
3584 | 0 | self.inner |
3585 | 0 | .vm |
3586 | 0 | .read_memory(target_str_ptr, target_str_size) |
3587 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMsy_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_7LogEmit4infos0_0Bb_ Unexecuted instantiation: _RNCNvMsy_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_7LogEmit4infos0_0Bb_ |
3588 | 0 | ), |
3589 | 0 | }, |
3590 | 0 | message: LogEmitInfoStr { |
3591 | 0 | data: Box::new( |
3592 | 0 | self.inner |
3593 | 0 | .vm |
3594 | 0 | .read_memory(msg_str_ptr, msg_str_size) |
3595 | 0 | .unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvMsy_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_7LogEmit4infos1_0Bb_ Unexecuted instantiation: _RNCNvMsy_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_7LogEmit4infos1_0Bb_ |
3596 | 0 | ), |
3597 | 0 | }, |
3598 | 0 | }, |
3599 | | } |
3600 | 0 | } Unexecuted instantiation: _RNvMsy_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_7LogEmit4info Unexecuted instantiation: _RNvMsy_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_7LogEmit4info |
3601 | | |
3602 | | /// Resumes execution. |
3603 | 0 | pub fn resume(self) -> HostVm { |
3604 | 0 | HostVm::ReadyToRun(ReadyToRun { |
3605 | 0 | inner: self.inner, |
3606 | 0 | resume_value: None, |
3607 | 0 | }) |
3608 | 0 | } Unexecuted instantiation: _RNvMsy_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_7LogEmit6resume Unexecuted instantiation: _RNvMsy_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_7LogEmit6resume |
3609 | | } |
3610 | | |
3611 | | impl fmt::Debug for LogEmit { |
3612 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3613 | 0 | f.debug_struct("LogEmit") |
3614 | 0 | .field("info", &self.info()) |
3615 | 0 | .finish() |
3616 | 0 | } Unexecuted instantiation: _RNvXsz_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_7LogEmitNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsz_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_7LogEmitNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3617 | | } |
3618 | | |
3619 | | /// Detail about what a [`LogEmit`] should output. See [`LogEmit::info`]. |
3620 | | #[derive(Debug)] |
3621 | | pub enum LogEmitInfo<'a> { |
3622 | | /// Must output a single number. |
3623 | | Num(u64), |
3624 | | /// Must output a UTF-8 string. |
3625 | | Utf8(LogEmitInfoStr<'a>), |
3626 | | /// Must output the hexadecimal encoding of the given buffer. |
3627 | | Hex(LogEmitInfoHex<'a>), |
3628 | | /// Must output a log line. |
3629 | | Log { |
3630 | | /// Log level. Arbitrary number indicated by runtime, but typically in the `1..=5` range. |
3631 | | log_level: u32, |
3632 | | /// "Target" of the log. Arbitrary string indicated by the runtime. Typically indicates |
3633 | | /// the subsystem which has emitted the log line. |
3634 | | target: LogEmitInfoStr<'a>, |
3635 | | /// Actual log message being emitted. |
3636 | | message: LogEmitInfoStr<'a>, |
3637 | | }, |
3638 | | } |
3639 | | |
3640 | | /// See [`LogEmitInfo`]. Use the `AsRef` trait implementation to retrieve the buffer. |
3641 | | pub struct LogEmitInfoHex<'a> { |
3642 | | // TODO: don't use a Box once Rust supports type Foo = impl Trait; |
3643 | | data: Box<dyn AsRef<[u8]> + Send + Sync + 'a>, |
3644 | | } |
3645 | | |
3646 | | impl<'a> AsRef<[u8]> for LogEmitInfoHex<'a> { |
3647 | 0 | fn as_ref(&self) -> &[u8] { |
3648 | 0 | (*self.data).as_ref() |
3649 | 0 | } Unexecuted instantiation: _RNvXsA_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_14LogEmitInfoHexINtNtCsaYZPK01V26L_4core7convert5AsRefShE6as_ref Unexecuted instantiation: _RNvXsA_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_14LogEmitInfoHexINtNtCsaYZPK01V26L_4core7convert5AsRefShE6as_ref |
3650 | | } |
3651 | | |
3652 | | impl<'a> fmt::Debug for LogEmitInfoHex<'a> { |
3653 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
3654 | 0 | fmt::Debug::fmt(self.as_ref(), f) |
3655 | 0 | } Unexecuted instantiation: _RNvXsB_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_14LogEmitInfoHexNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsB_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_14LogEmitInfoHexNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3656 | | } |
3657 | | |
3658 | | impl<'a> fmt::Display for LogEmitInfoHex<'a> { |
3659 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
3660 | 0 | fmt::Debug::fmt(&hex::encode(self.as_ref()), f) |
3661 | 0 | } Unexecuted instantiation: _RNvXsC_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_14LogEmitInfoHexNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXsC_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_14LogEmitInfoHexNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
3662 | | } |
3663 | | |
3664 | | /// See [`LogEmitInfo`]. Use the `AsRef` trait implementation to retrieve the string. |
3665 | | pub struct LogEmitInfoStr<'a> { |
3666 | | // TODO: don't use a Box once Rust supports type Foo = impl Trait; |
3667 | | data: Box<dyn AsRef<[u8]> + Send + Sync + 'a>, |
3668 | | } |
3669 | | |
3670 | | impl<'a> AsRef<str> for LogEmitInfoStr<'a> { |
3671 | 0 | fn as_ref(&self) -> &str { |
3672 | 0 | let data = (*self.data).as_ref(); |
3673 | 0 | // The creator of `LogEmitInfoStr` always makes sure that the string is indeed UTF-8 |
3674 | 0 | // before creating it. |
3675 | 0 | str::from_utf8(data).unwrap_or_else(|_| unreachable!()) Unexecuted instantiation: _RNCNvXsD_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_14LogEmitInfoStrINtNtCsaYZPK01V26L_4core7convert5AsRefeE6as_ref0Bb_ Unexecuted instantiation: _RNCNvXsD_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_14LogEmitInfoStrINtNtCsaYZPK01V26L_4core7convert5AsRefeE6as_ref0Bb_ |
3676 | 0 | } Unexecuted instantiation: _RNvXsD_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_14LogEmitInfoStrINtNtCsaYZPK01V26L_4core7convert5AsRefeE6as_ref Unexecuted instantiation: _RNvXsD_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_14LogEmitInfoStrINtNtCsaYZPK01V26L_4core7convert5AsRefeE6as_ref |
3677 | | } |
3678 | | |
3679 | | impl<'a> fmt::Debug for LogEmitInfoStr<'a> { |
3680 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
3681 | 0 | fmt::Debug::fmt(self.as_ref(), f) |
3682 | 0 | } Unexecuted instantiation: _RNvXsE_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_14LogEmitInfoStrNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsE_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_14LogEmitInfoStrNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3683 | | } |
3684 | | |
3685 | | impl<'a> fmt::Display for LogEmitInfoStr<'a> { |
3686 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
3687 | 0 | fmt::Display::fmt(self.as_ref(), f) |
3688 | 0 | } Unexecuted instantiation: _RNvXsF_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_14LogEmitInfoStrNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXsF_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_14LogEmitInfoStrNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
3689 | | } |
3690 | | |
3691 | | /// Queries the maximum log level. |
3692 | | pub struct GetMaxLogLevel { |
3693 | | inner: Box<Inner>, |
3694 | | } |
3695 | | |
3696 | | impl GetMaxLogLevel { |
3697 | | /// Resumes execution after indicating the maximum log level. |
3698 | | /// |
3699 | | /// 0 means off, 1 means error, 2 means warn, 3 means info, 4 means debug, 5 means trace. |
3700 | 136 | pub fn resume(self, max_level: u32) -> HostVm { |
3701 | 136 | HostVm::ReadyToRun(ReadyToRun { |
3702 | 136 | inner: self.inner, |
3703 | 136 | resume_value: Some(vm::WasmValue::I32(i32::from_ne_bytes( |
3704 | 136 | max_level.to_ne_bytes(), |
3705 | 136 | ))), |
3706 | 136 | }) |
3707 | 136 | } _RNvMsG_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_14GetMaxLogLevel6resume Line | Count | Source | 3700 | 9 | pub fn resume(self, max_level: u32) -> HostVm { | 3701 | 9 | HostVm::ReadyToRun(ReadyToRun { | 3702 | 9 | inner: self.inner, | 3703 | 9 | resume_value: Some(vm::WasmValue::I32(i32::from_ne_bytes( | 3704 | 9 | max_level.to_ne_bytes(), | 3705 | 9 | ))), | 3706 | 9 | }) | 3707 | 9 | } |
_RNvMsG_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_14GetMaxLogLevel6resume Line | Count | Source | 3700 | 127 | pub fn resume(self, max_level: u32) -> HostVm { | 3701 | 127 | HostVm::ReadyToRun(ReadyToRun { | 3702 | 127 | inner: self.inner, | 3703 | 127 | resume_value: Some(vm::WasmValue::I32(i32::from_ne_bytes( | 3704 | 127 | max_level.to_ne_bytes(), | 3705 | 127 | ))), | 3706 | 127 | }) | 3707 | 127 | } |
|
3708 | | } |
3709 | | |
3710 | | impl fmt::Debug for GetMaxLogLevel { |
3711 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3712 | 0 | f.debug_tuple("GetMaxLogLevel").finish() |
3713 | 0 | } Unexecuted instantiation: _RNvXsH_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_14GetMaxLogLevelNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsH_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_14GetMaxLogLevelNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3714 | | } |
3715 | | |
3716 | | /// Declares the start of a transaction. |
3717 | | pub struct StartStorageTransaction { |
3718 | | inner: Box<Inner>, |
3719 | | } |
3720 | | |
3721 | | impl StartStorageTransaction { |
3722 | | /// Resumes execution after having acknowledged the event. |
3723 | 14 | pub fn resume(self) -> HostVm { |
3724 | 14 | HostVm::ReadyToRun(ReadyToRun { |
3725 | 14 | inner: self.inner, |
3726 | 14 | resume_value: None, |
3727 | 14 | }) |
3728 | 14 | } _RNvMsI_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_23StartStorageTransaction6resume Line | Count | Source | 3723 | 14 | pub fn resume(self) -> HostVm { | 3724 | 14 | HostVm::ReadyToRun(ReadyToRun { | 3725 | 14 | inner: self.inner, | 3726 | 14 | resume_value: None, | 3727 | 14 | }) | 3728 | 14 | } |
Unexecuted instantiation: _RNvMsI_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_23StartStorageTransaction6resume |
3729 | | } |
3730 | | |
3731 | | impl fmt::Debug for StartStorageTransaction { |
3732 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3733 | 0 | f.debug_tuple("StartStorageTransaction").finish() |
3734 | 0 | } Unexecuted instantiation: _RNvXsJ_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_23StartStorageTransactionNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsJ_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_23StartStorageTransactionNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3735 | | } |
3736 | | |
3737 | | /// Declares the end of a transaction. |
3738 | | pub struct EndStorageTransaction { |
3739 | | inner: Box<Inner>, |
3740 | | } |
3741 | | |
3742 | | impl EndStorageTransaction { |
3743 | | /// Resumes execution after having acknowledged the event. |
3744 | 14 | pub fn resume(self) -> HostVm { |
3745 | 14 | HostVm::ReadyToRun(ReadyToRun { |
3746 | 14 | inner: self.inner, |
3747 | 14 | resume_value: None, |
3748 | 14 | }) |
3749 | 14 | } _RNvMsK_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21EndStorageTransaction6resume Line | Count | Source | 3744 | 14 | pub fn resume(self) -> HostVm { | 3745 | 14 | HostVm::ReadyToRun(ReadyToRun { | 3746 | 14 | inner: self.inner, | 3747 | 14 | resume_value: None, | 3748 | 14 | }) | 3749 | 14 | } |
Unexecuted instantiation: _RNvMsK_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21EndStorageTransaction6resume |
3750 | | } |
3751 | | |
3752 | | impl fmt::Debug for EndStorageTransaction { |
3753 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3754 | 0 | f.debug_tuple("EndStorageTransaction").finish() |
3755 | 0 | } Unexecuted instantiation: _RNvXsL_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_21EndStorageTransactionNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt Unexecuted instantiation: _RNvXsL_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_21EndStorageTransactionNtNtCsaYZPK01V26L_4core3fmt5Debug3fmt |
3756 | | } |
3757 | | |
3758 | | #[derive(Clone)] |
3759 | | enum FunctionImport { |
3760 | | Resolved(HostFunction), |
3761 | | Unresolved { module: String, name: String }, |
3762 | | } |
3763 | | |
3764 | | /// Running virtual machine. Shared between all the variants in [`HostVm`]. |
3765 | | struct Inner { |
3766 | | /// Inner lower-level virtual machine. |
3767 | | vm: vm::VirtualMachine, |
3768 | | |
3769 | | /// The depth of storage transaction started with `ext_storage_start_transaction_version_1`. |
3770 | | storage_transaction_depth: u32, |
3771 | | |
3772 | | /// The host provides a "batch signature verification" mechanism, where the runtime can start |
3773 | | /// verifying multiple signatures at once. This mechanism is deprecated, but is emulated |
3774 | | /// through a simple field. |
3775 | | /// |
3776 | | /// Contains `Some` if and only if the runtime is currently within a batch signatures |
3777 | | /// verification. If `Some`, contains `true` if all the signatures have been verified |
3778 | | /// successfully so far. |
3779 | | signatures_batch_verification: Option<bool>, |
3780 | | |
3781 | | /// Memory allocator in order to answer the calls to `malloc` and `free`. |
3782 | | allocator: allocator::FreeingBumpHeapAllocator, |
3783 | | |
3784 | | /// Value passed as parameter. |
3785 | | storage_proof_size_behavior: StorageProofSizeBehavior, |
3786 | | |
3787 | | /// Fields that are kept as is even during the execution. |
3788 | | common: Box<VmCommon>, |
3789 | | } |
3790 | | |
3791 | | impl Inner { |
3792 | | /// Uses the memory allocator to allocate some memory for the given data, writes the data in |
3793 | | /// memory, and returns an [`HostVm`] ready for the Wasm `host_fn` return. |
3794 | | /// |
3795 | | /// The data is passed as a list of chunks. These chunks will be laid out linearly in memory. |
3796 | | /// |
3797 | | /// The function name passed as parameter is used for error-reporting reasons. |
3798 | | /// |
3799 | | /// # Panic |
3800 | | /// |
3801 | | /// Must only be called while the Wasm is handling an `host_fn`. |
3802 | | /// |
3803 | 683 | fn alloc_write_and_return_pointer_size( |
3804 | 683 | mut self: Box<Self>, |
3805 | 683 | function_name: &'static str, |
3806 | 683 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, |
3807 | 683 | ) -> HostVm { |
3808 | 683 | let mut data_len = 0u32; |
3809 | 1.86k | for chunk in data.clone()683 { |
3810 | 1.86k | data_len = |
3811 | 1.86k | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); |
3812 | 1.86k | } |
3813 | | |
3814 | 683 | let dest_ptr = match self.alloc(function_name, data_len) { |
3815 | 683 | Ok(p) => p, |
3816 | 0 | Err(error) => { |
3817 | 0 | return HostVm::Error { |
3818 | 0 | error, |
3819 | 0 | prototype: self.into_prototype(), |
3820 | 0 | } |
3821 | | } |
3822 | | }; |
3823 | | |
3824 | 683 | let mut ptr_iter = dest_ptr; |
3825 | 2.55k | for chunk1.86k in data { |
3826 | 1.86k | let chunk = chunk.as_ref(); |
3827 | 1.86k | self.vm |
3828 | 1.86k | .write_memory(ptr_iter, chunk) |
3829 | 1.86k | .unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeAhj1_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1x_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_Ahj4_EIB1y_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtNtB2p_7sources4once4OnceB1x_EB3a_EB3a_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_Ahj4_EINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1x_Kj2_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_IB1y_INtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_ERShEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB38_INtNtNtB3e_7sources4once4OnceB1x_EB44_EB44_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherRShB22_EINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB2f_3map3MapIB2b_INtNtNtB2h_7sources4once4OnceB22_EB3o_ENcNtB1x_4Left0EIB33_B3o_NcNtB1x_5Right0EEE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeRAhj1_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1x_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeRAhj20_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1x_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1x_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1x_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeRShINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB1B_INtNtNtB1H_7sources4once4OnceB1x_EB2x_EB2x_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeAhj1_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_Ahj4_EIB1z_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtNtB2q_7sources4once4OnceB1y_EB3b_EB3b_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_Ahj4_EINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1y_Kj2_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_IB1z_INtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_ERShEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB39_INtNtNtB3f_7sources4once4OnceB1y_EB45_EB45_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherRShB23_EINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB2g_3map3MapIB2c_INtNtNtB2i_7sources4once4OnceB23_EB3p_ENcNtB1y_4Left0EIB34_B3p_NcNtB1y_5Right0EEE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeRAhj1_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeRAhj20_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1y_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner35alloc_write_and_return_pointer_sizeRShINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB1C_INtNtNtB1I_7sources4once4OnceB1y_EB2y_EB2y_EE0Bc_ |
3830 | 1.86k | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); |
3831 | 1.86k | } |
3832 | | |
3833 | 683 | let ret_val = (u64::from(data_len) << 32) | u64::from(dest_ptr); |
3834 | 683 | let ret_val = i64::from_ne_bytes(ret_val.to_ne_bytes()); |
3835 | 683 | |
3836 | 683 | ReadyToRun { |
3837 | 683 | inner: self, |
3838 | 683 | resume_value: Some(vm::WasmValue::I64(ret_val)), |
3839 | 683 | } |
3840 | 683 | .into() |
3841 | 683 | } Unexecuted instantiation: _RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeAhj1_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1v_EEBa_ _RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_Ahj4_EIB1w_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtNtB2n_7sources4once4OnceB1v_EB38_EB38_EEBa_ Line | Count | Source | 3803 | 14 | fn alloc_write_and_return_pointer_size( | 3804 | 14 | mut self: Box<Self>, | 3805 | 14 | function_name: &'static str, | 3806 | 14 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3807 | 14 | ) -> HostVm { | 3808 | 14 | let mut data_len = 0u32; | 3809 | 16 | for chunk in data.clone()14 { | 3810 | 16 | data_len = | 3811 | 16 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3812 | 16 | } | 3813 | | | 3814 | 14 | let dest_ptr = match self.alloc(function_name, data_len) { | 3815 | 14 | Ok(p) => p, | 3816 | 0 | Err(error) => { | 3817 | 0 | return HostVm::Error { | 3818 | 0 | error, | 3819 | 0 | prototype: self.into_prototype(), | 3820 | 0 | } | 3821 | | } | 3822 | | }; | 3823 | | | 3824 | 14 | let mut ptr_iter = dest_ptr; | 3825 | 30 | for chunk16 in data { | 3826 | 16 | let chunk = chunk.as_ref(); | 3827 | 16 | self.vm | 3828 | 16 | .write_memory(ptr_iter, chunk) | 3829 | 16 | .unwrap_or_else(|_| unreachable!()); | 3830 | 16 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3831 | 16 | } | 3832 | | | 3833 | 14 | let ret_val = (u64::from(data_len) << 32) | u64::from(dest_ptr); | 3834 | 14 | let ret_val = i64::from_ne_bytes(ret_val.to_ne_bytes()); | 3835 | 14 | | 3836 | 14 | ReadyToRun { | 3837 | 14 | inner: self, | 3838 | 14 | resume_value: Some(vm::WasmValue::I64(ret_val)), | 3839 | 14 | } | 3840 | 14 | .into() | 3841 | 14 | } |
_RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_Ahj4_EINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1v_Kj2_EEBa_ Line | Count | Source | 3803 | 5 | fn alloc_write_and_return_pointer_size( | 3804 | 5 | mut self: Box<Self>, | 3805 | 5 | function_name: &'static str, | 3806 | 5 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3807 | 5 | ) -> HostVm { | 3808 | 5 | let mut data_len = 0u32; | 3809 | 10 | for chunk in data.clone()5 { | 3810 | 10 | data_len = | 3811 | 10 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3812 | 10 | } | 3813 | | | 3814 | 5 | let dest_ptr = match self.alloc(function_name, data_len) { | 3815 | 5 | Ok(p) => p, | 3816 | 0 | Err(error) => { | 3817 | 0 | return HostVm::Error { | 3818 | 0 | error, | 3819 | 0 | prototype: self.into_prototype(), | 3820 | 0 | } | 3821 | | } | 3822 | | }; | 3823 | | | 3824 | 5 | let mut ptr_iter = dest_ptr; | 3825 | 15 | for chunk10 in data { | 3826 | 10 | let chunk = chunk.as_ref(); | 3827 | 10 | self.vm | 3828 | 10 | .write_memory(ptr_iter, chunk) | 3829 | 10 | .unwrap_or_else(|_| unreachable!()); | 3830 | 10 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3831 | 10 | } | 3832 | | | 3833 | 5 | let ret_val = (u64::from(data_len) << 32) | u64::from(dest_ptr); | 3834 | 5 | let ret_val = i64::from_ne_bytes(ret_val.to_ne_bytes()); | 3835 | 5 | | 3836 | 5 | ReadyToRun { | 3837 | 5 | inner: self, | 3838 | 5 | resume_value: Some(vm::WasmValue::I64(ret_val)), | 3839 | 5 | } | 3840 | 5 | .into() | 3841 | 5 | } |
Unexecuted instantiation: _RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_IB1w_INtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_ERShEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB36_INtNtNtB3c_7sources4once4OnceB1v_EB42_EB42_EEBa_ _RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherRShB20_EINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB2d_3map3MapIB29_INtNtNtB2f_7sources4once4OnceB20_EB3m_ENcNtB1v_4Left0EIB31_B3m_NcNtB1v_5Right0EEEBa_ Line | Count | Source | 3803 | 504 | fn alloc_write_and_return_pointer_size( | 3804 | 504 | mut self: Box<Self>, | 3805 | 504 | function_name: &'static str, | 3806 | 504 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3807 | 504 | ) -> HostVm { | 3808 | 504 | let mut data_len = 0u32; | 3809 | 1.51k | for chunk in data.clone()504 { | 3810 | 1.51k | data_len = | 3811 | 1.51k | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3812 | 1.51k | } | 3813 | | | 3814 | 504 | let dest_ptr = match self.alloc(function_name, data_len) { | 3815 | 504 | Ok(p) => p, | 3816 | 0 | Err(error) => { | 3817 | 0 | return HostVm::Error { | 3818 | 0 | error, | 3819 | 0 | prototype: self.into_prototype(), | 3820 | 0 | } | 3821 | | } | 3822 | | }; | 3823 | | | 3824 | 504 | let mut ptr_iter = dest_ptr; | 3825 | 2.01k | for chunk1.51k in data { | 3826 | 1.51k | let chunk = chunk.as_ref(); | 3827 | 1.51k | self.vm | 3828 | 1.51k | .write_memory(ptr_iter, chunk) | 3829 | 1.51k | .unwrap_or_else(|_| unreachable!()); | 3830 | 1.51k | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3831 | 1.51k | } | 3832 | | | 3833 | 504 | let ret_val = (u64::from(data_len) << 32) | u64::from(dest_ptr); | 3834 | 504 | let ret_val = i64::from_ne_bytes(ret_val.to_ne_bytes()); | 3835 | 504 | | 3836 | 504 | ReadyToRun { | 3837 | 504 | inner: self, | 3838 | 504 | resume_value: Some(vm::WasmValue::I64(ret_val)), | 3839 | 504 | } | 3840 | 504 | .into() | 3841 | 504 | } |
_RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeRAhj1_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1v_EEBa_ Line | Count | Source | 3803 | 69 | fn alloc_write_and_return_pointer_size( | 3804 | 69 | mut self: Box<Self>, | 3805 | 69 | function_name: &'static str, | 3806 | 69 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3807 | 69 | ) -> HostVm { | 3808 | 69 | let mut data_len = 0u32; | 3809 | 69 | for chunk in data.clone() { | 3810 | 69 | data_len = | 3811 | 69 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3812 | 69 | } | 3813 | | | 3814 | 69 | let dest_ptr = match self.alloc(function_name, data_len) { | 3815 | 69 | Ok(p) => p, | 3816 | 0 | Err(error) => { | 3817 | 0 | return HostVm::Error { | 3818 | 0 | error, | 3819 | 0 | prototype: self.into_prototype(), | 3820 | 0 | } | 3821 | | } | 3822 | | }; | 3823 | | | 3824 | 69 | let mut ptr_iter = dest_ptr; | 3825 | 138 | for chunk69 in data { | 3826 | 69 | let chunk = chunk.as_ref(); | 3827 | 69 | self.vm | 3828 | 69 | .write_memory(ptr_iter, chunk) | 3829 | 69 | .unwrap_or_else(|_| unreachable!()); | 3830 | 69 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3831 | 69 | } | 3832 | | | 3833 | 69 | let ret_val = (u64::from(data_len) << 32) | u64::from(dest_ptr); | 3834 | 69 | let ret_val = i64::from_ne_bytes(ret_val.to_ne_bytes()); | 3835 | 69 | | 3836 | 69 | ReadyToRun { | 3837 | 69 | inner: self, | 3838 | 69 | resume_value: Some(vm::WasmValue::I64(ret_val)), | 3839 | 69 | } | 3840 | 69 | .into() | 3841 | 69 | } |
_RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeRAhj20_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1v_EEBa_ Line | Count | Source | 3803 | 5 | fn alloc_write_and_return_pointer_size( | 3804 | 5 | mut self: Box<Self>, | 3805 | 5 | function_name: &'static str, | 3806 | 5 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3807 | 5 | ) -> HostVm { | 3808 | 5 | let mut data_len = 0u32; | 3809 | 5 | for chunk in data.clone() { | 3810 | 5 | data_len = | 3811 | 5 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3812 | 5 | } | 3813 | | | 3814 | 5 | let dest_ptr = match self.alloc(function_name, data_len) { | 3815 | 5 | Ok(p) => p, | 3816 | 0 | Err(error) => { | 3817 | 0 | return HostVm::Error { | 3818 | 0 | error, | 3819 | 0 | prototype: self.into_prototype(), | 3820 | 0 | } | 3821 | | } | 3822 | | }; | 3823 | | | 3824 | 5 | let mut ptr_iter = dest_ptr; | 3825 | 10 | for chunk5 in data { | 3826 | 5 | let chunk = chunk.as_ref(); | 3827 | 5 | self.vm | 3828 | 5 | .write_memory(ptr_iter, chunk) | 3829 | 5 | .unwrap_or_else(|_| unreachable!()); | 3830 | 5 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3831 | 5 | } | 3832 | | | 3833 | 5 | let ret_val = (u64::from(data_len) << 32) | u64::from(dest_ptr); | 3834 | 5 | let ret_val = i64::from_ne_bytes(ret_val.to_ne_bytes()); | 3835 | 5 | | 3836 | 5 | ReadyToRun { | 3837 | 5 | inner: self, | 3838 | 5 | resume_value: Some(vm::WasmValue::I64(ret_val)), | 3839 | 5 | } | 3840 | 5 | .into() | 3841 | 5 | } |
Unexecuted instantiation: _RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1v_EEBa_ _RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1v_EEBa_ Line | Count | Source | 3803 | 1 | fn alloc_write_and_return_pointer_size( | 3804 | 1 | mut self: Box<Self>, | 3805 | 1 | function_name: &'static str, | 3806 | 1 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3807 | 1 | ) -> HostVm { | 3808 | 1 | let mut data_len = 0u32; | 3809 | 1 | for chunk in data.clone() { | 3810 | 1 | data_len = | 3811 | 1 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3812 | 1 | } | 3813 | | | 3814 | 1 | let dest_ptr = match self.alloc(function_name, data_len) { | 3815 | 1 | Ok(p) => p, | 3816 | 0 | Err(error) => { | 3817 | 0 | return HostVm::Error { | 3818 | 0 | error, | 3819 | 0 | prototype: self.into_prototype(), | 3820 | 0 | } | 3821 | | } | 3822 | | }; | 3823 | | | 3824 | 1 | let mut ptr_iter = dest_ptr; | 3825 | 2 | for chunk1 in data { | 3826 | 1 | let chunk = chunk.as_ref(); | 3827 | 1 | self.vm | 3828 | 1 | .write_memory(ptr_iter, chunk) | 3829 | 1 | .unwrap_or_else(|_| unreachable!()); | 3830 | 1 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3831 | 1 | } | 3832 | | | 3833 | 1 | let ret_val = (u64::from(data_len) << 32) | u64::from(dest_ptr); | 3834 | 1 | let ret_val = i64::from_ne_bytes(ret_val.to_ne_bytes()); | 3835 | 1 | | 3836 | 1 | ReadyToRun { | 3837 | 1 | inner: self, | 3838 | 1 | resume_value: Some(vm::WasmValue::I64(ret_val)), | 3839 | 1 | } | 3840 | 1 | .into() | 3841 | 1 | } |
_RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeRShINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB1z_INtNtNtB1F_7sources4once4OnceB1v_EB2v_EB2v_EEBa_ Line | Count | Source | 3803 | 1 | fn alloc_write_and_return_pointer_size( | 3804 | 1 | mut self: Box<Self>, | 3805 | 1 | function_name: &'static str, | 3806 | 1 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3807 | 1 | ) -> HostVm { | 3808 | 1 | let mut data_len = 0u32; | 3809 | 3 | for chunk in data.clone()1 { | 3810 | 3 | data_len = | 3811 | 3 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3812 | 3 | } | 3813 | | | 3814 | 1 | let dest_ptr = match self.alloc(function_name, data_len) { | 3815 | 1 | Ok(p) => p, | 3816 | 0 | Err(error) => { | 3817 | 0 | return HostVm::Error { | 3818 | 0 | error, | 3819 | 0 | prototype: self.into_prototype(), | 3820 | 0 | } | 3821 | | } | 3822 | | }; | 3823 | | | 3824 | 1 | let mut ptr_iter = dest_ptr; | 3825 | 4 | for chunk3 in data { | 3826 | 3 | let chunk = chunk.as_ref(); | 3827 | 3 | self.vm | 3828 | 3 | .write_memory(ptr_iter, chunk) | 3829 | 3 | .unwrap_or_else(|_| unreachable!()); | 3830 | 3 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3831 | 3 | } | 3832 | | | 3833 | 1 | let ret_val = (u64::from(data_len) << 32) | u64::from(dest_ptr); | 3834 | 1 | let ret_val = i64::from_ne_bytes(ret_val.to_ne_bytes()); | 3835 | 1 | | 3836 | 1 | ReadyToRun { | 3837 | 1 | inner: self, | 3838 | 1 | resume_value: Some(vm::WasmValue::I64(ret_val)), | 3839 | 1 | } | 3840 | 1 | .into() | 3841 | 1 | } |
Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeAhj1_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1w_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_Ahj4_EIB1x_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtNtB2o_7sources4once4OnceB1w_EB39_EB39_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_Ahj4_EINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1w_Kj2_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherAhj1_IB1x_INtNtCsjZUZ4cETtOy_8arrayvec8arrayvec8ArrayVechKj9_ERShEEINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB37_INtNtNtB3d_7sources4once4OnceB1w_EB43_EB43_EEBa_ _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeINtCs1qmLyiTSqYF_6either6EitherRShB21_EINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtB2e_3map3MapIB2a_INtNtNtB2g_7sources4once4OnceB21_EB3n_ENcNtB1w_4Left0EIB32_B3n_NcNtB1w_5Right0EEEBa_ Line | Count | Source | 3803 | 84 | fn alloc_write_and_return_pointer_size( | 3804 | 84 | mut self: Box<Self>, | 3805 | 84 | function_name: &'static str, | 3806 | 84 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3807 | 84 | ) -> HostVm { | 3808 | 84 | let mut data_len = 0u32; | 3809 | 252 | for chunk in data.clone()84 { | 3810 | 252 | data_len = | 3811 | 252 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3812 | 252 | } | 3813 | | | 3814 | 84 | let dest_ptr = match self.alloc(function_name, data_len) { | 3815 | 84 | Ok(p) => p, | 3816 | 0 | Err(error) => { | 3817 | 0 | return HostVm::Error { | 3818 | 0 | error, | 3819 | 0 | prototype: self.into_prototype(), | 3820 | 0 | } | 3821 | | } | 3822 | | }; | 3823 | | | 3824 | 84 | let mut ptr_iter = dest_ptr; | 3825 | 336 | for chunk252 in data { | 3826 | 252 | let chunk = chunk.as_ref(); | 3827 | 252 | self.vm | 3828 | 252 | .write_memory(ptr_iter, chunk) | 3829 | 252 | .unwrap_or_else(|_| unreachable!()); | 3830 | 252 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3831 | 252 | } | 3832 | | | 3833 | 84 | let ret_val = (u64::from(data_len) << 32) | u64::from(dest_ptr); | 3834 | 84 | let ret_val = i64::from_ne_bytes(ret_val.to_ne_bytes()); | 3835 | 84 | | 3836 | 84 | ReadyToRun { | 3837 | 84 | inner: self, | 3838 | 84 | resume_value: Some(vm::WasmValue::I64(ret_val)), | 3839 | 84 | } | 3840 | 84 | .into() | 3841 | 84 | } |
Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeRAhj1_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1w_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeRAhj20_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1w_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeRINtNtCsdZExvAaxgia_5alloc3vec3VechEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1w_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1w_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner35alloc_write_and_return_pointer_sizeRShINtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB1A_INtNtNtB1G_7sources4once4OnceB1w_EB2w_EB2w_EEBa_ |
3842 | | |
3843 | | /// Uses the memory allocator to allocate some memory for the given data, writes the data in |
3844 | | /// memory, and returns an [`HostVm`] ready for the Wasm `host_fn` return. |
3845 | | /// |
3846 | | /// The data is passed as a list of chunks. These chunks will be laid out linearly in memory. |
3847 | | /// |
3848 | | /// The function name passed as parameter is used for error-reporting reasons. |
3849 | | /// |
3850 | | /// # Panic |
3851 | | /// |
3852 | | /// Must only be called while the Wasm is handling an `host_fn`. |
3853 | | /// |
3854 | 2.07k | fn alloc_write_and_return_pointer( |
3855 | 2.07k | mut self: Box<Self>, |
3856 | 2.07k | function_name: &'static str, |
3857 | 2.07k | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, |
3858 | 2.07k | ) -> HostVm { |
3859 | 2.07k | let mut data_len = 0u32; |
3860 | 3.89k | for chunk in data.clone()2.07k { |
3861 | 3.89k | data_len = |
3862 | 3.89k | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); |
3863 | 3.89k | } |
3864 | | |
3865 | 2.07k | let dest_ptr = match self.alloc(function_name, data_len) { |
3866 | 2.07k | Ok(p) => p, |
3867 | 0 | Err(error) => { |
3868 | 0 | return HostVm::Error { |
3869 | 0 | error, |
3870 | 0 | prototype: self.into_prototype(), |
3871 | 0 | } |
3872 | | } |
3873 | | }; |
3874 | | |
3875 | 2.07k | let mut ptr_iter = dest_ptr; |
3876 | 5.97k | for chunk3.89k in data { |
3877 | 3.89k | let chunk = chunk.as_ref(); |
3878 | 3.89k | self.vm |
3879 | 3.89k | .write_memory(ptr_iter, chunk) |
3880 | 3.89k | .unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRAhj20_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB1z_IB1z_INtNtNtB1F_7sources4once4OnceB1s_EB2A_EB2A_EB2A_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtNtB1F_7sources4once4OnceB1s_EB2q_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRINtCskYLzYmOFGAo_13generic_array12GenericArrayhINtNtCsg8gh8wv4eQn_7typenum4uint4UIntIB2f_IB2f_IB2f_IB2f_IB2f_IB2f_NtB2h_5UTermNtNtB2j_3bit2B1ENtB3x_2B0EB3L_EB3L_EB3L_EB3L_EB3L_EEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRINtCskYLzYmOFGAo_13generic_array12GenericArrayhINtNtCsg8gh8wv4eQn_7typenum4uint4UIntIB2f_IB2f_IB2f_IB2f_IB2f_NtB2h_5UTermNtNtB2j_3bit2B1ENtB3s_2B0EB3G_EB3G_EB3G_EB3G_EEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRShINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1s_Kj2_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1s_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerAhj20_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1t_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRAhj20_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1t_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1t_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB1A_IB1A_INtNtNtB1G_7sources4once4OnceB1t_EB2B_EB2B_EB2B_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtNtB1G_7sources4once4OnceB1t_EB2r_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRINtCskYLzYmOFGAo_13generic_array12GenericArrayhINtNtCsg8gh8wv4eQn_7typenum4uint4UIntIB2g_IB2g_IB2g_IB2g_IB2g_IB2g_NtB2i_5UTermNtNtB2k_3bit2B1ENtB3y_2B0EB3M_EB3M_EB3M_EB3M_EB3M_EEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1t_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRINtCskYLzYmOFGAo_13generic_array12GenericArrayhINtNtCsg8gh8wv4eQn_7typenum4uint4UIntIB2g_IB2g_IB2g_IB2g_IB2g_NtB2i_5UTermNtNtB2k_3bit2B1ENtB3t_2B0EB3H_EB3H_EB3H_EB3H_EEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1t_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRShINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1t_Kj2_EE0Bc_ Unexecuted instantiation: _RNCINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB8_5Inner30alloc_write_and_return_pointerRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1t_EE0Bc_ |
3881 | 3.89k | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); |
3882 | 3.89k | } |
3883 | | |
3884 | 2.07k | let ret_val = i32::from_ne_bytes(dest_ptr.to_ne_bytes()); |
3885 | 2.07k | ReadyToRun { |
3886 | 2.07k | inner: self, |
3887 | 2.07k | resume_value: Some(vm::WasmValue::I32(ret_val)), |
3888 | 2.07k | } |
3889 | 2.07k | .into() |
3890 | 2.07k | } _RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRAhj20_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEBa_ Line | Count | Source | 3854 | 5 | fn alloc_write_and_return_pointer( | 3855 | 5 | mut self: Box<Self>, | 3856 | 5 | function_name: &'static str, | 3857 | 5 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3858 | 5 | ) -> HostVm { | 3859 | 5 | let mut data_len = 0u32; | 3860 | 5 | for chunk in data.clone() { | 3861 | 5 | data_len = | 3862 | 5 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3863 | 5 | } | 3864 | | | 3865 | 5 | let dest_ptr = match self.alloc(function_name, data_len) { | 3866 | 5 | Ok(p) => p, | 3867 | 0 | Err(error) => { | 3868 | 0 | return HostVm::Error { | 3869 | 0 | error, | 3870 | 0 | prototype: self.into_prototype(), | 3871 | 0 | } | 3872 | | } | 3873 | | }; | 3874 | | | 3875 | 5 | let mut ptr_iter = dest_ptr; | 3876 | 10 | for chunk5 in data { | 3877 | 5 | let chunk = chunk.as_ref(); | 3878 | 5 | self.vm | 3879 | 5 | .write_memory(ptr_iter, chunk) | 3880 | 5 | .unwrap_or_else(|_| unreachable!()); | 3881 | 5 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3882 | 5 | } | 3883 | | | 3884 | 5 | let ret_val = i32::from_ne_bytes(dest_ptr.to_ne_bytes()); | 3885 | 5 | ReadyToRun { | 3886 | 5 | inner: self, | 3887 | 5 | resume_value: Some(vm::WasmValue::I32(ret_val)), | 3888 | 5 | } | 3889 | 5 | .into() | 3890 | 5 | } |
_RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEBa_ Line | Count | Source | 3854 | 67 | fn alloc_write_and_return_pointer( | 3855 | 67 | mut self: Box<Self>, | 3856 | 67 | function_name: &'static str, | 3857 | 67 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3858 | 67 | ) -> HostVm { | 3859 | 67 | let mut data_len = 0u32; | 3860 | 67 | for chunk in data.clone() { | 3861 | 67 | data_len = | 3862 | 67 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3863 | 67 | } | 3864 | | | 3865 | 67 | let dest_ptr = match self.alloc(function_name, data_len) { | 3866 | 67 | Ok(p) => p, | 3867 | 0 | Err(error) => { | 3868 | 0 | return HostVm::Error { | 3869 | 0 | error, | 3870 | 0 | prototype: self.into_prototype(), | 3871 | 0 | } | 3872 | | } | 3873 | | }; | 3874 | | | 3875 | 67 | let mut ptr_iter = dest_ptr; | 3876 | 134 | for chunk67 in data { | 3877 | 67 | let chunk = chunk.as_ref(); | 3878 | 67 | self.vm | 3879 | 67 | .write_memory(ptr_iter, chunk) | 3880 | 67 | .unwrap_or_else(|_| unreachable!()); | 3881 | 67 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3882 | 67 | } | 3883 | | | 3884 | 67 | let ret_val = i32::from_ne_bytes(dest_ptr.to_ne_bytes()); | 3885 | 67 | ReadyToRun { | 3886 | 67 | inner: self, | 3887 | 67 | resume_value: Some(vm::WasmValue::I32(ret_val)), | 3888 | 67 | } | 3889 | 67 | .into() | 3890 | 67 | } |
_RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB1x_IB1x_INtNtNtB1D_7sources4once4OnceB1q_EB2y_EB2y_EB2y_EEBa_ Line | Count | Source | 3854 | 2 | fn alloc_write_and_return_pointer( | 3855 | 2 | mut self: Box<Self>, | 3856 | 2 | function_name: &'static str, | 3857 | 2 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3858 | 2 | ) -> HostVm { | 3859 | 2 | let mut data_len = 0u32; | 3860 | 8 | for chunk in data.clone()2 { | 3861 | 8 | data_len = | 3862 | 8 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3863 | 8 | } | 3864 | | | 3865 | 2 | let dest_ptr = match self.alloc(function_name, data_len) { | 3866 | 2 | Ok(p) => p, | 3867 | 0 | Err(error) => { | 3868 | 0 | return HostVm::Error { | 3869 | 0 | error, | 3870 | 0 | prototype: self.into_prototype(), | 3871 | 0 | } | 3872 | | } | 3873 | | }; | 3874 | | | 3875 | 2 | let mut ptr_iter = dest_ptr; | 3876 | 10 | for chunk8 in data { | 3877 | 8 | let chunk = chunk.as_ref(); | 3878 | 8 | self.vm | 3879 | 8 | .write_memory(ptr_iter, chunk) | 3880 | 8 | .unwrap_or_else(|_| unreachable!()); | 3881 | 8 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3882 | 8 | } | 3883 | | | 3884 | 2 | let ret_val = i32::from_ne_bytes(dest_ptr.to_ne_bytes()); | 3885 | 2 | ReadyToRun { | 3886 | 2 | inner: self, | 3887 | 2 | resume_value: Some(vm::WasmValue::I32(ret_val)), | 3888 | 2 | } | 3889 | 2 | .into() | 3890 | 2 | } |
_RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtNtB1D_7sources4once4OnceB1q_EB2o_EEBa_ Line | Count | Source | 3854 | 1.73k | fn alloc_write_and_return_pointer( | 3855 | 1.73k | mut self: Box<Self>, | 3856 | 1.73k | function_name: &'static str, | 3857 | 1.73k | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3858 | 1.73k | ) -> HostVm { | 3859 | 1.73k | let mut data_len = 0u32; | 3860 | 3.46k | for chunk in data.clone()1.73k { | 3861 | 3.46k | data_len = | 3862 | 3.46k | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3863 | 3.46k | } | 3864 | | | 3865 | 1.73k | let dest_ptr = match self.alloc(function_name, data_len) { | 3866 | 1.73k | Ok(p) => p, | 3867 | 0 | Err(error) => { | 3868 | 0 | return HostVm::Error { | 3869 | 0 | error, | 3870 | 0 | prototype: self.into_prototype(), | 3871 | 0 | } | 3872 | | } | 3873 | | }; | 3874 | | | 3875 | 1.73k | let mut ptr_iter = dest_ptr; | 3876 | 5.19k | for chunk3.46k in data { | 3877 | 3.46k | let chunk = chunk.as_ref(); | 3878 | 3.46k | self.vm | 3879 | 3.46k | .write_memory(ptr_iter, chunk) | 3880 | 3.46k | .unwrap_or_else(|_| unreachable!()); | 3881 | 3.46k | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3882 | 3.46k | } | 3883 | | | 3884 | 1.73k | let ret_val = i32::from_ne_bytes(dest_ptr.to_ne_bytes()); | 3885 | 1.73k | ReadyToRun { | 3886 | 1.73k | inner: self, | 3887 | 1.73k | resume_value: Some(vm::WasmValue::I32(ret_val)), | 3888 | 1.73k | } | 3889 | 1.73k | .into() | 3890 | 1.73k | } |
_RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRINtCskYLzYmOFGAo_13generic_array12GenericArrayhINtNtCsg8gh8wv4eQn_7typenum4uint4UIntIB2d_IB2d_IB2d_IB2d_IB2d_IB2d_NtB2f_5UTermNtNtB2h_3bit2B1ENtB3v_2B0EB3J_EB3J_EB3J_EB3J_EB3J_EEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEBa_ Line | Count | Source | 3854 | 2 | fn alloc_write_and_return_pointer( | 3855 | 2 | mut self: Box<Self>, | 3856 | 2 | function_name: &'static str, | 3857 | 2 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3858 | 2 | ) -> HostVm { | 3859 | 2 | let mut data_len = 0u32; | 3860 | 2 | for chunk in data.clone() { | 3861 | 2 | data_len = | 3862 | 2 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3863 | 2 | } | 3864 | | | 3865 | 2 | let dest_ptr = match self.alloc(function_name, data_len) { | 3866 | 2 | Ok(p) => p, | 3867 | 0 | Err(error) => { | 3868 | 0 | return HostVm::Error { | 3869 | 0 | error, | 3870 | 0 | prototype: self.into_prototype(), | 3871 | 0 | } | 3872 | | } | 3873 | | }; | 3874 | | | 3875 | 2 | let mut ptr_iter = dest_ptr; | 3876 | 4 | for chunk2 in data { | 3877 | 2 | let chunk = chunk.as_ref(); | 3878 | 2 | self.vm | 3879 | 2 | .write_memory(ptr_iter, chunk) | 3880 | 2 | .unwrap_or_else(|_| unreachable!()); | 3881 | 2 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3882 | 2 | } | 3883 | | | 3884 | 2 | let ret_val = i32::from_ne_bytes(dest_ptr.to_ne_bytes()); | 3885 | 2 | ReadyToRun { | 3886 | 2 | inner: self, | 3887 | 2 | resume_value: Some(vm::WasmValue::I32(ret_val)), | 3888 | 2 | } | 3889 | 2 | .into() | 3890 | 2 | } |
_RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRINtCskYLzYmOFGAo_13generic_array12GenericArrayhINtNtCsg8gh8wv4eQn_7typenum4uint4UIntIB2d_IB2d_IB2d_IB2d_IB2d_NtB2f_5UTermNtNtB2h_3bit2B1ENtB3q_2B0EB3E_EB3E_EB3E_EB3E_EEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEBa_ Line | Count | Source | 3854 | 4 | fn alloc_write_and_return_pointer( | 3855 | 4 | mut self: Box<Self>, | 3856 | 4 | function_name: &'static str, | 3857 | 4 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3858 | 4 | ) -> HostVm { | 3859 | 4 | let mut data_len = 0u32; | 3860 | 4 | for chunk in data.clone() { | 3861 | 4 | data_len = | 3862 | 4 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3863 | 4 | } | 3864 | | | 3865 | 4 | let dest_ptr = match self.alloc(function_name, data_len) { | 3866 | 4 | Ok(p) => p, | 3867 | 0 | Err(error) => { | 3868 | 0 | return HostVm::Error { | 3869 | 0 | error, | 3870 | 0 | prototype: self.into_prototype(), | 3871 | 0 | } | 3872 | | } | 3873 | | }; | 3874 | | | 3875 | 4 | let mut ptr_iter = dest_ptr; | 3876 | 8 | for chunk4 in data { | 3877 | 4 | let chunk = chunk.as_ref(); | 3878 | 4 | self.vm | 3879 | 4 | .write_memory(ptr_iter, chunk) | 3880 | 4 | .unwrap_or_else(|_| unreachable!()); | 3881 | 4 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3882 | 4 | } | 3883 | | | 3884 | 4 | let ret_val = i32::from_ne_bytes(dest_ptr.to_ne_bytes()); | 3885 | 4 | ReadyToRun { | 3886 | 4 | inner: self, | 3887 | 4 | resume_value: Some(vm::WasmValue::I32(ret_val)), | 3888 | 4 | } | 3889 | 4 | .into() | 3890 | 4 | } |
Unexecuted instantiation: _RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRShINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1q_Kj2_EEBa_ _RINvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1q_EEBa_ Line | Count | Source | 3854 | 178 | fn alloc_write_and_return_pointer( | 3855 | 178 | mut self: Box<Self>, | 3856 | 178 | function_name: &'static str, | 3857 | 178 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3858 | 178 | ) -> HostVm { | 3859 | 178 | let mut data_len = 0u32; | 3860 | 178 | for chunk in data.clone() { | 3861 | 178 | data_len = | 3862 | 178 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3863 | 178 | } | 3864 | | | 3865 | 178 | let dest_ptr = match self.alloc(function_name, data_len) { | 3866 | 178 | Ok(p) => p, | 3867 | 0 | Err(error) => { | 3868 | 0 | return HostVm::Error { | 3869 | 0 | error, | 3870 | 0 | prototype: self.into_prototype(), | 3871 | 0 | } | 3872 | | } | 3873 | | }; | 3874 | | | 3875 | 178 | let mut ptr_iter = dest_ptr; | 3876 | 356 | for chunk178 in data { | 3877 | 178 | let chunk = chunk.as_ref(); | 3878 | 178 | self.vm | 3879 | 178 | .write_memory(ptr_iter, chunk) | 3880 | 178 | .unwrap_or_else(|_| unreachable!()); | 3881 | 178 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3882 | 178 | } | 3883 | | | 3884 | 178 | let ret_val = i32::from_ne_bytes(dest_ptr.to_ne_bytes()); | 3885 | 178 | ReadyToRun { | 3886 | 178 | inner: self, | 3887 | 178 | resume_value: Some(vm::WasmValue::I32(ret_val)), | 3888 | 178 | } | 3889 | 178 | .into() | 3890 | 178 | } |
Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerAhj20_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRAhj20_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainIB1y_IB1y_INtNtNtB1E_7sources4once4OnceB1r_EB2z_EB2z_EB2z_EEBa_ _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRAhj8_INtNtNtNtCsaYZPK01V26L_4core4iter8adapters5chain5ChainINtNtNtB1E_7sources4once4OnceB1r_EB2p_EEBa_ Line | Count | Source | 3854 | 84 | fn alloc_write_and_return_pointer( | 3855 | 84 | mut self: Box<Self>, | 3856 | 84 | function_name: &'static str, | 3857 | 84 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone, | 3858 | 84 | ) -> HostVm { | 3859 | 84 | let mut data_len = 0u32; | 3860 | 168 | for chunk in data.clone()84 { | 3861 | 168 | data_len = | 3862 | 168 | data_len.saturating_add(u32::try_from(chunk.as_ref().len()).unwrap_or(u32::MAX)); | 3863 | 168 | } | 3864 | | | 3865 | 84 | let dest_ptr = match self.alloc(function_name, data_len) { | 3866 | 84 | Ok(p) => p, | 3867 | 0 | Err(error) => { | 3868 | 0 | return HostVm::Error { | 3869 | 0 | error, | 3870 | 0 | prototype: self.into_prototype(), | 3871 | 0 | } | 3872 | | } | 3873 | | }; | 3874 | | | 3875 | 84 | let mut ptr_iter = dest_ptr; | 3876 | 252 | for chunk168 in data { | 3877 | 168 | let chunk = chunk.as_ref(); | 3878 | 168 | self.vm | 3879 | 168 | .write_memory(ptr_iter, chunk) | 3880 | 168 | .unwrap_or_else(|_| unreachable!()); | 3881 | 168 | ptr_iter += u32::try_from(chunk.len()).unwrap_or(u32::MAX); | 3882 | 168 | } | 3883 | | | 3884 | 84 | let ret_val = i32::from_ne_bytes(dest_ptr.to_ne_bytes()); | 3885 | 84 | ReadyToRun { | 3886 | 84 | inner: self, | 3887 | 84 | resume_value: Some(vm::WasmValue::I32(ret_val)), | 3888 | 84 | } | 3889 | 84 | .into() | 3890 | 84 | } |
Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRINtCskYLzYmOFGAo_13generic_array12GenericArrayhINtNtCsg8gh8wv4eQn_7typenum4uint4UIntIB2e_IB2e_IB2e_IB2e_IB2e_IB2e_NtB2g_5UTermNtNtB2i_3bit2B1ENtB3w_2B0EB3K_EB3K_EB3K_EB3K_EB3K_EEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRINtCskYLzYmOFGAo_13generic_array12GenericArrayhINtNtCsg8gh8wv4eQn_7typenum4uint4UIntIB2e_IB2e_IB2e_IB2e_IB2e_NtB2g_5UTermNtNtB2i_3bit2B1ENtB3r_2B0EB3F_EB3F_EB3F_EB3F_EEINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRShINtNtNtCsaYZPK01V26L_4core5array4iter8IntoIterB1r_Kj2_EEBa_ Unexecuted instantiation: _RINvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5Inner30alloc_write_and_return_pointerRShINtNtNtNtCsaYZPK01V26L_4core4iter7sources4once4OnceB1r_EEBa_ |
3891 | | |
3892 | | /// Uses the memory allocator to allocate some memory. |
3893 | | /// |
3894 | | /// The function name passed as parameter is used for error-reporting reasons. |
3895 | | /// |
3896 | | /// # Panic |
3897 | | /// |
3898 | | /// Must only be called while the Wasm is handling an `host_fn`. |
3899 | | /// |
3900 | 16.8k | fn alloc(&mut self, function_name: &'static str, size: u32) -> Result<u32, Error> { |
3901 | | // Use the allocator to decide where the value will be written. |
3902 | 16.8k | let dest_ptr = match self.allocator.allocate( |
3903 | 16.8k | &mut MemAccess { |
3904 | 16.8k | vm: MemAccessVm::Running(&mut self.vm), |
3905 | 16.8k | memory_total_pages: self.common.memory_total_pages, |
3906 | 16.8k | }, |
3907 | 16.8k | size, |
3908 | 16.8k | ) { |
3909 | 16.8k | Ok(p) => p, |
3910 | | Err(_) => { |
3911 | 0 | return Err(Error::OutOfMemory { |
3912 | 0 | function: function_name, |
3913 | 0 | requested_size: size, |
3914 | 0 | }) |
3915 | | } |
3916 | | }; |
3917 | | |
3918 | | // Unfortunately this function doesn't stop here. |
3919 | | // We lie to the allocator. The allocator thinks that there are `self.memory_total_pages` |
3920 | | // allocated and available, while in reality it can be less. |
3921 | | // The allocator might thus allocate memory at a location above the current memory size. |
3922 | | // To handle this, we grow the memory. |
3923 | | |
3924 | | // Offset of the memory page where the last allocated byte is found. |
3925 | 16.8k | let last_byte_memory_page = HeapPages::new((dest_ptr + size - 1) / (64 * 1024)); |
3926 | 16.8k | |
3927 | 16.8k | // Grow the memory more if necessary. |
3928 | 16.8k | // Please note the `=`. For example if we write to page 0, we want to have at least 1 page |
3929 | 16.8k | // allocated. |
3930 | 16.8k | let current_num_pages = self.vm.memory_size(); |
3931 | 16.8k | debug_assert!(current_num_pages <= self.common.memory_total_pages); |
3932 | 16.8k | if current_num_pages <= last_byte_memory_page { |
3933 | 39 | // For now, we grow the memory just enough to fit. |
3934 | 39 | // TODO: do better |
3935 | 39 | // Note the order of operations: we add 1 at the end to avoid a potential overflow |
3936 | 39 | // in case `last_byte_memory_page` is the maximum possible value. |
3937 | 39 | let to_grow = last_byte_memory_page - current_num_pages + HeapPages::new(1); |
3938 | 39 | |
3939 | 39 | // We check at initialization that the virtual machine is capable of growing up to |
3940 | 39 | // `memory_total_pages`, meaning that this can't panic. |
3941 | 39 | self.vm |
3942 | 39 | .grow_memory(to_grow) |
3943 | 39 | .unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCNvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_5Inner5alloc0Bb_ Unexecuted instantiation: _RNCNvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_5Inner5alloc0Bb_ |
3944 | 16.8k | } |
3945 | | |
3946 | 16.8k | Ok(dest_ptr) |
3947 | 16.8k | } _RNvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_5Inner5alloc Line | Count | Source | 3900 | 14.3k | fn alloc(&mut self, function_name: &'static str, size: u32) -> Result<u32, Error> { | 3901 | | // Use the allocator to decide where the value will be written. | 3902 | 14.3k | let dest_ptr = match self.allocator.allocate( | 3903 | 14.3k | &mut MemAccess { | 3904 | 14.3k | vm: MemAccessVm::Running(&mut self.vm), | 3905 | 14.3k | memory_total_pages: self.common.memory_total_pages, | 3906 | 14.3k | }, | 3907 | 14.3k | size, | 3908 | 14.3k | ) { | 3909 | 14.3k | Ok(p) => p, | 3910 | | Err(_) => { | 3911 | 0 | return Err(Error::OutOfMemory { | 3912 | 0 | function: function_name, | 3913 | 0 | requested_size: size, | 3914 | 0 | }) | 3915 | | } | 3916 | | }; | 3917 | | | 3918 | | // Unfortunately this function doesn't stop here. | 3919 | | // We lie to the allocator. The allocator thinks that there are `self.memory_total_pages` | 3920 | | // allocated and available, while in reality it can be less. | 3921 | | // The allocator might thus allocate memory at a location above the current memory size. | 3922 | | // To handle this, we grow the memory. | 3923 | | | 3924 | | // Offset of the memory page where the last allocated byte is found. | 3925 | 14.3k | let last_byte_memory_page = HeapPages::new((dest_ptr + size - 1) / (64 * 1024)); | 3926 | 14.3k | | 3927 | 14.3k | // Grow the memory more if necessary. | 3928 | 14.3k | // Please note the `=`. For example if we write to page 0, we want to have at least 1 page | 3929 | 14.3k | // allocated. | 3930 | 14.3k | let current_num_pages = self.vm.memory_size(); | 3931 | 14.3k | debug_assert!(current_num_pages <= self.common.memory_total_pages); | 3932 | 14.3k | if current_num_pages <= last_byte_memory_page { | 3933 | 34 | // For now, we grow the memory just enough to fit. | 3934 | 34 | // TODO: do better | 3935 | 34 | // Note the order of operations: we add 1 at the end to avoid a potential overflow | 3936 | 34 | // in case `last_byte_memory_page` is the maximum possible value. | 3937 | 34 | let to_grow = last_byte_memory_page - current_num_pages + HeapPages::new(1); | 3938 | 34 | | 3939 | 34 | // We check at initialization that the virtual machine is capable of growing up to | 3940 | 34 | // `memory_total_pages`, meaning that this can't panic. | 3941 | 34 | self.vm | 3942 | 34 | .grow_memory(to_grow) | 3943 | 34 | .unwrap_or_else(|_| unreachable!()); | 3944 | 14.3k | } | 3945 | | | 3946 | 14.3k | Ok(dest_ptr) | 3947 | 14.3k | } |
_RNvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_5Inner5alloc Line | Count | Source | 3900 | 2.53k | fn alloc(&mut self, function_name: &'static str, size: u32) -> Result<u32, Error> { | 3901 | | // Use the allocator to decide where the value will be written. | 3902 | 2.53k | let dest_ptr = match self.allocator.allocate( | 3903 | 2.53k | &mut MemAccess { | 3904 | 2.53k | vm: MemAccessVm::Running(&mut self.vm), | 3905 | 2.53k | memory_total_pages: self.common.memory_total_pages, | 3906 | 2.53k | }, | 3907 | 2.53k | size, | 3908 | 2.53k | ) { | 3909 | 2.53k | Ok(p) => p, | 3910 | | Err(_) => { | 3911 | 0 | return Err(Error::OutOfMemory { | 3912 | 0 | function: function_name, | 3913 | 0 | requested_size: size, | 3914 | 0 | }) | 3915 | | } | 3916 | | }; | 3917 | | | 3918 | | // Unfortunately this function doesn't stop here. | 3919 | | // We lie to the allocator. The allocator thinks that there are `self.memory_total_pages` | 3920 | | // allocated and available, while in reality it can be less. | 3921 | | // The allocator might thus allocate memory at a location above the current memory size. | 3922 | | // To handle this, we grow the memory. | 3923 | | | 3924 | | // Offset of the memory page where the last allocated byte is found. | 3925 | 2.53k | let last_byte_memory_page = HeapPages::new((dest_ptr + size - 1) / (64 * 1024)); | 3926 | 2.53k | | 3927 | 2.53k | // Grow the memory more if necessary. | 3928 | 2.53k | // Please note the `=`. For example if we write to page 0, we want to have at least 1 page | 3929 | 2.53k | // allocated. | 3930 | 2.53k | let current_num_pages = self.vm.memory_size(); | 3931 | 2.53k | debug_assert!(current_num_pages <= self.common.memory_total_pages); | 3932 | 2.53k | if current_num_pages <= last_byte_memory_page { | 3933 | 5 | // For now, we grow the memory just enough to fit. | 3934 | 5 | // TODO: do better | 3935 | 5 | // Note the order of operations: we add 1 at the end to avoid a potential overflow | 3936 | 5 | // in case `last_byte_memory_page` is the maximum possible value. | 3937 | 5 | let to_grow = last_byte_memory_page - current_num_pages + HeapPages::new(1); | 3938 | 5 | | 3939 | 5 | // We check at initialization that the virtual machine is capable of growing up to | 3940 | 5 | // `memory_total_pages`, meaning that this can't panic. | 3941 | 5 | self.vm | 3942 | 5 | .grow_memory(to_grow) | 3943 | 5 | .unwrap_or_else(|_| unreachable!()); | 3944 | 2.53k | } | 3945 | | | 3946 | 2.53k | Ok(dest_ptr) | 3947 | 2.53k | } |
|
3948 | | |
3949 | | /// Turns the virtual machine back into a prototype. |
3950 | 145 | fn into_prototype(self) -> HostVmPrototype { |
3951 | 145 | HostVmPrototype { |
3952 | 145 | vm_proto: self.vm.into_prototype(), |
3953 | 145 | common: self.common, |
3954 | 145 | } |
3955 | 145 | } _RNvMsM_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_5Inner14into_prototype Line | Count | Source | 3950 | 19 | fn into_prototype(self) -> HostVmPrototype { | 3951 | 19 | HostVmPrototype { | 3952 | 19 | vm_proto: self.vm.into_prototype(), | 3953 | 19 | common: self.common, | 3954 | 19 | } | 3955 | 19 | } |
_RNvMsM_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_5Inner14into_prototype Line | Count | Source | 3950 | 126 | fn into_prototype(self) -> HostVmPrototype { | 3951 | 126 | HostVmPrototype { | 3952 | 126 | vm_proto: self.vm.into_prototype(), | 3953 | 126 | common: self.common, | 3954 | 126 | } | 3955 | 126 | } |
|
3956 | | } |
3957 | | |
3958 | | /// Error that can happen when initializing a VM. |
3959 | 0 | #[derive(Debug, derive_more::From, derive_more::Display, Clone)] Unexecuted instantiation: _RNvXs1m_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_6NewErrNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXs1m_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_6NewErrNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
3960 | | pub enum NewErr { |
3961 | | /// Error in the format of the runtime code. |
3962 | | #[display(fmt = "{_0}")] |
3963 | | BadFormat(ModuleFormatError), |
3964 | | /// Error while initializing the virtual machine. |
3965 | | #[display(fmt = "{_0}")] |
3966 | | VirtualMachine(vm::NewErr), |
3967 | | /// Error while finding the runtime-version-related sections in the Wasm blob. |
3968 | | #[display(fmt = "Error in runtime spec Wasm sections: {_0}")] |
3969 | | RuntimeVersion(FindEmbeddedRuntimeVersionError), |
3970 | | /// Error while calling `Core_version` to determine the runtime version. |
3971 | | #[display(fmt = "Error while calling Core_version: {_0}")] |
3972 | | CoreVersion(CoreVersionError), |
3973 | | /// Couldn't find the `__heap_base` symbol in the Wasm code. |
3974 | | HeapBaseNotFound, |
3975 | | /// Maximum size of the Wasm memory found in the module is too low to provide the requested |
3976 | | /// number of heap pages. |
3977 | | MemoryMaxSizeTooLow, |
3978 | | } |
3979 | | |
3980 | | /// Error while determining . |
3981 | 0 | #[derive(Debug, derive_more::Display, Clone)] Unexecuted instantiation: _RNvXs1p_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_31FindEmbeddedRuntimeVersionErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXs1p_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_31FindEmbeddedRuntimeVersionErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
3982 | | pub enum FindEmbeddedRuntimeVersionError { |
3983 | | /// Error while finding the custom section. |
3984 | | #[display(fmt = "{_0}")] |
3985 | | FindSections(FindEncodedEmbeddedRuntimeVersionApisError), |
3986 | | /// Error while decoding the runtime version. |
3987 | | RuntimeVersionDecode, |
3988 | | /// Error while decoding the runtime APIs. |
3989 | | #[display(fmt = "{_0}")] |
3990 | | RuntimeApisDecode(CoreVersionApisFromSliceErr), |
3991 | | } |
3992 | | |
3993 | | /// Error that can happen when starting a VM. |
3994 | 0 | #[derive(Debug, Clone, derive_more::From, derive_more::Display)] Unexecuted instantiation: _RNvXs1v_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_8StartErrNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXs1v_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_8StartErrNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
3995 | | pub enum StartErr { |
3996 | | /// Error while starting the virtual machine. |
3997 | | #[display(fmt = "{_0}")] |
3998 | | VirtualMachine(vm::StartErr), |
3999 | | /// The size of the input data is too large. |
4000 | | DataSizeOverflow, |
4001 | | } |
4002 | | |
4003 | | /// Reason why the Wasm blob isn't conforming to the runtime environment. |
4004 | 0 | #[derive(Debug, Clone, derive_more::Display)] Unexecuted instantiation: _RNvXs1y_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB6_5ErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt Unexecuted instantiation: _RNvXs1y_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB6_5ErrorNtNtCsaYZPK01V26L_4core3fmt7Display3fmt |
4005 | | pub enum Error { |
4006 | | /// Error in the Wasm code execution. |
4007 | | #[display(fmt = "{_0}")] |
4008 | | Trap(vm::Trap), |
4009 | | /// Runtime has called the `ext_panic_handler_abort_on_panic_version_1` host function. |
4010 | | #[display(fmt = "Runtime has aborted: {message:?}")] |
4011 | | AbortOnPanic { |
4012 | | /// Message generated by the runtime. |
4013 | | message: String, |
4014 | | }, |
4015 | | /// A non-`i64` value has been returned by the Wasm entry point. |
4016 | | #[display(fmt = "A non-I64 value has been returned: {actual:?}")] |
4017 | | BadReturnValue { |
4018 | | /// Type that has actually gotten returned. `None` for "void". |
4019 | | actual: Option<vm::ValueType>, |
4020 | | }, |
4021 | | /// The pointer and size returned by the Wasm entry point function are invalid. |
4022 | | #[display(fmt = "The pointer and size returned by the function are invalid")] |
4023 | | ReturnedPtrOutOfRange { |
4024 | | /// Pointer that got returned. |
4025 | | pointer: u32, |
4026 | | /// Size that got returned. |
4027 | | size: u32, |
4028 | | /// Size of the virtual memory. |
4029 | | memory_size: u32, |
4030 | | }, |
4031 | | /// Called a function that is unknown to the host. |
4032 | | /// |
4033 | | /// > **Note**: Can only happen if `allow_unresolved_imports` was `true`. |
4034 | | #[display(fmt = "Called unresolved function `{module_name}`:`{function}`")] |
4035 | | UnresolvedFunctionCalled { |
4036 | | /// Name of the function that was unresolved. |
4037 | | function: String, |
4038 | | /// Name of module associated with the unresolved function. |
4039 | | module_name: String, |
4040 | | }, |
4041 | | /// Failed to decode a SCALE-encoded parameter. |
4042 | | ParamDecodeError, |
4043 | | /// One parameter is expected to point to a buffer, but the pointer is out |
4044 | | /// of range of the memory of the Wasm VM. |
4045 | | #[display( |
4046 | | fmt = "Bad pointer for parameter of index {param_num} of {function}: 0x{pointer:x}, \ |
4047 | | len = 0x{length:x}" |
4048 | | )] |
4049 | | ParamOutOfRange { |
4050 | | /// Name of the function being called where a type mismatch happens. |
4051 | | function: &'static str, |
4052 | | /// Index of the invalid parameter. The first parameter has index 0. |
4053 | | param_num: usize, |
4054 | | /// Pointer passed as parameter. |
4055 | | pointer: u32, |
4056 | | /// Expected length of the buffer. |
4057 | | /// |
4058 | | /// Depending on the function, this can either be an implicit length |
4059 | | /// or a length passed as parameter. |
4060 | | length: u32, |
4061 | | }, |
4062 | | /// One parameter is expected to point to a UTF-8 string, but the buffer |
4063 | | /// isn't valid UTF-8. |
4064 | | #[display(fmt = "UTF-8 error for parameter of index {param_num} of {function}: {error}")] |
4065 | | Utf8Error { |
4066 | | /// Name of the function being called where a type mismatch happens. |
4067 | | function: &'static str, |
4068 | | /// Index of the invalid parameter. The first parameter has index 0. |
4069 | | param_num: usize, |
4070 | | /// Decoding error that happened. |
4071 | | error: core::str::Utf8Error, |
4072 | | }, |
4073 | | /// Called `ext_storage_rollback_transaction_version_1` or |
4074 | | /// `ext_storage_commit_transaction_version_1` but no transaction was in progress. |
4075 | | #[display(fmt = "Attempted to end a transaction while none is in progress")] |
4076 | | NoActiveTransaction, |
4077 | | /// Execution has finished while a transaction started with |
4078 | | /// `ext_storage_start_transaction_version_1` was still in progress. |
4079 | | #[display(fmt = "Execution returned with a pending storage transaction")] |
4080 | | FinishedWithPendingTransaction, |
4081 | | /// Error when allocating memory for a return type. |
4082 | | #[display(fmt = "Out of memory allocating 0x{requested_size:x} bytes during {function}")] |
4083 | | OutOfMemory { |
4084 | | /// Name of the function being called. |
4085 | | function: &'static str, |
4086 | | /// Size of the requested allocation. |
4087 | | requested_size: u32, |
4088 | | }, |
4089 | | /// Called `ext_allocator_free_version_1` with an invalid pointer. |
4090 | | #[display(fmt = "Bad pointer passed to ext_allocator_free_version_1: 0x{pointer:x}")] |
4091 | | FreeError { |
4092 | | /// Pointer that was expected to be freed. |
4093 | | pointer: u32, |
4094 | | }, |
4095 | | /// Mismatch between the state trie version provided as parameter and the state trie version |
4096 | | /// found in the runtime specification. |
4097 | | #[display( |
4098 | | fmt = "Mismatch between the state trie version provided as parameter ({parameter:?}) and \ |
4099 | | the state trie version found in the runtime specification ({specification:?})." |
4100 | | )] |
4101 | | StateVersionMismatch { |
4102 | | /// The version passed as parameter. |
4103 | | parameter: TrieEntryVersion, |
4104 | | /// The version in the specification. |
4105 | | specification: TrieEntryVersion, |
4106 | | }, |
4107 | | /// Called `ext_default_child_storage_root_version_1` or |
4108 | | /// `ext_default_child_storage_root_version_2` on a child trie that doesn't exist. |
4109 | | #[display(fmt = "Called `ext_default_child_storage_root_version_1` or |
4110 | | `ext_default_child_storage_root_version_2` on a child trie that doesn't exist.")] |
4111 | | ChildStorageRootTrieDoesntExist, |
4112 | | /// Runtime has tried to perform a signature batch verification before initiating a batch |
4113 | | /// verification. |
4114 | | BatchVerifyWithoutStarting, |
4115 | | /// Runtime has tried to initiate a batch signatures verification while there was already one |
4116 | | /// in progress. |
4117 | | AlreadyBatchVerify, |
4118 | | /// Runtime has tried to finish a batch signatures verification while none is in progress. |
4119 | | NoBatchVerify, |
4120 | | /// The host function isn't implemented. |
4121 | | // TODO: this variant should eventually disappear as all functions are implemented |
4122 | | #[display(fmt = "Host function not implemented: {function}")] |
4123 | | HostFunctionNotImplemented { |
4124 | | /// Name of the function being called. |
4125 | | function: &'static str, |
4126 | | }, |
4127 | | } |
4128 | | |
4129 | | // Glue between the `allocator` module and the `vm` module. |
4130 | | // |
4131 | | // The allocator believes that there are `memory_total_pages` pages available and allocated, where |
4132 | | // `memory_total_pages` is equal to `heap_base + heap_pages`, while in reality, because we grow |
4133 | | // memory lazily, there might be fewer. |
4134 | | struct MemAccess<'a> { |
4135 | | vm: MemAccessVm<'a>, |
4136 | | memory_total_pages: HeapPages, |
4137 | | } |
4138 | | |
4139 | | enum MemAccessVm<'a> { |
4140 | | Prepare(&'a mut vm::Prepare), |
4141 | | Running(&'a mut vm::VirtualMachine), |
4142 | | } |
4143 | | |
4144 | | impl<'a> allocator::Memory for MemAccess<'a> { |
4145 | 30.0k | fn read_le_u64(&self, ptr: u32) -> Result<u64, allocator::Error> { |
4146 | 30.0k | if (ptr + 8) > u32::from(self.memory_total_pages) * 64 * 1024 { |
4147 | 0 | return Err(allocator::Error::Other("out of bounds access")); |
4148 | 30.0k | } |
4149 | 30.0k | |
4150 | 30.0k | // Note that this function (`read_le_u64`) really should take ̀`&mut self` but that is |
4151 | 30.0k | // unfortunately not the case, meaning that we can't "just" grow the memory if trying |
4152 | 30.0k | // to access an out of bound location. |
4153 | 30.0k | // |
4154 | 30.0k | // Additionally, the value being read can in theory overlap between an allocated and |
4155 | 30.0k | // non-allocated parts of the memory, making this more complicated. |
4156 | 30.0k | |
4157 | 30.0k | // Offset of the memory page where the first byte of the value will be read. |
4158 | 30.0k | let accessed_memory_page_start = HeapPages::new(ptr / (64 * 1024)); |
4159 | 30.0k | // Offset of the memory page where the last byte of the value will be read. |
4160 | 30.0k | let accessed_memory_page_end = HeapPages::new((ptr + 7) / (64 * 1024)); |
4161 | | // Number of pages currently allocated. |
4162 | 30.0k | let current_num_pages = match self.vm { |
4163 | 0 | MemAccessVm::Prepare(ref vm) => vm.memory_size(), |
4164 | 30.0k | MemAccessVm::Running(ref vm) => vm.memory_size(), |
4165 | | }; |
4166 | 30.0k | debug_assert!(current_num_pages <= self.memory_total_pages); |
4167 | | |
4168 | 30.0k | if accessed_memory_page_end < current_num_pages { |
4169 | | // This is the simple case: the memory access is in bounds. |
4170 | 30.0k | match self.vm { |
4171 | 0 | MemAccessVm::Prepare(ref vm) => { |
4172 | 0 | let bytes = vm.read_memory(ptr, 8).unwrap_or_else(|_| unreachable!()); Unexecuted instantiation: _RNCNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u640Bb_ Unexecuted instantiation: _RNCNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u640Bb_ |
4173 | 0 | Ok(u64::from_le_bytes( |
4174 | 0 | <[u8; 8]>::try_from(bytes.as_ref()).unwrap_or_else(|_| unreachable!()), Unexecuted instantiation: _RNCNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u64s_0Bb_ Unexecuted instantiation: _RNCNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u64s_0Bb_ |
4175 | 0 | )) |
4176 | | } |
4177 | 30.0k | MemAccessVm::Running(ref vm) => { |
4178 | 30.0k | let bytes = vm.read_memory(ptr, 8).unwrap_or_else(|_| unreachable!()0 ); Unexecuted instantiation: _RNCNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u64s0_0Bb_ Unexecuted instantiation: _RNCNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u64s0_0Bb_ |
4179 | 30.0k | Ok(u64::from_le_bytes( |
4180 | 30.0k | <[u8; 8]>::try_from(bytes.as_ref()).unwrap_or_else(|_| unreachable!()0 ), Unexecuted instantiation: _RNCNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u64s1_0Bb_ Unexecuted instantiation: _RNCNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u64s1_0Bb_ |
4181 | 30.0k | )) |
4182 | | } |
4183 | | } |
4184 | 0 | } else if accessed_memory_page_start < current_num_pages { |
4185 | | // Memory access is partially in bounds. This is the most complicated situation. |
4186 | 0 | match self.vm { |
4187 | 0 | MemAccessVm::Prepare(ref vm) => { |
4188 | 0 | let partial_bytes = vm |
4189 | 0 | .read_memory(ptr, u32::from(current_num_pages) * 64 * 1024 - ptr) |
4190 | 0 | .unwrap_or_else(|_| unreachable!()); Unexecuted instantiation: _RNCNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u64s2_0Bb_ Unexecuted instantiation: _RNCNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u64s2_0Bb_ |
4191 | 0 | let partial_bytes = partial_bytes.as_ref(); |
4192 | 0 | debug_assert!(partial_bytes.len() < 8); |
4193 | | |
4194 | 0 | let mut out = [0; 8]; |
4195 | 0 | out[..partial_bytes.len()].copy_from_slice(partial_bytes); |
4196 | 0 | Ok(u64::from_le_bytes(out)) |
4197 | | } |
4198 | 0 | MemAccessVm::Running(ref vm) => { |
4199 | 0 | let partial_bytes = vm |
4200 | 0 | .read_memory(ptr, u32::from(current_num_pages) * 64 * 1024 - ptr) |
4201 | 0 | .unwrap_or_else(|_| unreachable!()); Unexecuted instantiation: _RNCNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u64s3_0Bb_ Unexecuted instantiation: _RNCNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory11read_le_u64s3_0Bb_ |
4202 | 0 | let partial_bytes = partial_bytes.as_ref(); |
4203 | 0 | debug_assert!(partial_bytes.len() < 8); |
4204 | | |
4205 | 0 | let mut out = [0; 8]; |
4206 | 0 | out[..partial_bytes.len()].copy_from_slice(partial_bytes); |
4207 | 0 | Ok(u64::from_le_bytes(out)) |
4208 | | } |
4209 | | } |
4210 | | } else { |
4211 | | // Everything out bounds. Memory is zero. |
4212 | 0 | Ok(0) |
4213 | | } |
4214 | 30.0k | } _RNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_9MemAccessNtNtB7_9allocator6Memory11read_le_u64 Line | Count | Source | 4145 | 27.0k | fn read_le_u64(&self, ptr: u32) -> Result<u64, allocator::Error> { | 4146 | 27.0k | if (ptr + 8) > u32::from(self.memory_total_pages) * 64 * 1024 { | 4147 | 0 | return Err(allocator::Error::Other("out of bounds access")); | 4148 | 27.0k | } | 4149 | 27.0k | | 4150 | 27.0k | // Note that this function (`read_le_u64`) really should take ̀`&mut self` but that is | 4151 | 27.0k | // unfortunately not the case, meaning that we can't "just" grow the memory if trying | 4152 | 27.0k | // to access an out of bound location. | 4153 | 27.0k | // | 4154 | 27.0k | // Additionally, the value being read can in theory overlap between an allocated and | 4155 | 27.0k | // non-allocated parts of the memory, making this more complicated. | 4156 | 27.0k | | 4157 | 27.0k | // Offset of the memory page where the first byte of the value will be read. | 4158 | 27.0k | let accessed_memory_page_start = HeapPages::new(ptr / (64 * 1024)); | 4159 | 27.0k | // Offset of the memory page where the last byte of the value will be read. | 4160 | 27.0k | let accessed_memory_page_end = HeapPages::new((ptr + 7) / (64 * 1024)); | 4161 | | // Number of pages currently allocated. | 4162 | 27.0k | let current_num_pages = match self.vm { | 4163 | 0 | MemAccessVm::Prepare(ref vm) => vm.memory_size(), | 4164 | 27.0k | MemAccessVm::Running(ref vm) => vm.memory_size(), | 4165 | | }; | 4166 | 27.0k | debug_assert!(current_num_pages <= self.memory_total_pages); | 4167 | | | 4168 | 27.0k | if accessed_memory_page_end < current_num_pages { | 4169 | | // This is the simple case: the memory access is in bounds. | 4170 | 27.0k | match self.vm { | 4171 | 0 | MemAccessVm::Prepare(ref vm) => { | 4172 | 0 | let bytes = vm.read_memory(ptr, 8).unwrap_or_else(|_| unreachable!()); | 4173 | 0 | Ok(u64::from_le_bytes( | 4174 | 0 | <[u8; 8]>::try_from(bytes.as_ref()).unwrap_or_else(|_| unreachable!()), | 4175 | 0 | )) | 4176 | | } | 4177 | 27.0k | MemAccessVm::Running(ref vm) => { | 4178 | 27.0k | let bytes = vm.read_memory(ptr, 8).unwrap_or_else(|_| unreachable!()); | 4179 | 27.0k | Ok(u64::from_le_bytes( | 4180 | 27.0k | <[u8; 8]>::try_from(bytes.as_ref()).unwrap_or_else(|_| unreachable!()), | 4181 | 27.0k | )) | 4182 | | } | 4183 | | } | 4184 | 0 | } else if accessed_memory_page_start < current_num_pages { | 4185 | | // Memory access is partially in bounds. This is the most complicated situation. | 4186 | 0 | match self.vm { | 4187 | 0 | MemAccessVm::Prepare(ref vm) => { | 4188 | 0 | let partial_bytes = vm | 4189 | 0 | .read_memory(ptr, u32::from(current_num_pages) * 64 * 1024 - ptr) | 4190 | 0 | .unwrap_or_else(|_| unreachable!()); | 4191 | 0 | let partial_bytes = partial_bytes.as_ref(); | 4192 | 0 | debug_assert!(partial_bytes.len() < 8); | 4193 | | | 4194 | 0 | let mut out = [0; 8]; | 4195 | 0 | out[..partial_bytes.len()].copy_from_slice(partial_bytes); | 4196 | 0 | Ok(u64::from_le_bytes(out)) | 4197 | | } | 4198 | 0 | MemAccessVm::Running(ref vm) => { | 4199 | 0 | let partial_bytes = vm | 4200 | 0 | .read_memory(ptr, u32::from(current_num_pages) * 64 * 1024 - ptr) | 4201 | 0 | .unwrap_or_else(|_| unreachable!()); | 4202 | 0 | let partial_bytes = partial_bytes.as_ref(); | 4203 | 0 | debug_assert!(partial_bytes.len() < 8); | 4204 | | | 4205 | 0 | let mut out = [0; 8]; | 4206 | 0 | out[..partial_bytes.len()].copy_from_slice(partial_bytes); | 4207 | 0 | Ok(u64::from_le_bytes(out)) | 4208 | | } | 4209 | | } | 4210 | | } else { | 4211 | | // Everything out bounds. Memory is zero. | 4212 | 0 | Ok(0) | 4213 | | } | 4214 | 27.0k | } |
_RNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_9MemAccessNtNtB7_9allocator6Memory11read_le_u64 Line | Count | Source | 4145 | 2.94k | fn read_le_u64(&self, ptr: u32) -> Result<u64, allocator::Error> { | 4146 | 2.94k | if (ptr + 8) > u32::from(self.memory_total_pages) * 64 * 1024 { | 4147 | 0 | return Err(allocator::Error::Other("out of bounds access")); | 4148 | 2.94k | } | 4149 | 2.94k | | 4150 | 2.94k | // Note that this function (`read_le_u64`) really should take ̀`&mut self` but that is | 4151 | 2.94k | // unfortunately not the case, meaning that we can't "just" grow the memory if trying | 4152 | 2.94k | // to access an out of bound location. | 4153 | 2.94k | // | 4154 | 2.94k | // Additionally, the value being read can in theory overlap between an allocated and | 4155 | 2.94k | // non-allocated parts of the memory, making this more complicated. | 4156 | 2.94k | | 4157 | 2.94k | // Offset of the memory page where the first byte of the value will be read. | 4158 | 2.94k | let accessed_memory_page_start = HeapPages::new(ptr / (64 * 1024)); | 4159 | 2.94k | // Offset of the memory page where the last byte of the value will be read. | 4160 | 2.94k | let accessed_memory_page_end = HeapPages::new((ptr + 7) / (64 * 1024)); | 4161 | | // Number of pages currently allocated. | 4162 | 2.94k | let current_num_pages = match self.vm { | 4163 | 0 | MemAccessVm::Prepare(ref vm) => vm.memory_size(), | 4164 | 2.94k | MemAccessVm::Running(ref vm) => vm.memory_size(), | 4165 | | }; | 4166 | 2.94k | debug_assert!(current_num_pages <= self.memory_total_pages); | 4167 | | | 4168 | 2.94k | if accessed_memory_page_end < current_num_pages { | 4169 | | // This is the simple case: the memory access is in bounds. | 4170 | 2.94k | match self.vm { | 4171 | 0 | MemAccessVm::Prepare(ref vm) => { | 4172 | 0 | let bytes = vm.read_memory(ptr, 8).unwrap_or_else(|_| unreachable!()); | 4173 | 0 | Ok(u64::from_le_bytes( | 4174 | 0 | <[u8; 8]>::try_from(bytes.as_ref()).unwrap_or_else(|_| unreachable!()), | 4175 | 0 | )) | 4176 | | } | 4177 | 2.94k | MemAccessVm::Running(ref vm) => { | 4178 | 2.94k | let bytes = vm.read_memory(ptr, 8).unwrap_or_else(|_| unreachable!()); | 4179 | 2.94k | Ok(u64::from_le_bytes( | 4180 | 2.94k | <[u8; 8]>::try_from(bytes.as_ref()).unwrap_or_else(|_| unreachable!()), | 4181 | 2.94k | )) | 4182 | | } | 4183 | | } | 4184 | 0 | } else if accessed_memory_page_start < current_num_pages { | 4185 | | // Memory access is partially in bounds. This is the most complicated situation. | 4186 | 0 | match self.vm { | 4187 | 0 | MemAccessVm::Prepare(ref vm) => { | 4188 | 0 | let partial_bytes = vm | 4189 | 0 | .read_memory(ptr, u32::from(current_num_pages) * 64 * 1024 - ptr) | 4190 | 0 | .unwrap_or_else(|_| unreachable!()); | 4191 | 0 | let partial_bytes = partial_bytes.as_ref(); | 4192 | 0 | debug_assert!(partial_bytes.len() < 8); | 4193 | | | 4194 | 0 | let mut out = [0; 8]; | 4195 | 0 | out[..partial_bytes.len()].copy_from_slice(partial_bytes); | 4196 | 0 | Ok(u64::from_le_bytes(out)) | 4197 | | } | 4198 | 0 | MemAccessVm::Running(ref vm) => { | 4199 | 0 | let partial_bytes = vm | 4200 | 0 | .read_memory(ptr, u32::from(current_num_pages) * 64 * 1024 - ptr) | 4201 | 0 | .unwrap_or_else(|_| unreachable!()); | 4202 | 0 | let partial_bytes = partial_bytes.as_ref(); | 4203 | 0 | debug_assert!(partial_bytes.len() < 8); | 4204 | | | 4205 | 0 | let mut out = [0; 8]; | 4206 | 0 | out[..partial_bytes.len()].copy_from_slice(partial_bytes); | 4207 | 0 | Ok(u64::from_le_bytes(out)) | 4208 | | } | 4209 | | } | 4210 | | } else { | 4211 | | // Everything out bounds. Memory is zero. | 4212 | 0 | Ok(0) | 4213 | | } | 4214 | 2.94k | } |
|
4215 | | |
4216 | 33.8k | fn write_le_u64(&mut self, ptr: u32, val: u64) -> Result<(), allocator::Error> { |
4217 | 33.8k | if (ptr + 8) > u32::from(self.memory_total_pages) * 64 * 1024 { |
4218 | 0 | return Err(allocator::Error::Other("out of bounds access")); |
4219 | 33.8k | } |
4220 | 33.8k | |
4221 | 33.8k | let bytes = val.to_le_bytes(); |
4222 | 33.8k | |
4223 | 33.8k | // Offset of the memory page where the last byte of the value will be written. |
4224 | 33.8k | let written_memory_page = HeapPages::new((ptr + 7) / (64 * 1024)); |
4225 | | |
4226 | | // Grow the memory more if necessary. |
4227 | | // Please note the `<=`. For example if we write to page 0, we want to have at least 1 page |
4228 | | // allocated. |
4229 | 33.8k | let current_num_pages = match self.vm { |
4230 | 179 | MemAccessVm::Prepare(ref vm) => vm.memory_size(), |
4231 | 33.6k | MemAccessVm::Running(ref vm) => vm.memory_size(), |
4232 | | }; |
4233 | 33.8k | debug_assert!(current_num_pages <= self.memory_total_pages); |
4234 | 33.8k | if current_num_pages <= written_memory_page { |
4235 | | // For now, we grow the memory just enough to fit. |
4236 | | // TODO: do better |
4237 | | // Note the order of operations: we add 1 at the end to avoid a potential overflow |
4238 | | // in case `written_memory_page` is the maximum possible value. |
4239 | 19 | let to_grow = written_memory_page - current_num_pages + HeapPages::new(1); |
4240 | 19 | |
4241 | 19 | // We check at initialization that the virtual machine is capable of growing up to |
4242 | 19 | // `memory_total_pages`, meaning that this can't panic. |
4243 | 19 | match self.vm { |
4244 | 14 | MemAccessVm::Prepare(ref mut vm) => { |
4245 | 14 | vm.grow_memory(to_grow).unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory12write_le_u640Bb_ Unexecuted instantiation: _RNCNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory12write_le_u640Bb_ |
4246 | | } |
4247 | 5 | MemAccessVm::Running(ref mut vm) => { |
4248 | 5 | vm.grow_memory(to_grow).unwrap_or_else(|_| unreachable!()0 ) Unexecuted instantiation: _RNCNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory12write_le_u64s_0Bb_ Unexecuted instantiation: _RNCNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory12write_le_u64s_0Bb_ |
4249 | | } |
4250 | | } |
4251 | 33.7k | } |
4252 | | |
4253 | 33.8k | match self.vm { |
4254 | 179 | MemAccessVm::Prepare(ref mut vm) => vm |
4255 | 179 | .write_memory(ptr, &bytes) |
4256 | 179 | .unwrap_or_else(|_| unreachable!()0 ), Unexecuted instantiation: _RNCNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory12write_le_u64s0_0Bb_ Unexecuted instantiation: _RNCNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory12write_le_u64s0_0Bb_ |
4257 | 33.6k | MemAccessVm::Running(ref mut vm) => vm |
4258 | 33.6k | .write_memory(ptr, &bytes) |
4259 | 33.6k | .unwrap_or_else(|_| unreachable!()0 ), Unexecuted instantiation: _RNCNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory12write_le_u64s1_0Bb_ Unexecuted instantiation: _RNCNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB7_9MemAccessNtNtB9_9allocator6Memory12write_le_u64s1_0Bb_ |
4260 | | } |
4261 | 33.8k | Ok(()) |
4262 | 33.8k | } _RNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_9MemAccessNtNtB7_9allocator6Memory12write_le_u64 Line | Count | Source | 4216 | 28.7k | fn write_le_u64(&mut self, ptr: u32, val: u64) -> Result<(), allocator::Error> { | 4217 | 28.7k | if (ptr + 8) > u32::from(self.memory_total_pages) * 64 * 1024 { | 4218 | 0 | return Err(allocator::Error::Other("out of bounds access")); | 4219 | 28.7k | } | 4220 | 28.7k | | 4221 | 28.7k | let bytes = val.to_le_bytes(); | 4222 | 28.7k | | 4223 | 28.7k | // Offset of the memory page where the last byte of the value will be written. | 4224 | 28.7k | let written_memory_page = HeapPages::new((ptr + 7) / (64 * 1024)); | 4225 | | | 4226 | | // Grow the memory more if necessary. | 4227 | | // Please note the `<=`. For example if we write to page 0, we want to have at least 1 page | 4228 | | // allocated. | 4229 | 28.7k | let current_num_pages = match self.vm { | 4230 | 52 | MemAccessVm::Prepare(ref vm) => vm.memory_size(), | 4231 | 28.6k | MemAccessVm::Running(ref vm) => vm.memory_size(), | 4232 | | }; | 4233 | 28.7k | debug_assert!(current_num_pages <= self.memory_total_pages); | 4234 | 28.7k | if current_num_pages <= written_memory_page { | 4235 | | // For now, we grow the memory just enough to fit. | 4236 | | // TODO: do better | 4237 | | // Note the order of operations: we add 1 at the end to avoid a potential overflow | 4238 | | // in case `written_memory_page` is the maximum possible value. | 4239 | 18 | let to_grow = written_memory_page - current_num_pages + HeapPages::new(1); | 4240 | 18 | | 4241 | 18 | // We check at initialization that the virtual machine is capable of growing up to | 4242 | 18 | // `memory_total_pages`, meaning that this can't panic. | 4243 | 18 | match self.vm { | 4244 | 14 | MemAccessVm::Prepare(ref mut vm) => { | 4245 | 14 | vm.grow_memory(to_grow).unwrap_or_else(|_| unreachable!()) | 4246 | | } | 4247 | 4 | MemAccessVm::Running(ref mut vm) => { | 4248 | 4 | vm.grow_memory(to_grow).unwrap_or_else(|_| unreachable!()) | 4249 | | } | 4250 | | } | 4251 | 28.7k | } | 4252 | | | 4253 | 28.7k | match self.vm { | 4254 | 52 | MemAccessVm::Prepare(ref mut vm) => vm | 4255 | 52 | .write_memory(ptr, &bytes) | 4256 | 52 | .unwrap_or_else(|_| unreachable!()), | 4257 | 28.6k | MemAccessVm::Running(ref mut vm) => vm | 4258 | 28.6k | .write_memory(ptr, &bytes) | 4259 | 28.6k | .unwrap_or_else(|_| unreachable!()), | 4260 | | } | 4261 | 28.7k | Ok(()) | 4262 | 28.7k | } |
_RNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_9MemAccessNtNtB7_9allocator6Memory12write_le_u64 Line | Count | Source | 4216 | 5.07k | fn write_le_u64(&mut self, ptr: u32, val: u64) -> Result<(), allocator::Error> { | 4217 | 5.07k | if (ptr + 8) > u32::from(self.memory_total_pages) * 64 * 1024 { | 4218 | 0 | return Err(allocator::Error::Other("out of bounds access")); | 4219 | 5.07k | } | 4220 | 5.07k | | 4221 | 5.07k | let bytes = val.to_le_bytes(); | 4222 | 5.07k | | 4223 | 5.07k | // Offset of the memory page where the last byte of the value will be written. | 4224 | 5.07k | let written_memory_page = HeapPages::new((ptr + 7) / (64 * 1024)); | 4225 | | | 4226 | | // Grow the memory more if necessary. | 4227 | | // Please note the `<=`. For example if we write to page 0, we want to have at least 1 page | 4228 | | // allocated. | 4229 | 5.07k | let current_num_pages = match self.vm { | 4230 | 127 | MemAccessVm::Prepare(ref vm) => vm.memory_size(), | 4231 | 4.94k | MemAccessVm::Running(ref vm) => vm.memory_size(), | 4232 | | }; | 4233 | 5.07k | debug_assert!(current_num_pages <= self.memory_total_pages); | 4234 | 5.07k | if current_num_pages <= written_memory_page { | 4235 | | // For now, we grow the memory just enough to fit. | 4236 | | // TODO: do better | 4237 | | // Note the order of operations: we add 1 at the end to avoid a potential overflow | 4238 | | // in case `written_memory_page` is the maximum possible value. | 4239 | 1 | let to_grow = written_memory_page - current_num_pages + HeapPages::new(1); | 4240 | 1 | | 4241 | 1 | // We check at initialization that the virtual machine is capable of growing up to | 4242 | 1 | // `memory_total_pages`, meaning that this can't panic. | 4243 | 1 | match self.vm { | 4244 | 0 | MemAccessVm::Prepare(ref mut vm) => { | 4245 | 0 | vm.grow_memory(to_grow).unwrap_or_else(|_| unreachable!()) | 4246 | | } | 4247 | 1 | MemAccessVm::Running(ref mut vm) => { | 4248 | 1 | vm.grow_memory(to_grow).unwrap_or_else(|_| unreachable!()) | 4249 | | } | 4250 | | } | 4251 | 5.07k | } | 4252 | | | 4253 | 5.07k | match self.vm { | 4254 | 127 | MemAccessVm::Prepare(ref mut vm) => vm | 4255 | 127 | .write_memory(ptr, &bytes) | 4256 | 127 | .unwrap_or_else(|_| unreachable!()), | 4257 | 4.94k | MemAccessVm::Running(ref mut vm) => vm | 4258 | 4.94k | .write_memory(ptr, &bytes) | 4259 | 4.94k | .unwrap_or_else(|_| unreachable!()), | 4260 | | } | 4261 | 5.07k | Ok(()) | 4262 | 5.07k | } |
|
4263 | | |
4264 | 84.6k | fn size(&self) -> u32 { |
4265 | 84.6k | // Lie to the allocator to pretend that `memory_total_pages` are available. |
4266 | 84.6k | u32::from(self.memory_total_pages) |
4267 | 84.6k | .saturating_mul(64) |
4268 | 84.6k | .saturating_mul(1024) |
4269 | 84.6k | } _RNvXsN_NtNtCsN16ciHI6Qf_7smoldot8executor4hostNtB5_9MemAccessNtNtB7_9allocator6Memory4size Line | Count | Source | 4264 | 71.8k | fn size(&self) -> u32 { | 4265 | 71.8k | // Lie to the allocator to pretend that `memory_total_pages` are available. | 4266 | 71.8k | u32::from(self.memory_total_pages) | 4267 | 71.8k | .saturating_mul(64) | 4268 | 71.8k | .saturating_mul(1024) | 4269 | 71.8k | } |
_RNvXsN_NtNtCseuYC0Zibziv_7smoldot8executor4hostNtB5_9MemAccessNtNtB7_9allocator6Memory4size Line | Count | Source | 4264 | 12.8k | fn size(&self) -> u32 { | 4265 | 12.8k | // Lie to the allocator to pretend that `memory_total_pages` are available. | 4266 | 12.8k | u32::from(self.memory_total_pages) | 4267 | 12.8k | .saturating_mul(64) | 4268 | 12.8k | .saturating_mul(1024) | 4269 | 12.8k | } |
|
4270 | | } |