-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
base: main
Are you sure you want to change the base?
Conversation
Integrate the VM type to the BytecodeId.
@@ -47,9 +48,14 @@ pub fn create_dummy_user_application_description( | |||
compressed_bytes: b"service".to_vec(), | |||
}); | |||
|
|||
let vm_runtime = VmRuntime::default(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: just inline the value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, done.
@@ -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, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, if so it would have to be in a separate PR I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think that makes sense. Or even something like:
pub enum BytecodeId {
Wasm {
contract_blob_hash: CryptoHash,
service_blob_hash: CryptoHash,
},
Evm {
bytecode_hash: CryptoHash,
},
}
Or even just have one blob per bytecode, which for Wasm could either be:
- a
tar
archive with the contract and the service together, - a blob index listing which blobs make up the contract and which ones make the service
The latter would allow for larger applications, and could store the VM runtime inside the blob itself 🤔
We can discuss to decide on an alternative and implement it in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this approach ^^, even if this may create bit more boilerplate. @afck What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the tar
idea; except I wonder whether it creates a lot of overhead if we have to always load both bytecode modules even if we use only one.
record bytecode-id { | ||
contract-blob-hash: crypto-hash, | ||
service-blob-hash: crypto-hash, | ||
vm-runtime: vm-runtime, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could change. But in another PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that it's not ideal and will make adding new runtimes harder because it will always require changing the WIT interface.
I'm starting to lean more towards having a single bytecode blob with metadata including the VM runtime and pointing to the actual blobs to form the bytecode.
But yeah, it doesn't have to be done in this PR.
linera-client/src/client_options.rs
Outdated
@@ -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>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: We could also handle the default here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct, thank you.
@@ -1344,19 +1344,6 @@ pub trait WithWasmDefault { | |||
} | |||
|
|||
impl WasmRuntime { | |||
#[cfg(with_wasm_runtime)] | |||
pub fn default_with_sanitizer() -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? Is this unused?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
@MathieuDutSik LGTM. I believe you need to update the summary. Letting someone else accept for good |
@@ -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, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think that makes sense. Or even something like:
pub enum BytecodeId {
Wasm {
contract_blob_hash: CryptoHash,
service_blob_hash: CryptoHash,
},
Evm {
bytecode_hash: CryptoHash,
},
}
Or even just have one blob per bytecode, which for Wasm could either be:
- a
tar
archive with the contract and the service together, - a blob index listing which blobs make up the contract and which ones make the service
The latter would allow for larger applications, and could store the VM runtime inside the blob itself 🤔
We can discuss to decide on an alternative and implement it in a separate PR.
@@ -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( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Also need to update the documentation above, maybe with:
Creates a bytecode ID from contract/service hashes and the VM runtime to use.
fn from_str(string: &str) -> Result<Self, Self::Err> { | ||
match string { | ||
"wasm" => Ok(VmRuntime::Wasm), | ||
"revm" => Ok(VmRuntime::Evm), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I think this should be "evm"
, because if I understood correctly revm is an implementation of the Evm (like Wasmer is an implementation of Wasm) 🤔
"revm" => Ok(VmRuntime::Evm), | |
"evm" => Ok(VmRuntime::Evm), |
record bytecode-id { | ||
contract-blob-hash: crypto-hash, | ||
service-blob-hash: crypto-hash, | ||
vm-runtime: vm-runtime, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that it's not ideal and will make adding new runtimes harder because it will always require changing the WIT interface.
I'm starting to lean more towards having a single bytecode blob with metadata including the VM runtime and pointing to the actual blobs to form the bytecode.
But yeah, it doesn't have to be done in this PR.
} else { | ||
panic!( | ||
"An Evm runtime is required to load user applications. \ | ||
Please enable the `revm` feature flags \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: typo
Please enable the `revm` feature flags \ | |
Please enable the `revm` feature flag \ |
let evm_runtime = EvmRuntime::Revm; | ||
Ok(EvmServiceModule::new(_service_bytecode, evm_runtime) | ||
.await? | ||
.into()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not really sure what it means to have an Evm service. We could either return an error saying Evm services are not supported, or figure out a way to query the Evm state, either exposing some read-only entrypoints or a single generic service to inspect the state.
} else { | ||
panic!( | ||
"An Evm runtime is required to load user applications. \ | ||
Please enable the `revm` feature flags \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: typo
Please enable the `revm` feature flags \ | |
Please enable the `revm` feature flag \ |
@@ -278,41 +280,57 @@ pub trait Storage: Sized { | |||
let compressed_contract_bytecode = CompressedBytecode { | |||
compressed_bytes: contract_blob.into_bytes().to_vec(), | |||
}; | |||
let contract_bytecode = | |||
let _contract_bytecode = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add an attribute instead of the underscore. The pattern is to add the underscore to unused bindings, but in this case it might be used.
let _contract_bytecode = | |
#[cfg_attr(not(any(with_wasm_runtime, with_revm)), allow(unused_variables))] | |
let contract_bytecode = |
Please enable the `wasmer` or the `wasmtime` feature flags \ | ||
when compiling `linera-storage`." | ||
); | ||
let _service_bytecode = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here:
let _service_bytecode = | |
#[cfg_attr(not(any(with_wasm_runtime, with_revm)), allow(unused_variables))] | |
let service_bytecode = |
Motivation
We extend here the support for EVM. This requires no longer making the virtual machine
a feature of the storage but instead a part of the
BytecodeId
.Proposal
The following changes have been done:
VmRuntime
has been introduced that covers bothWasm
(Native linera) andEvm
.VmRuntime
is added to theBytecodeId
. This is a reasonable way to make the VM a part of the type description.VmRuntime
in theUserApplicationDescription
since this forces thecreate_application
to have aVmRuntime
type. While innocent, this changes is not adequate since thecreate_application
is used in smart contract code and we want to avoid this part to seep into the smart contract code.VmRuntime,
does not depend on any feature. This is because they have to pass the wit barrier and the wit-types cannot depend on features.VmRuntime
has been added to thelinera-base
. This is unavoidable becauseBytecodeId
depends on it.load_contract/load_service
is simplified into one single code that panics when relevant features have not been installed.--vm-runtime
is added to the function calls likepublish_application
. When missing it defaults toVmRuntime::Wasm
.default_with_stabilizer
is eliminated since it is not used.contract_runtime_apis.rs
forApplicationDescription
is corrected.Test Plan
The CI. No test has been added to test the functionality.
Release Plan
Normal release plan.
Links
None.