Skip to content

Commit

Permalink
Move the WasmRuntime / VmRuntime, etc. to linera-base.
Browse files Browse the repository at this point in the history
Integrate the VM type to the BytecodeId.
  • Loading branch information
MathieuDutSik committed Feb 21, 2025
1 parent a53da6e commit 9570014
Show file tree
Hide file tree
Showing 41 changed files with 497 additions and 355 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions linera-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ repository.workspace = true
version.workspace = true

[features]
wasmer = []
wasmtime = []
revm = []
metrics = ["prometheus"]
reqwest = ["dep:reqwest"]
test = ["test-strategy", "proptest"]
Expand Down Expand Up @@ -39,6 +42,7 @@ bcs.workspace = true
cfg-if.workspace = true
chrono.workspace = true
custom_debug_derive.workspace = true
derive_more = { workspace = true, features = ["display"] }
ed25519-dalek.workspace = true
futures.workspace = true
getrandom = { workspace = true, optional = true }
Expand Down
4 changes: 3 additions & 1 deletion linera-base/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ fn main() {
with_metrics: { all(not(target_arch = "wasm32"), feature = "metrics") },
with_reqwest: { feature = "reqwest" },
with_testing: { any(test, feature = "test") },

with_revm: { feature = "revm" },
with_wasmer: { feature = "wasmer" },
with_wasmtime: { all(not(target_arch = "wasm32"), feature = "wasmtime") },
// the old version of `getrandom` we pin here is available on all targets, but
// using it will panic if no suitable source of entropy is found
with_getrandom: { any(web, not(target_arch = "wasm32")) },
Expand Down
30 changes: 27 additions & 3 deletions linera-base/src/identifiers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{
crypto::{BcsHashable, CryptoError, CryptoHash},
data_types::BlockHeight,
doc_scalar, hex_debug,
vm::VmRuntime,
};

/// The owner of a chain. This is currently the hash of the owner's public key used to
Expand Down Expand Up @@ -350,6 +351,8 @@ pub struct BytecodeId<Abi = (), Parameters = (), InstantiationArgument = ()> {
pub contract_blob_hash: CryptoHash,
/// The hash of the blob containing the service bytecode.
pub service_blob_hash: CryptoHash,
/// The virtual machine being used.
pub vm_runtime: VmRuntime,
#[witty(skip)]
#[debug(skip)]
_phantom: PhantomData<(Abi, Parameters, InstantiationArgument)>,
Expand Down Expand Up @@ -568,10 +571,12 @@ impl<Abi, Parameters, InstantiationArgument> PartialEq
let BytecodeId {
contract_blob_hash,
service_blob_hash,
vm_runtime,
_phantom,
} = other;
self.contract_blob_hash == *contract_blob_hash
&& self.service_blob_hash == *service_blob_hash
&& self.vm_runtime == *vm_runtime
}
}

Expand All @@ -595,10 +600,15 @@ impl<Abi, Parameters, InstantiationArgument> Ord
let BytecodeId {
contract_blob_hash,
service_blob_hash,
vm_runtime,
_phantom,
} = other;
(self.contract_blob_hash, self.service_blob_hash)
.cmp(&(*contract_blob_hash, *service_blob_hash))
(
self.contract_blob_hash,
self.service_blob_hash,
self.vm_runtime,
)
.cmp(&(*contract_blob_hash, *service_blob_hash, *vm_runtime))
}
}

Expand All @@ -609,10 +619,12 @@ impl<Abi, Parameters, InstantiationArgument> Hash
let BytecodeId {
contract_blob_hash: contract_blob_id,
service_blob_hash: service_blob_id,
vm_runtime: vm_runtime_id,
_phantom,
} = self;
contract_blob_id.hash(state);
service_blob_id.hash(state);
vm_runtime_id.hash(state);
}
}

Expand All @@ -621,6 +633,7 @@ impl<Abi, Parameters, InstantiationArgument> Hash
struct SerializableBytecodeId {
contract_blob_hash: CryptoHash,
service_blob_hash: CryptoHash,
vm_runtime: VmRuntime,
}

impl<Abi, Parameters, InstantiationArgument> Serialize
Expand All @@ -633,6 +646,7 @@ impl<Abi, Parameters, InstantiationArgument> Serialize
let serializable_bytecode_id = SerializableBytecodeId {
contract_blob_hash: self.contract_blob_hash,
service_blob_hash: self.service_blob_hash,
vm_runtime: self.vm_runtime,
};
if serializer.is_human_readable() {
let bytes =
Expand All @@ -659,13 +673,15 @@ impl<'de, Abi, Parameters, InstantiationArgument> Deserialize<'de>
Ok(BytecodeId {
contract_blob_hash: serializable_bytecode_id.contract_blob_hash,
service_blob_hash: serializable_bytecode_id.service_blob_hash,
vm_runtime: serializable_bytecode_id.vm_runtime,
_phantom: PhantomData,
})
} else {
let serializable_bytecode_id = SerializableBytecodeId::deserialize(deserializer)?;
Ok(BytecodeId {
contract_blob_hash: serializable_bytecode_id.contract_blob_hash,
service_blob_hash: serializable_bytecode_id.service_blob_hash,
vm_runtime: serializable_bytecode_id.vm_runtime,
_phantom: PhantomData,
})
}
Expand All @@ -674,10 +690,15 @@ impl<'de, Abi, Parameters, InstantiationArgument> Deserialize<'de>

impl BytecodeId {
/// Creates a bytecode ID from contract/service hashes.
pub fn new(contract_blob_hash: CryptoHash, service_blob_hash: CryptoHash) -> Self {
pub fn new(
contract_blob_hash: CryptoHash,
service_blob_hash: CryptoHash,
vm_runtime: VmRuntime,
) -> Self {
BytecodeId {
contract_blob_hash,
service_blob_hash,
vm_runtime,
_phantom: PhantomData,
}
}
Expand All @@ -689,6 +710,7 @@ impl BytecodeId {
BytecodeId {
contract_blob_hash: self.contract_blob_hash,
service_blob_hash: self.service_blob_hash,
vm_runtime: self.vm_runtime,
_phantom: PhantomData,
}
}
Expand All @@ -700,6 +722,7 @@ impl<Abi, Parameters, InstantiationArgument> BytecodeId<Abi, Parameters, Instant
BytecodeId {
contract_blob_hash: self.contract_blob_hash,
service_blob_hash: self.service_blob_hash,
vm_runtime: self.vm_runtime,
_phantom: PhantomData,
}
}
Expand All @@ -709,6 +732,7 @@ impl<Abi, Parameters, InstantiationArgument> BytecodeId<Abi, Parameters, Instant
BytecodeId {
contract_blob_hash: self.contract_blob_hash,
service_blob_hash: self.service_blob_hash,
vm_runtime: self.vm_runtime,
_phantom: PhantomData,
}
}
Expand Down
1 change: 1 addition & 0 deletions linera-base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub mod port;
pub mod prometheus_util;
#[cfg(not(chain))]
pub mod task;
pub mod vm;
#[cfg(not(chain))]
pub use task::Blocking;
pub mod time;
Expand Down
3 changes: 3 additions & 0 deletions linera-base/src/unit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::{
MessageId, Owner,
},
ownership::{ChainOwnership, TimeoutConfig},
vm::VmRuntime,
};

/// Test roundtrip of types used in the WIT interface.
Expand Down Expand Up @@ -103,6 +104,7 @@ fn application_id_test_case() -> ApplicationId {
bytecode_id: BytecodeId::new(
CryptoHash::test_hash("contract bytecode"),
CryptoHash::test_hash("service bytecode"),
VmRuntime::default(),
),
creation: MessageId {
chain_id: ChainId::root(0),
Expand All @@ -117,6 +119,7 @@ fn bytecode_id_test_case() -> BytecodeId {
BytecodeId::new(
CryptoHash::test_hash("another contract bytecode"),
CryptoHash::test_hash("another service bytecode"),
VmRuntime::default(),
)
}

Expand Down
154 changes: 154 additions & 0 deletions linera-base/src/vm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//! The virtual machines being supported.
use std::str::FromStr;

use async_graphql::scalar;
use derive_more::Display;
use linera_witty::{WitLoad, WitStore, WitType};
use serde::{Deserialize, Serialize};
use thiserror::Error;

/// The runtime to use for running the application.
#[derive(
Clone,
Copy,
Display,
Hash,
PartialEq,
Eq,
PartialOrd,
Ord,
Serialize,
Deserialize,
WitType,
WitStore,
WitLoad,
Debug,
)]
#[cfg_attr(with_testing, derive(test_strategy::Arbitrary))]
pub enum WasmRuntime {
/// The choice of the Wasmer runtime for WebAssembly
#[display("wasmer")]
Wasmer,
/// The choice of the Wasmtime runtime for WebAssembly
#[display("wasmtime")]
Wasmtime,
/// The choice of the Wasmer with sanitizer runtime for WebAssembly
WasmerWithSanitizer,
/// The choice of the Wasmtime with sanitizer runtime for WebAssembly
WasmtimeWithSanitizer,
}

impl WasmRuntime {
/// Returns whether we need a stabilizer or not.
pub fn needs_sanitizer(self) -> bool {
matches!(
self,
WasmRuntime::WasmerWithSanitizer | WasmRuntime::WasmtimeWithSanitizer
)
}
}

impl FromStr for WasmRuntime {
type Err = InvalidVmRuntime;

fn from_str(string: &str) -> Result<Self, Self::Err> {
match string {
"wasmer" => Ok(WasmRuntime::Wasmer),
"wasmtime" => Ok(WasmRuntime::Wasmtime),
unknown => Err(InvalidVmRuntime(unknown.to_owned())),
}
}
}

scalar!(WasmRuntime);

#[derive(
Clone,
Copy,
Debug,
Display,
Hash,
PartialEq,
Eq,
PartialOrd,
Ord,
Serialize,
Deserialize,
WitType,
WitStore,
WitLoad,
)]
#[cfg_attr(with_testing, derive(test_strategy::Arbitrary))]
/// The choice of runtime for handling the Evm.
pub enum EvmRuntime {
/// The choice of the Revm runtime for Evm.
Revm,
}

scalar!(EvmRuntime);

#[derive(
Clone,
Copy,
Display,
Hash,
PartialEq,
Eq,
PartialOrd,
Ord,
Serialize,
Deserialize,
WitType,
WitStore,
WitLoad,
Debug,
)]
#[cfg_attr(with_testing, derive(test_strategy::Arbitrary))]
/// The virtual machine runtime
pub enum VmRuntime {
/// The Wasm for the virtual machine
Wasm(WasmRuntime),
/// The Evm for the virtual machine
Evm(EvmRuntime),
}

impl FromStr for VmRuntime {
type Err = InvalidVmRuntime;

fn from_str(string: &str) -> Result<Self, Self::Err> {
match string {
"wasmer" => Ok(VmRuntime::Wasm(WasmRuntime::Wasmer)),
"wasmtime" => Ok(VmRuntime::Wasm(WasmRuntime::Wasmtime)),
"revm" => Ok(VmRuntime::Evm(EvmRuntime::Revm)),
unknown => Err(InvalidVmRuntime(unknown.to_owned())),
}
}
}

scalar!(VmRuntime);

#[cfg(with_testing)]
impl Default for VmRuntime {
fn default() -> Self {
cfg_if::cfg_if! {
if #[cfg(with_wasmer)] {
VmRuntime::Wasm(WasmRuntime::Wasmer)
} else if #[cfg(with_wasmtime)] {
VmRuntime::Wasm(WasmRuntime::Wasmtime)
} else if #[cfg(with_revm)] {
VmRuntime::Evm(EvmRuntime::Revm)
} else {
panic!("Cannot call default for VmRuntime without wasmer, or wasmtime or revm features");
}
}
}
}

/// Attempts to create an invalid [`VmRuntime`] instance from a string.
#[derive(Clone, Debug, Error)]
#[error("{0:?} is not a valid virtual machine runtime")]
pub struct InvalidVmRuntime(String);
Loading

0 comments on commit 9570014

Please sign in to comment.