Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Evm a part of the supported virtual machines. #3386

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -602,14 +602,18 @@ Run a GraphQL service that exposes a faucet where users can claim tokens. This g

Publish bytecode

**Usage:** `linera publish-bytecode <CONTRACT> <SERVICE> [PUBLISHER]`
**Usage:** `linera publish-bytecode [OPTIONS] <CONTRACT> <SERVICE> [PUBLISHER]`

###### **Arguments:**

* `<CONTRACT>` — Path to the Wasm file for the application "contract" bytecode
* `<SERVICE>` — Path to the Wasm file for the application "service" bytecode
* `<PUBLISHER>` — An optional chain ID to publish the bytecode. The default chain of the wallet is used otherwise

###### **Options:**

* `--vm-runtime <VM_RUNTIME>` — The virtual machine runtime to use



## `linera publish-data-blob`
Expand Down Expand Up @@ -673,6 +677,7 @@ Create an application, and publish the required bytecode

###### **Options:**

* `--vm-runtime <VM_RUNTIME>` — The virtual machine runtime to use
* `--json-parameters <JSON_PARAMETERS>` — The shared parameters as JSON string
* `--json-parameters-path <JSON_PARAMETERS_PATH>` — Path to a JSON file containing the shared parameters
* `--json-argument <JSON_ARGUMENT>` — The instantiation argument as a JSON string
Expand Down Expand Up @@ -878,6 +883,7 @@ Build and publish a Linera project

###### **Options:**

* `--vm-runtime <VM_RUNTIME>` — The virtual machine runtime to use
* `--json-parameters <JSON_PARAMETERS>` — The shared parameters as JSON string
* `--json-parameters-path <JSON_PARAMETERS_PATH>` — Path to a JSON file containing the shared parameters
* `--json-argument <JSON_ARGUMENT>` — The instantiation argument as a JSON string
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions examples/Cargo.lock

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

1 change: 1 addition & 0 deletions linera-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,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
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
58 changes: 58 additions & 0 deletions linera-base/src/vm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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;

#[derive(
Clone,
Copy,
Default,
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
#[default]
Wasm,
/// The Evm for the virtual machine
Evm,
}

impl FromStr for VmRuntime {
type Err = InvalidVmRuntime;

fn from_str(string: &str) -> Result<Self, Self::Err> {
match string {
"wasm" => Ok(VmRuntime::Wasm),
"revm" => Ok(VmRuntime::Evm),
unknown => Err(InvalidVmRuntime(unknown.to_owned())),
}
}
}

scalar!(VmRuntime);

/// 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);
4 changes: 3 additions & 1 deletion linera-chain/src/unit_tests/chain_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use linera_base::{
hashed::Hashed,
identifiers::{ApplicationId, BytecodeId, ChainId, MessageId},
ownership::ChainOwnership,
vm::VmRuntime,
};
use linera_execution::{
committee::{Committee, Epoch, ValidatorState},
Expand Down Expand Up @@ -66,8 +67,9 @@ fn make_app_description() -> (UserApplicationDescription, Blob, Blob) {
let service = Bytecode::new(b"service".into());
let contract_blob = Blob::new_contract_bytecode(contract.compress());
let service_blob = Blob::new_service_bytecode(service.compress());
let vm_runtime = VmRuntime::default();

let bytecode_id = BytecodeId::new(contract_blob.id().hash, service_blob.id().hash);
let bytecode_id = BytecodeId::new(contract_blob.id().hash, service_blob.id().hash, vm_runtime);
(
UserApplicationDescription {
bytecode_id,
Expand Down
4 changes: 3 additions & 1 deletion linera-client/src/client_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ use {
linera_base::{
data_types::{BlobContent, Bytecode},
identifiers::BytecodeId,
vm::VmRuntime,
},
linera_core::client::create_bytecode_blobs,
std::{fs, path::PathBuf},
Expand Down Expand Up @@ -493,6 +494,7 @@ where
chain_client: &ChainClient<NodeProvider, S>,
contract: PathBuf,
service: PathBuf,
vm_runtime: VmRuntime,
) -> Result<BytecodeId, Error> {
info!("Loading bytecode files");
let contract_bytecode = Bytecode::load_from_file(&contract)
Expand All @@ -504,7 +506,7 @@ where

info!("Publishing bytecode");
let (contract_blob, service_blob, bytecode_id) =
create_bytecode_blobs(contract_bytecode, service_bytecode).await;
create_bytecode_blobs(contract_bytecode, service_bytecode, vm_runtime).await;
let (bytecode_id, _) = self
.apply_client_command(chain_client, |chain_client| {
let contract_blob = contract_blob.clone();
Expand Down
13 changes: 13 additions & 0 deletions linera-client/src/client_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use linera_base::{
},
ownership::{ChainOwnership, TimeoutConfig},
time::Duration,
vm::VmRuntime,
};
use linera_core::{client::BlanketMessagePolicy, DEFAULT_GRACE_PERIOD};
use linera_execution::{ResourceControlPolicy, WasmRuntime, WithWasmDefault as _};
Expand Down Expand Up @@ -773,6 +774,10 @@ pub enum ClientCommand {
/// Path to the Wasm file for the application "service" bytecode.
service: PathBuf,

/// The virtual machine runtime to use.
#[arg(long)]
vm_runtime: Option<VmRuntime>,

/// An optional chain ID to publish the bytecode. The default chain of the wallet
/// is used otherwise.
publisher: Option<ChainId>,
Expand Down Expand Up @@ -835,6 +840,10 @@ pub enum ClientCommand {
/// Path to the Wasm file for the application "service" bytecode.
service: PathBuf,

/// The virtual machine runtime to use.
#[arg(long)]
vm_runtime: Option<VmRuntime>,

/// An optional chain ID to publish the bytecode. The default chain of the wallet
/// is used otherwise.
publisher: Option<ChainId>,
Expand Down Expand Up @@ -1241,6 +1250,10 @@ pub enum ProjectCommand {
/// is used otherwise.
publisher: Option<ChainId>,

/// The virtual machine runtime to use.
#[arg(long)]
vm_runtime: Option<VmRuntime>,

/// The shared parameters as JSON string.
#[arg(long)]
json_parameters: Option<String>,
Expand Down
Loading