[][src]Crate ethereumvm

EthereumVM implementation, traits and structs.

EthereumVM works on two different levels. It handles:

  1. a transaction, or
  2. an Ethereum execution context.

To interact with the virtual machine, you usually only need to work with VM methods.

A EthereumVM's Lifecycle

A VM can be started after it is given a Transaction (or Context) and a BlockHeader. The user can then fire or step to run it. fire runs the EVM code (given in field code of the transaction) until it finishes or cannot continue. However step only runs at most one instruction. If the virtual machine needs some information (accounts in the current block, or block hashes of previous blocks) it fails, returning a RequireError enumeration. With the data returned in the RequireError enumeration, one can use the methods commit_account and commit_blockhash to commit the information to the VM. fire or step can be subsequently called to restart from that point. The current VM status can always be obtained using the status function. Again, see VM for a list of methods that can be applied.

Patch: Specifying a Network and Hard-fork

Every VM is associated with a Patch. This patch tells the VM which Ethereum network and which hard fork it is on. You will need to specify the patch as the type parameter. To interact with multiple patches at the same time, it is recommended that you use trait objects.

The example below creates a new EthereumVM and stores the object in vm which can be used to fire, step or get status on. To do this, it must first create a transaction and a block header. The patch associated with the VM is either EmbeddedPatch or VMTestPatch depending on an arbitrary block number value set at the beginning of the program.

use ethereumvm::{EmbeddedPatch, VMTestPatch,
                HeaderParams, ValidTransaction, TransactionAction,
                VM, SeqTransactionVM};
use bigint::{Gas, U256, Address};
use std::rc::Rc;

fn main() {
  let block_number = 1000;
  let transaction = ValidTransaction {
    caller: Some(Address::default()),
    gas_price: Gas::zero(),
    gas_limit: Gas::max_value(),
    action: TransactionAction::Create,
    value: U256::zero(),
    input: Rc::new(Vec::new()),
    nonce: U256::zero()
  };
  let header = HeaderParams {
    beneficiary: Address::default(),
    timestamp: 0,
    number: U256::zero(),
    difficulty: U256::zero(),
    gas_limit: Gas::zero()
  };
  let cfg_before_500 = VMTestPatch::default();
  let cfg_after_500 = EmbeddedPatch::default();
  let vm = if block_number < 500 {
    SeqTransactionVM::new(
      &cfg_before_500,
      transaction,
      header
    );
  } else {
    SeqTransactionVM::new(
      &cfg_after_500,
      transaction,
      header
    );
  };
}

Transaction Execution

To start a VM on the Transaction level, use the TransactionVM struct. Usually, you want to use the sequential memory module which can be done using the type definition SeqTransactionVM.

Calling TransactionVM::new or SeqTransactionVM::new requires the transaction passed in to be valid (according to the rules for an Ethereum transaction). If the transaction is invalid, the VM will probably panic. If you want to handle untrusted transactions, you should use SeqTransactionVM::new_untrusted, which will not panic but instead return an error if the transaction is invalid.

Context Execution

To start a VM on the Context level, use the ContextVM struct. Usually, you use the sequential memory module with the type definition SeqContextVM. Context execution, as with other EVM implementations, will not handle transaction-level gas reductions.

Re-exports

pub use crate::errors::CommitError;
pub use crate::errors::NotSupportedError;
pub use crate::errors::OnChainError;
pub use crate::errors::PreExecutionError;
pub use crate::errors::RequireError;

Modules

errors

VM errors

Structs

AccountState

A struct that manages the current account state for one EVM.

BlockhashState

A struct that manages the current blockhash state for one EVM.

Context

A VM context. See the Yellow Paper for more information.

ContextVM

A VM that executes using a context and block information.

DynamicAccountPatch

AccountPatch that can be configured in client code runtime

DynamicPatch

Patch that can be configured in client code runtime

ECRECPrecompiled

ECREC precompiled contract.

EmbeddedAccountPatch

Mainnet account patch

EmbeddedPatch

Embedded patch.

HeaderParams

Block header.

IDPrecompiled

ID precompiled contract.

Log
Machine

A VM state with PC.

PC

Represents a program counter in EVM.

PCMut

Represents a mutable program counter in EVM.

RIP160Precompiled

RIP160 precompiled contract.

Runtime

A VM runtime. Only available in eval.

SHA256Precompiled

SHA256 precompiled contract.

SeqMemory

A sequencial memory. It uses Rust's Vec for internal representation.

Stack

Represents an EVM stack.

State

A VM state without PC.

Storage

Internal representation of an account storage. It will return a RequireError if trying to access non-existing storage.

TransactionVM

A VM that executes using a transaction and block information.

UntrustedTransaction

Represents an Ethereum transaction.

VMTestPatch

Patch sepcific for the jsontests crate.

ValidTransaction

Represents an Ethereum transaction.

Valids

Mapping of valid jump destination from code.

Enums

AccountChange

Represents an account. This is usually returned by the EVM.

AccountCommitment

A single account commitment.

Instruction

Instructions for the program counter. This is the same as Opcode except PUSH, which might take longer length.

MachineStatus

Represents the current runtime status.

Opcode

Opcode enum. One-to-one corresponding to an u8 value.

TransactionAction
VMStatus

VM Status

Statics

ECREC_PRECOMPILED

Static value of ECREC precompiled contract.

EMBEDDED_PRECOMPILEDS

Default precompiled collections.

ID_PRECOMPILED

Static value of ID precompiled contract.

RIP160_PRECOMPILED

Static value of RIP160 precompiled contract.

SHA256_PRECOMPILED

Static value of SHA256 precompiled contract.

Traits

AccountPatch

Account patch for account related variables. Account patch is always static, as it's usually stays constant for any given network.

Memory

Represent a memory in EVM. Read should always succeed. Write can fall.

Patch

Represents different block range context.

Precompiled

Represent a precompiled contract.

VM

Represents an EVM. This is usually the main interface for clients to interact with.

Type Definitions

SeqContextVM

A sequential VM. It uses sequential memory representation and hash map storage for accounts.

SeqTransactionVM

A sequential transaction VM. This is same as SeqContextVM except it runs at transaction level.