Expand description
§near-vm-runner
An engine that runs smart contracts compiled to Wasm. This is the main crate of the “contract runtime” part of nearcore.
“Running smart contracts” is:
- Wasm instrumentation for gas metering and various safety checks (
prepare.rs). - Compiling Wasm to a particular VM representation (
cache.rs). - Exposing blockchain-specific functionality to Wasm code. That is, defining a corresponding host
function for each function in
near-vm-logic(imports.rs). - Actual code execution (
wasmer_runner.rs).
The particular runtime used for Wasm execution is an implementation detail. At the moment we support Wasmer 0.x, Wasmer 2.0 and Wasmtime, with Wasmer 2.0 being default.
The primary client of Wasm execution services is the blockchain proper. The second client is the contract sdk tooling. vm-runner provides additional API for contract developers to, for example, get a gas costs breakdown.
See the [FAQ][./faq.md] document for high-level design constraints discussion.
§Entry Point
The entry point is the runner::run function.
§Testing
There are a bunch of unit-tests in this crate. You can run them with
$ cargo t -p near-vm-runner --features wasmtime_vm,near_vmThe tests use either a short wasm snippet specified inline, or a couple of
larger test contracts from the near-test-contracts crate.
We also have a fuzzing setup:
$ cd runtime/near-vm-runner && RUSTC_BOOTSTRAP=1 cargo fuzz run runner§Profiling
tracing crate is used to collect Rust code profile data via manual instrumentation.
If you want to know how long a particular function executes, use the following pattern:
fn compute_thing() {
let _span = tracing::debug_span!(target: "vm", "compute_thing").entered();
for i in 0..99 {
do_work()
}
}This will record when the _span object is created and dropped, including the time diff between
the two events.
To get human-readable output out of these events, you can use the built-in tracing subscriber:
tracing_subscriber::fmt::Subscriber::builder()
.with_max_level(tracing::level_filters::LevelFilter::DEBUG)
.with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE)
.init();
code_to_profile_here();Alternatively, there’s an alternative hierarchical profiler
tracing_span_tree::span_tree().enable();
code_to_profile_here();The result would look like this:
112.33ms deserialize_wasmer
2.64ms run_wasmer/instantiate
96.34µs run_wasmer/call
123.15ms run_wasmer
123.17ms run_vmRe-exports§
pub use crate::logic::with_ext_cost_counter;
Modules§
- logic
- prepare
- Module that takes care of loading, checking and preprocessing of a wasm module before execution.
Macros§
Structs§
- Compiled
Contract Info - Contains result of contract compilation with auxiliary data
- Contract
Code - Filesystem
Contract Runtime Cache - Mock
Contract Runtime Cache - NoContract
Runtime Cache - Profile
Data V3 - Profile of gas consumption.
Enums§
Traits§
- Contract
- Trait encapsulating access to the contract’s WASM source code.
- Contract
Runtime Cache - Cache for compiled modules
- Prepared
Contract - VM
Functions§
- config_
cache_ key_ signature - Cache-key signature for
config, independent of any specific contract. Hashes the same inputs as [get_contract_cache_key] minuscode_hash, so two signatures compare equal iff any given contract would land under the same on-disk cache key under either config. - contract_
cached - noop_
background_ spawner - A [
BackgroundJobSpawner] that sends every job to the void. - precompile_
contract - Precompiles contract for the current default VM, and stores result to the cache.
Returns
Ok(true)if compiled code was added to the cache, andOk(false)if element is already in the cache, or if cache isNone. - prepare
- Prepare the contract for execution.
- report_
metrics - Reports the current metrics at the end of a single VM invocation (eg. to run a function call).
- reset_
metrics - run
- Validate and run the specified contract.
- try_
precompile_ contract - Like
precompile_contract, but returns immediately if another thread is already compiling the same contract. Intended for opportunistic background warming on a low-priority pool: if a higher-priority worker (or any other caller) is already runningcompile_and_cachefor this contract’s cache key, this call reportsContractAlreadyInCacheand lets the in-flight compiler populate the cache, instead of blocking a warming worker thread on the per-key compilation lock.