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