linera_base/
vm.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! The virtual machines being supported.
5
6use std::str::FromStr;
7
8use allocative::Allocative;
9use async_graphql::scalar;
10use derive_more::Display;
11use linera_witty::{WitLoad, WitStore, WitType};
12use serde::{Deserialize, Serialize};
13use thiserror::Error;
14
15use crate::data_types::Amount;
16
17#[derive(
18    Clone,
19    Copy,
20    Default,
21    Display,
22    Hash,
23    PartialEq,
24    Eq,
25    PartialOrd,
26    Ord,
27    Serialize,
28    Deserialize,
29    WitType,
30    WitStore,
31    WitLoad,
32    Debug,
33    Allocative,
34)]
35#[cfg_attr(with_testing, derive(test_strategy::Arbitrary))]
36/// The virtual machine runtime
37pub enum VmRuntime {
38    /// The Wasm virtual machine
39    #[default]
40    Wasm,
41    /// The Evm virtual machine
42    Evm,
43}
44
45impl FromStr for VmRuntime {
46    type Err = InvalidVmRuntime;
47
48    fn from_str(string: &str) -> Result<Self, Self::Err> {
49        match string {
50            "wasm" => Ok(VmRuntime::Wasm),
51            "evm" => Ok(VmRuntime::Evm),
52            unknown => Err(InvalidVmRuntime(unknown.to_owned())),
53        }
54    }
55}
56
57scalar!(VmRuntime);
58
59/// Error caused by invalid VM runtimes
60#[derive(Clone, Debug, Error)]
61#[error("{0:?} is not a valid virtual machine runtime")]
62pub struct InvalidVmRuntime(String);
63
64/// The possible types of queries for an EVM contract
65#[derive(Clone, Debug, Deserialize, Serialize)]
66pub enum EvmQuery {
67    /// A read-only query.
68    Query(Vec<u8>),
69    /// A request to schedule an operation that can mutate the application state.
70    Operation(Vec<u8>),
71    /// A request to schedule operations that can mutate the application state.
72    Operations(Vec<Vec<u8>>),
73}
74
75/// An EVM operation containing a value and argument data.
76#[derive(Debug, Default, Serialize, Deserialize)]
77pub struct EvmOperation {
78    /// The amount being transferred.
79    pub value: alloy_primitives::U256,
80    /// The encoded argument data.
81    pub argument: Vec<u8>,
82}
83
84impl EvmOperation {
85    /// Creates an EVM operation with a specified amount and function input.
86    pub fn new(amount: Amount, argument: Vec<u8>) -> Self {
87        Self {
88            value: amount.into(),
89            argument,
90        }
91    }
92
93    /// Converts the input to a `Vec<u8>` if possible.
94    pub fn to_bytes(&self) -> Result<Vec<u8>, bcs::Error> {
95        bcs::to_bytes(&self)
96    }
97
98    /// Creates an `EvmQuery` from the input.
99    pub fn to_evm_query(&self) -> Result<EvmQuery, bcs::Error> {
100        Ok(EvmQuery::Operation(self.to_bytes()?))
101    }
102}
103
104/// The instantiation argument to EVM smart contracts.
105/// `value` is the amount being transferred.
106#[derive(Default, Serialize, Deserialize)]
107pub struct EvmInstantiation {
108    /// The initial value put in the instantiation of the contract.
109    pub value: alloy_primitives::U256,
110    /// The input to the `fn instantiate` of the EVM smart contract.
111    pub argument: Vec<u8>,
112}