mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 03:01:07 +00:00
Rewrap all comments to 100 line width (#9490)
* reformat everything again * manual formatting * last manual fix * Fix build
This commit is contained in:
@@ -26,27 +26,28 @@
|
||||
//!
|
||||
//! To give you some examples:
|
||||
//!
|
||||
//! - wasmi allows reaching to non-exported mutable globals so that we could reset them.
|
||||
//! Wasmtime doesn’t support that.
|
||||
//! - wasmi allows reaching to non-exported mutable globals so that we could reset them. Wasmtime
|
||||
//! doesn’t support that.
|
||||
//!
|
||||
//! We need to reset the globals because when we
|
||||
//! execute the Substrate Runtime, we do not drop and create the instance anew, instead
|
||||
//! we restore some selected parts of the state.
|
||||
//!
|
||||
//! - stack depth metering can be performed via instrumentation or deferred to the engine and say
|
||||
//! be added directly in machine code. Implementing this in machine code is rather cumbersome so
|
||||
//! - stack depth metering can be performed via instrumentation or deferred to the engine and say be
|
||||
//! added directly in machine code. Implementing this in machine code is rather cumbersome so
|
||||
//! instrumentation looks like a good solution.
|
||||
//!
|
||||
//! Stack depth metering is needed to make a wasm blob
|
||||
//! execution deterministic, which in turn is needed by the Parachain Validation Function in Polkadot.
|
||||
//! execution deterministic, which in turn is needed by the Parachain Validation Function in
|
||||
//! Polkadot.
|
||||
//!
|
||||
//! ## Inspection
|
||||
//!
|
||||
//! Inspection of a wasm module may be needed to extract some useful information, such as to extract
|
||||
//! data segment snapshot, which is helpful for quickly restoring the initial state of instances.
|
||||
//! Inspection can be also useful to prove that a wasm module possesses some properties, such as,
|
||||
//! is free of any floating point operations, which is a useful step towards making instances produced
|
||||
//! from such a module deterministic.
|
||||
//! is free of any floating point operations, which is a useful step towards making instances
|
||||
//! produced from such a module deterministic.
|
||||
|
||||
mod data_segments_snapshot;
|
||||
mod globals_snapshot;
|
||||
|
||||
@@ -72,11 +72,13 @@ impl RuntimeBlob {
|
||||
export_mutable_globals(&mut self.raw_module, "exported_internal_global");
|
||||
}
|
||||
|
||||
/// Run a pass that instrument this module so as to introduce a deterministic stack height limit.
|
||||
/// Run a pass that instrument this module so as to introduce a deterministic stack height
|
||||
/// limit.
|
||||
///
|
||||
/// It will introduce a global mutable counter. The instrumentation will increase the counter
|
||||
/// according to the "cost" of the callee. If the cost exceeds the `stack_depth_limit` constant,
|
||||
/// the instrumentation will trap. The counter will be decreased as soon as the the callee returns.
|
||||
/// the instrumentation will trap. The counter will be decreased as soon as the the callee
|
||||
/// returns.
|
||||
///
|
||||
/// The stack cost of a function is computed based on how much locals there are and the maximum
|
||||
/// depth of the wasm operand stack.
|
||||
@@ -89,7 +91,8 @@ impl RuntimeBlob {
|
||||
Ok(Self { raw_module: injected_module })
|
||||
}
|
||||
|
||||
/// Perform an instrumentation that makes sure that a specific function `entry_point` is exported
|
||||
/// Perform an instrumentation that makes sure that a specific function `entry_point` is
|
||||
/// exported
|
||||
pub fn entry_point_exists(&self, entry_point: &str) -> bool {
|
||||
self.raw_module
|
||||
.export_section()
|
||||
|
||||
@@ -98,7 +98,8 @@ pub trait WasmInstance: Send {
|
||||
///
|
||||
/// This is meant to be the starting address of the memory mapped area for the linear memory.
|
||||
///
|
||||
/// This function is intended only for a specific test that measures physical memory consumption.
|
||||
/// This function is intended only for a specific test that measures physical memory
|
||||
/// consumption.
|
||||
fn linear_memory_base_ptr(&self) -> Option<*const u8> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -197,8 +197,8 @@ impl WasmExecutor {
|
||||
/// The runtime is passed as a [`RuntimeBlob`]. The runtime will be isntantiated with the
|
||||
/// parameters this `WasmExecutor` was initialized with.
|
||||
///
|
||||
/// In case of problems with during creation of the runtime or instantation, a `Err` is returned.
|
||||
/// that describes the message.
|
||||
/// In case of problems with during creation of the runtime or instantation, a `Err` is
|
||||
/// returned. that describes the message.
|
||||
#[doc(hidden)] // We use this function for tests across multiple crates.
|
||||
pub fn uncached_call(
|
||||
&self,
|
||||
@@ -456,8 +456,8 @@ impl RuntimeSpawn for RuntimeInstanceSpawn {
|
||||
let _ = sender.send(output);
|
||||
},
|
||||
Err(error) => {
|
||||
// If execution is panicked, the `join` in the original runtime code will panic as well,
|
||||
// since the sender is dropped without sending anything.
|
||||
// If execution is panicked, the `join` in the original runtime code will
|
||||
// panic as well, since the sender is dropped without sending anything.
|
||||
log::error!("Call error in spawned task: {:?}", error);
|
||||
},
|
||||
}
|
||||
|
||||
@@ -304,8 +304,8 @@ pub fn create_wasm_runtime_with_code(
|
||||
WasmExecutionMethod::Interpreted => {
|
||||
// Wasmi doesn't have any need in a cache directory.
|
||||
//
|
||||
// We drop the cache_path here to silence warnings that cache_path is not used if compiling
|
||||
// without the `wasmtime` flag.
|
||||
// We drop the cache_path here to silence warnings that cache_path is not used if
|
||||
// compiling without the `wasmtime` flag.
|
||||
drop(cache_path);
|
||||
|
||||
sc_executor_wasmi::create_runtime(
|
||||
@@ -361,8 +361,8 @@ fn decode_runtime_apis(apis: &[u8]) -> Result<Vec<([u8; 8], u32)>, WasmError> {
|
||||
|
||||
apis.chunks(RUNTIME_API_INFO_SIZE)
|
||||
.map(|chunk| {
|
||||
// `chunk` can be less than `RUNTIME_API_INFO_SIZE` if the total length of `apis` doesn't
|
||||
// completely divide by `RUNTIME_API_INFO_SIZE`.
|
||||
// `chunk` can be less than `RUNTIME_API_INFO_SIZE` if the total length of `apis`
|
||||
// doesn't completely divide by `RUNTIME_API_INFO_SIZE`.
|
||||
<[u8; RUNTIME_API_INFO_SIZE]>::try_from(chunk)
|
||||
.map(sp_api::deserialize_runtime_api_info)
|
||||
.map_err(|_| WasmError::Other("a clipped runtime api info declaration".to_owned()))
|
||||
@@ -370,8 +370,8 @@ fn decode_runtime_apis(apis: &[u8]) -> Result<Vec<([u8; 8], u32)>, WasmError> {
|
||||
.collect::<Result<Vec<_>, WasmError>>()
|
||||
}
|
||||
|
||||
/// Take the runtime blob and scan it for the custom wasm sections containing the version information
|
||||
/// and construct the `RuntimeVersion` from them.
|
||||
/// Take the runtime blob and scan it for the custom wasm sections containing the version
|
||||
/// information and construct the `RuntimeVersion` from them.
|
||||
///
|
||||
/// If there are no such sections, it returns `None`. If there is an error during decoding those
|
||||
/// sections, `Err` will be returned.
|
||||
@@ -380,8 +380,8 @@ pub fn read_embedded_version(blob: &RuntimeBlob) -> Result<Option<RuntimeVersion
|
||||
// We do not use `decode_version` here because the runtime_version section is not supposed
|
||||
// to ever contain a legacy version. Apart from that `decode_version` relies on presence
|
||||
// of a special API in the `apis` field to treat the input as a non-legacy version. However
|
||||
// the structure found in the `runtime_version` always contain an empty `apis` field. Therefore
|
||||
// the version read will be mistakenly treated as an legacy one.
|
||||
// the structure found in the `runtime_version` always contain an empty `apis` field.
|
||||
// Therefore the version read will be mistakenly treated as an legacy one.
|
||||
let mut decoded_version = sp_api::RuntimeVersion::decode(&mut version_section)
|
||||
.map_err(|_| WasmError::Instantiation("failed to decode version section".into()))?;
|
||||
|
||||
@@ -411,8 +411,9 @@ fn create_versioned_wasm_runtime(
|
||||
// the uncompressed code from now on.
|
||||
let blob = sc_executor_common::runtime_blob::RuntimeBlob::uncompress_if_needed(&code)?;
|
||||
|
||||
// Use the runtime blob to scan if there is any metadata embedded into the wasm binary pertaining
|
||||
// to runtime version. We do it before consuming the runtime blob for creating the runtime.
|
||||
// Use the runtime blob to scan if there is any metadata embedded into the wasm binary
|
||||
// pertaining to runtime version. We do it before consuming the runtime blob for creating the
|
||||
// runtime.
|
||||
let mut version: Option<_> = read_embedded_version(&blob)?;
|
||||
|
||||
let runtime = create_wasm_runtime_with_code(
|
||||
@@ -429,7 +430,8 @@ fn create_versioned_wasm_runtime(
|
||||
if version.is_none() {
|
||||
// Call to determine runtime version.
|
||||
let version_result = {
|
||||
// `ext` is already implicitly handled as unwind safe, as we store it in a global variable.
|
||||
// `ext` is already implicitly handled as unwind safe, as we store it in a global
|
||||
// variable.
|
||||
let mut ext = AssertUnwindSafe(ext);
|
||||
|
||||
// The following unwind safety assertion is OK because if the method call panics, the
|
||||
|
||||
@@ -687,7 +687,8 @@ pub struct WasmiInstance {
|
||||
missing_functions: Vec<String>,
|
||||
}
|
||||
|
||||
// This is safe because `WasmiInstance` does not leak any references to `self.memory` and `self.instance`
|
||||
// This is safe because `WasmiInstance` does not leak any references to `self.memory` and
|
||||
// `self.instance`
|
||||
unsafe impl Send for WasmiInstance {}
|
||||
|
||||
impl WasmInstance for WasmiInstance {
|
||||
|
||||
@@ -98,8 +98,8 @@ pub struct InstanceWrapper {
|
||||
instance: Instance,
|
||||
// The memory instance of the `instance`.
|
||||
//
|
||||
// It is important to make sure that we don't make any copies of this to make it easier to proof
|
||||
// See `memory_as_slice` and `memory_as_slice_mut`.
|
||||
// It is important to make sure that we don't make any copies of this to make it easier to
|
||||
// proof See `memory_as_slice` and `memory_as_slice_mut`.
|
||||
memory: Memory,
|
||||
table: Option<Table>,
|
||||
// Make this struct explicitly !Send & !Sync.
|
||||
@@ -399,9 +399,9 @@ impl InstanceWrapper {
|
||||
self.memory.data_ptr()
|
||||
}
|
||||
|
||||
/// Removes physical backing from the allocated linear memory. This leads to returning the memory
|
||||
/// back to the system. While the memory is zeroed this is considered as a side-effect and is not
|
||||
/// relied upon. Thus this function acts as a hint.
|
||||
/// Removes physical backing from the allocated linear memory. This leads to returning the
|
||||
/// memory back to the system. While the memory is zeroed this is considered as a side-effect
|
||||
/// and is not relied upon. Thus this function acts as a hint.
|
||||
pub fn decommit(&self) {
|
||||
if self.memory.data_size() == 0 {
|
||||
return
|
||||
|
||||
@@ -100,8 +100,8 @@ impl WasmModule for WasmtimeRuntime {
|
||||
// and results.
|
||||
//
|
||||
// NOTE: Attentive reader may notice that this could've been moved in `WasmModule` creation.
|
||||
// However, I am not sure if that's a good idea since it would be pushing our luck further
|
||||
// by assuming that `Store` not only `Send` but also `Sync`.
|
||||
// However, I am not sure if that's a good idea since it would be pushing our luck
|
||||
// further by assuming that `Store` not only `Send` but also `Sync`.
|
||||
let imports = resolve_imports(
|
||||
&store,
|
||||
&self.module,
|
||||
@@ -115,10 +115,10 @@ impl WasmModule for WasmtimeRuntime {
|
||||
InstanceWrapper::new(&store, &self.module, &imports, self.config.heap_pages)?;
|
||||
let heap_base = instance_wrapper.extract_heap_base()?;
|
||||
|
||||
// This function panics if the instance was created from a runtime blob different from which
|
||||
// the mutable globals were collected. Here, it is easy to see that there is only a single
|
||||
// runtime blob and thus it's the same that was used for both creating the instance and
|
||||
// collecting the mutable globals.
|
||||
// This function panics if the instance was created from a runtime blob different from
|
||||
// which the mutable globals were collected. Here, it is easy to see that there is only
|
||||
// a single runtime blob and thus it's the same that was used for both creating the
|
||||
// instance and collecting the mutable globals.
|
||||
let globals_snapshot =
|
||||
GlobalsSnapshot::take(&snapshot_data.mutable_globals, &instance_wrapper);
|
||||
|
||||
@@ -291,10 +291,10 @@ fn common_config(semantics: &Semantics) -> std::result::Result<wasmtime::Config,
|
||||
/// estimate of the actual stack limit in wasmtime. This is because wasmtime measures it's stack
|
||||
/// usage in bytes.
|
||||
///
|
||||
/// The actual number of bytes consumed by a function is not trivial to compute without going through
|
||||
/// full compilation. Therefore, it's expected that `native_stack_max` is grealy overestimated and
|
||||
/// thus never reached in practice. The stack overflow check introduced by the instrumentation and
|
||||
/// that relies on the logical item count should be reached first.
|
||||
/// The actual number of bytes consumed by a function is not trivial to compute without going
|
||||
/// through full compilation. Therefore, it's expected that `native_stack_max` is grealy
|
||||
/// overestimated and thus never reached in practice. The stack overflow check introduced by the
|
||||
/// instrumentation and that relies on the logical item count should be reached first.
|
||||
///
|
||||
/// See [here][stack_height] for more details of the instrumentation
|
||||
///
|
||||
@@ -307,12 +307,12 @@ pub struct DeterministicStackLimit {
|
||||
pub logical_max: u32,
|
||||
/// The maximum number of bytes for stack used by wasmtime JITed code.
|
||||
///
|
||||
/// It's not specified how much bytes will be consumed by a stack frame for a given wasm function
|
||||
/// after translation into machine code. It is also not quite trivial.
|
||||
/// It's not specified how much bytes will be consumed by a stack frame for a given wasm
|
||||
/// function after translation into machine code. It is also not quite trivial.
|
||||
///
|
||||
/// Therefore, this number should be choosen conservatively. It must be so large so that it can
|
||||
/// fit the [`logical_max`](Self::logical_max) logical values on the stack, according to the current
|
||||
/// instrumentation algorithm.
|
||||
/// fit the [`logical_max`](Self::logical_max) logical values on the stack, according to the
|
||||
/// current instrumentation algorithm.
|
||||
///
|
||||
/// This value cannot be 0.
|
||||
pub native_stack_max: u32,
|
||||
@@ -335,9 +335,9 @@ pub struct Semantics {
|
||||
// I.e. if [`CodeSupplyMode::Verbatim`] is used.
|
||||
pub fast_instance_reuse: bool,
|
||||
|
||||
/// Specifiying `Some` will enable deterministic stack height. That is, all executor invocations
|
||||
/// will reach stack overflow at the exactly same point across different wasmtime versions and
|
||||
/// architectures.
|
||||
/// Specifiying `Some` will enable deterministic stack height. That is, all executor
|
||||
/// invocations will reach stack overflow at the exactly same point across different wasmtime
|
||||
/// versions and architectures.
|
||||
///
|
||||
/// This is achieved by a combination of running an instrumentation pass on input code and
|
||||
/// configuring wasmtime accordingly.
|
||||
@@ -351,10 +351,10 @@ pub struct Semantics {
|
||||
/// non-determinism.
|
||||
///
|
||||
/// By default, the wasm spec allows some local non-determinism wrt. certain floating point
|
||||
/// operations. Specifically, those operations that are not defined to operate on bits (e.g. fneg)
|
||||
/// can produce NaN values. The exact bit pattern for those is not specified and may depend
|
||||
/// on the particular machine that executes wasmtime generated JITed machine code. That is
|
||||
/// a source of non-deterministic values.
|
||||
/// operations. Specifically, those operations that are not defined to operate on bits (e.g.
|
||||
/// fneg) can produce NaN values. The exact bit pattern for those is not specified and may
|
||||
/// depend on the particular machine that executes wasmtime generated JITed machine code. That
|
||||
/// is a source of non-deterministic values.
|
||||
///
|
||||
/// The classical runtime environment for Substrate allowed it and punted this on the runtime
|
||||
/// developers. For PVFs, we want to ensure that execution is deterministic though. Therefore,
|
||||
@@ -368,11 +368,11 @@ pub struct Config {
|
||||
|
||||
/// The total number of wasm pages an instance can request.
|
||||
///
|
||||
/// If specified, the runtime will be able to allocate only that much of wasm memory pages. This
|
||||
/// is the total number and therefore the [`heap_pages`] is accounted for.
|
||||
/// If specified, the runtime will be able to allocate only that much of wasm memory pages.
|
||||
/// This is the total number and therefore the [`heap_pages`] is accounted for.
|
||||
///
|
||||
/// That means that the initial number of pages of a linear memory plus the [`heap_pages`] should
|
||||
/// be less or equal to `max_memory_pages`, otherwise the instance won't be created.
|
||||
/// That means that the initial number of pages of a linear memory plus the [`heap_pages`]
|
||||
/// should be less or equal to `max_memory_pages`, otherwise the instance won't be created.
|
||||
///
|
||||
/// Moreover, `memory.grow` will fail (return -1) if the sum of the number of currently mounted
|
||||
/// pages and the number of additional pages exceeds `max_memory_pages`.
|
||||
@@ -382,8 +382,8 @@ pub struct Config {
|
||||
|
||||
/// The WebAssembly standard requires all imports of an instantiated module to be resolved,
|
||||
/// othewise, the instantiation fails. If this option is set to `true`, then this behavior is
|
||||
/// overriden and imports that are requested by the module and not provided by the host functions
|
||||
/// will be resolved using stubs. These stubs will trap upon a call.
|
||||
/// overriden and imports that are requested by the module and not provided by the host
|
||||
/// functions will be resolved using stubs. These stubs will trap upon a call.
|
||||
pub allow_missing_func_imports: bool,
|
||||
|
||||
/// A directory in which wasmtime can store its compiled artifacts cache.
|
||||
@@ -402,15 +402,16 @@ enum CodeSupplyMode<'a> {
|
||||
// some instrumentations for both anticipated paths: substrate execution and PVF execution.
|
||||
//
|
||||
// Should there raise a need in performing no instrumentation and the client doesn't need
|
||||
// to do any checks, then we can provide a `Cow` like semantics here: if we need the blob and
|
||||
// the user got `RuntimeBlob` then extract it, or otherwise create it from the given
|
||||
// to do any checks, then we can provide a `Cow` like semantics here: if we need the blob
|
||||
// and the user got `RuntimeBlob` then extract it, or otherwise create it from the given
|
||||
// bytecode.
|
||||
blob: RuntimeBlob,
|
||||
},
|
||||
|
||||
/// The code is supplied in a form of a compiled artifact.
|
||||
///
|
||||
/// This assumes that the code is already prepared for execution and the same `Config` was used.
|
||||
/// This assumes that the code is already prepared for execution and the same `Config` was
|
||||
/// used.
|
||||
Artifact { compiled_artifact: &'a [u8] },
|
||||
}
|
||||
|
||||
@@ -430,11 +431,12 @@ pub fn create_runtime(
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that the compiled artifact passed here was produced by [`prepare_runtime_artifact`].
|
||||
/// Otherwise, there is a risk of arbitrary code execution with all implications.
|
||||
/// The caller must ensure that the compiled artifact passed here was produced by
|
||||
/// [`prepare_runtime_artifact`]. Otherwise, there is a risk of arbitrary code execution with all
|
||||
/// implications.
|
||||
///
|
||||
/// It is ok though if the `compiled_artifact` was created by code of another version or with different
|
||||
/// configuration flags. In such case the caller will receive an `Err` deterministically.
|
||||
/// It is ok though if the `compiled_artifact` was created by code of another version or with
|
||||
/// different configuration flags. In such case the caller will receive an `Err` deterministically.
|
||||
pub unsafe fn create_runtime_from_artifact(
|
||||
compiled_artifact: &[u8],
|
||||
config: Config,
|
||||
@@ -445,8 +447,8 @@ pub unsafe fn create_runtime_from_artifact(
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// This is only unsafe if called with [`CodeSupplyMode::Artifact`]. See [`create_runtime_from_artifact`]
|
||||
/// to get more details.
|
||||
/// This is only unsafe if called with [`CodeSupplyMode::Artifact`]. See
|
||||
/// [`create_runtime_from_artifact`] to get more details.
|
||||
unsafe fn do_create_runtime(
|
||||
code_supply_mode: CodeSupplyMode<'_>,
|
||||
config: Config,
|
||||
|
||||
@@ -44,7 +44,8 @@ pub fn from_wasmtime_val(val: wasmtime::Val) -> Value {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a sp_wasm_interface's [`Value`] into the corresponding variant in wasmtime's [`wasmtime::Val`].
|
||||
/// Converts a sp_wasm_interface's [`Value`] into the corresponding variant in wasmtime's
|
||||
/// [`wasmtime::Val`].
|
||||
pub fn into_wasmtime_val(value: Value) -> wasmtime::Val {
|
||||
match value {
|
||||
Value::I32(v) => wasmtime::Val::I32(v),
|
||||
|
||||
Reference in New Issue
Block a user