Skip to content

Commit

Permalink
feat(runtime): Wasmer 1.0 runner (#3799)
Browse files Browse the repository at this point in the history
Add Wasmer 1.0 runner, enabled by wasmer1_vm features (similar to wasmtime_vm). Expose wasmer 1.0 runner and wasmtime runner available to neard and vm standalone.

Test Plan
---------
All near-vm-runner tests pass. compatible behavior as wasmer 0.17. neard compiles and work with wasmer 1.0 runner turns on
  • Loading branch information
ailisp authored Feb 23, 2021
1 parent a637519 commit 79f1732
Show file tree
Hide file tree
Showing 20 changed files with 1,201 additions and 206 deletions.
408 changes: 383 additions & 25 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ delay_detector = ["neard/delay_detector"]
rosetta_rpc = ["neard/rosetta_rpc"]
protocol_feature_forward_chunk_parts = ["neard/protocol_feature_forward_chunk_parts"]
nightly_protocol = ["near-primitives/nightly_protocol", "near-jsonrpc/nightly_protocol"]
# enable this to build neard with wasmer 1.0 runner
# now if none of wasmer0_default, wasmer1_default or wasmtime_default is enabled, wasmer1 would be default
wasmer1_default = ["node-runtime/wasmer1_default"]
wasmer0_default = ["node-runtime/wasmer0_default"]
wasmtime_default = ["node-runtime/wasmtime_default"]
# enable some of these to run runtime tests with wasmer 1.0, 0.x and wasmtime vm enabled
# but would not change default runner used by neard
wasmer1_vm = ["node-runtime/wasmer1_vm"]
wasmer0_vm = ["node-runtime/wasmer0_vm"]
wasmtime_vm = ["node-runtime/wasmtime_vm"]
nightly_protocol_features = ["nightly_protocol", "neard/nightly_protocol_features", "protocol_feature_evm", "protocol_feature_block_header_v3"]
protocol_feature_evm = ["neard/protocol_feature_evm", "testlib/protocol_feature_evm", "runtime-params-estimator/protocol_feature_evm"]
protocol_feature_block_header_v3 = ["near-primitives/protocol_feature_block_header_v3", "near-chain/protocol_feature_block_header_v3", "neard/protocol_feature_block_header_v3"]
Expand Down
15 changes: 15 additions & 0 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,21 @@ skip = [
# actix 0.11 and actix-rt 2.0 use conflicting versions
{ name = "actix-macros", version = "=0.1.3" },

# wasmer 1.0 use some newer version of crates than wasmer 0.17 & wasmtime, old ones are skipped here
{ name = "cranelift-bforest", version = "=0.67.0" },
{ name = "cranelift-codegen", version = "=0.67.0" },
{ name = "cranelift-codegen-meta", version = "=0.67.0" },
{ name = "cranelift-codegen-shared", version = "=0.67.0" },
{ name = "cranelift-entity", version = "=0.67.0" },
{ name = "cranelift-frontend", version = "=0.67.0" },
{ name = "gimli", version = "=0.21.0" },
{ name = "libloading", version = "=0.5.2" },
{ name = "regalloc", version = "=0.0.30" },
{ name = "strsim", version = "=0.8.0" },
{ name = "wasmparser", version = "=0.57.0" },
{ name = "which", version = "=3.1.1" },
{ name = "object", version = "=0.23.0" },

# hashbrown uses an older version
{ name = "ahash", version = "=0.4.7" },
]
23 changes: 23 additions & 0 deletions runtime/near-vm-errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ pub enum FunctionCallError {
WasmUnknownError,
HostError(HostError),
EvmError(EvmError),
/// An error message when wasmer 1.0 returns a wasmer::RuntimeError
WasmerRuntimeError(String),
/// A trap in Wasmer 1.0, not same as WasmTrap above, String is a machine readable form like "stk_ovf"
/// String is used instead of wasmer internal enum is because of BorshSerializable.
/// It can be convert back by wasmer_vm::TrapCode::from_str
Wasmer1Trap(String),
}
#[derive(
Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize, RpcError,
Expand Down Expand Up @@ -277,6 +283,8 @@ pub enum VMLogicError {
EvmError(EvmError),
}

impl std::error::Error for VMLogicError {}

/// An error that is caused by an operation on an inconsistent state.
/// E.g. a deserialization error or an integer overflow.
#[derive(Debug, Clone, PartialEq, Eq, BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
Expand Down Expand Up @@ -306,6 +314,19 @@ impl From<PrepareError> for VMError {
}
}

impl From<&VMLogicError> for VMError {
fn from(err: &VMLogicError) -> Self {
match err {
VMLogicError::HostError(h) => {
VMError::FunctionCallError(FunctionCallError::HostError(h.clone()))
}
VMLogicError::ExternalError(s) => VMError::ExternalError(s.clone()),
VMLogicError::InconsistentStateError(e) => VMError::InconsistentStateError(e.clone()),
VMLogicError::EvmError(_) => unreachable!("Wasm can't return EVM error"),
}
}
}

impl fmt::Display for VMLogicError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(f, "{:?}", self)
Expand Down Expand Up @@ -341,6 +362,8 @@ impl fmt::Display for FunctionCallError {
write!(f, "Unknown error during Wasm contract execution")
}
FunctionCallError::EvmError(e) => write!(f, "EVM: {:?}", e),
FunctionCallError::WasmerRuntimeError(e) => write!(f, "Wasmer Runtime: {}", e),
FunctionCallError::Wasmer1Trap(e) => write!(f, "Wasmer 1.0 trap: {}", e),
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion runtime/near-vm-logic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ serde_json = {version= "1", features= ["preserve_order"]}
[features]
default = []
protocol_feature_evm = ["near-primitives-core/protocol_feature_evm"]
wasmer0_default = []
wasmtime_default = []

wasmer1_default = []

# Use this feature to enable counting of fees and costs applied.
costs_counting = ["near-primitives-core/costs_counting"]
Expand Down
47 changes: 40 additions & 7 deletions runtime/near-vm-logic/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,58 @@ use std::hash::Hash;

#[derive(Clone, Copy, Debug, Hash, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
pub enum VMKind {
/// Wasmer VM.
Wasmer,
/// Wasmer 0.17.x VM.
Wasmer0,
/// Wasmtime VM.
Wasmtime,
/// Wasmer 1.x VM.
Wasmer1,
}

impl Default for VMKind {
#[cfg(feature = "wasmer_default")]
#[cfg(all(
feature = "wasmer0_default",
not(feature = "wasmer1_default"),
not(feature = "wasmtime_default")
))]
fn default() -> Self {
VMKind::Wasmer
VMKind::Wasmer0
}

#[cfg(feature = "wasmtime_default")]
#[cfg(all(
not(feature = "wasmer0_default"),
feature = "wasmer1_default",
not(feature = "wasmtime_default")
))]
fn default() -> Self {
VMKind::Wasmer1
}

#[cfg(all(
not(feature = "wasmer0_default"),
not(feature = "wasmer1_default"),
feature = "wasmtime_default"
))]
fn default() -> Self {
VMKind::Wasmtime
}

#[cfg(all(not(feature = "wasmer_default"), not(feature = "wasmtime_default")))]
#[cfg(all(
not(feature = "wasmer0_default"),
not(feature = "wasmer1_default"),
not(feature = "wasmtime_default")
))]
fn default() -> Self {
VMKind::Wasmer0
}

// These features should be mutually exclusive, but implement this to work around CI cargo check --all-features
#[cfg(all(
feature = "wasmer0_default",
feature = "wasmer1_default",
feature = "wasmtime_default"
))]
fn default() -> Self {
VMKind::Wasmer
VMKind::Wasmer0
}
}
2 changes: 1 addition & 1 deletion runtime/near-vm-runner-standalone/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ strum = "0.20"
num-rational = { version = "0.3" }

near-vm-logic = { path = "../near-vm-logic", version = "3.0.0", features = ["costs_counting"]}
near-vm-runner = { path = "../near-vm-runner", version = "3.0.0", features = ["wasmtime_vm"] }
near-vm-runner = { path = "../near-vm-runner", version = "3.0.0", features = ["wasmtime_vm", "wasmer1_vm"] }
near-primitives-core = { path = "../../core/primitives-core", version = "0.1.0" }

[features]
Expand Down
3 changes: 2 additions & 1 deletion runtime/near-vm-runner-standalone/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ fn main() {
let vm_kind: VMKind = match matches.value_of("vm-kind") {
Some(value) => match value {
"wasmtime" => VMKind::Wasmtime,
"wasmer" => VMKind::Wasmer,
"wasmer" => VMKind::Wasmer0,
"wasmer1" => VMKind::Wasmer1,
_ => VMKind::default(),
},
None => VMKind::default(),
Expand Down
13 changes: 9 additions & 4 deletions runtime/near-vm-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ This crate implements the specification of the interface that Near blockchain ex

[dependencies]
borsh = "0.8.1"
wasmer-runtime = { version="0.17.1", features = ["default-backend-singlepass"], default-features = false, package = "wasmer-runtime-near" }
wasmer-runtime = { version="0.17.1", features = ["default-backend-singlepass"], default-features = false, package = "wasmer-runtime-near", optional = true }
# Always used even for wasmer 1.0 for validating wasm, will be replaced when refactor prepare.rs
wasmer-runtime-core = {version = "0.17.1", package = "wasmer-runtime-core-near" }
wasmer = { version = "1.0.2", optional = true }
wasmer-types = { version = "1.0.2", optional = true }
wasmer-compiler-singlepass = { version = "1.0.2", optional = true }
pwasm-utils = "0.12"
parity-wasm = "0.41"
wasmtime = { version = "0.20.0", default-features = false, optional = true }
Expand All @@ -33,11 +37,12 @@ wabt = "0.9"
bencher = "^0.1.5"

[features]
default = [ "wasmer_default" ]
# all vms enabled for tests, but only one default vm, specified by runtime crate
default = ["wasmer0_vm", "wasmtime_vm", "wasmer1_vm"]
wasmer0_vm = [ "wasmer-runtime" ]
wasmtime_vm = [ "wasmtime", "anyhow"]
wasmer1_vm = [ "wasmer", "wasmer-types", "wasmer-compiler-singlepass" ]
lightbeam = ["wasmtime/lightbeam"]
wasmer_default = []
wasmtime_default = ["wasmtime_vm"]
no_cpu_compatibility_checks = []
protocol_feature_evm = ["near-primitives/protocol_feature_evm", "near-evm-runner/protocol_feature_evm"]

Expand Down
Loading

0 comments on commit 79f1732

Please sign in to comment.