Home

Awesome

Rust SSVM

build Generic badge

This project provides SSVM a Rust interface by using EVMC (Ethereum Client-VM Connector API) to binding SSVM and host written in Rust.

We extend evmc rust binding module to include evmc-client base on evmc version 6.3.1 for now.

The software architecture of evmc-client was inspired by go-ethereum about how to use EVMC connect Ewasm VM (Hera) with host written in golang.

evmc-client :                                ┌───────────────────────────────────────────────┐
stack diagram                                │                 evmc-client                   │
                                             ├───────────────────────────────────────────────┤
                                             │            lib.rs (pub interface)             │
                                             ├─────────────────────────────────┬─────────────┤
                                             │   host.rs (hook host context)   │  loader.rs  │
go-ethereum :                                ┆                                               ┆
sequential diagram                           ┆                                               ┆
                                                                         ┌───────────────────┐
┌───────────────────┐ ┌────────────────────┐ ┌─────────────────────────┐ │     C module      │
│geth/core/vm/evm.go│ │geth/core/vm/evmc.go│ │evmc/bindings/.../evmc.go│ │ex. loader and hera│
└─────────┬─────────┘ └─────────┬──────────┘ └────────────┬────────────┘ └─────────┬─────────┘
 NewEVM   │ NewEVMC             │                         │                        │
─────────>│────────────────────>│                         │                        │
          │           CreateVM ─┤                         │                        │
          │                     │ Load                    │                      ╔═══════════╗
          │                     │ ───────────────────────>│                      ║  Loader  ░║
          │                     │                         │ evmc_load_and_create ╚═══════════╝
          │                     │                         │───────────────────────>│
          │                     │                         │      load EVMC VM .so ─┤
          │                     │                         │      call evmc_create ─┤
          │                     │                         │                        │
          │                     │ return Instance{handle} │ return evmc_instance   │
          │<─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │<─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│
          │                     │                         │                        │
 run      │ Run                 │                         │                        │
─────────>│────────────────────>│                         │                      ╔═══════════╗
          │                     │ Execute                 │                      ║ EVMC VM  ░║
          │                     │ ───────────────────────>│                      ║ ex. Hera  ║
          │                     │                         │ evmc_execute         ╚═══════════╝
          │                     │                         │───────────────────────>│
          │                     │                         │               execute ─┤
          │                     │ return output, gasLeft, │                        │
          │                     │        err              │return evmc_result      │
          │<─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │<─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│
          │                     │                         │                        │

Build environment

Build rust-ssvm you need prepare a build ssvm environment and include rust compile tool.

> docker pull secondstate/ssvm
> git clone --recursive git@github.com:second-state/rust-ssvm.git
> docker run -it \
    -v $(pwd)/rust-ssvm:/root/rust-ssvm \
    secondstate/ssvm:latest
(docker) $ curl https://sh.rustup.rs -sSf | sh
(docker) $ source ~/.cargo/env
(docker) $ cd ~/rust-ssvm && cargo build -v

Example

We provide a simple demo show how to launch a ssvm instance and call vm execute function with a dummy HostContext (host functions) and fib.wasm demo bytecode.

Yul is an intermediate language designed by Ethereum fundaction.
The other project of our company call SOLL could help you compile Yul to EWASM. (more...)

(docker) $ cd ~/rust-ssvm && cargo run --example execute_vm -v -- -f=examples/fib.wasm

The result should be the same as the following content.

Instantiate: ("ssvm", "0.4.0")
Host: get_storage
"0000000000000000000000000000000000000000000000000000000000000000" -> "0000000000000000000000000000000000000000000000000000000000000000"
Host: set_storage
"0000000000000000000000000000000000000000000000000000000000000000" -> "0000000000000000000000000000000000000000000000000000000000000001"
Host: get_storage
"0000000000000000000000000000000000000000000000000000000000000001" -> "0000000000000000000000000000000000000000000000000000000000000000"
Host: set_storage
"0000000000000000000000000000000000000000000000000000000000000001" -> "0000000000000000000000000000000000000000000000000000000000000001"
Host: get_storage
"0000000000000000000000000000000000000000000000000000000000000002" -> "0000000000000000000000000000000000000000000000000000000000000000"
Host: set_storage
"0000000000000000000000000000000000000000000000000000000000000002" -> "0000000000000000000000000000000000000000000000000000000000000002"
Host: get_storage
"0000000000000000000000000000000000000000000000000000000000000003" -> "0000000000000000000000000000000000000000000000000000000000000000"
Host: set_storage
"0000000000000000000000000000000000000000000000000000000000000003" -> "0000000000000000000000000000000000000000000000000000000000000003"
Host: get_storage
"0000000000000000000000000000000000000000000000000000000000000004" -> "0000000000000000000000000000000000000000000000000000000000000000"
Host: set_storage
"0000000000000000000000000000000000000000000000000000000000000004" -> "0000000000000000000000000000000000000000000000000000000000000005"
Host: get_storage
"0000000000000000000000000000000000000000000000000000000000000005" -> "0000000000000000000000000000000000000000000000000000000000000000"
Host: set_storage
"0000000000000000000000000000000000000000000000000000000000000005" -> "0000000000000000000000000000000000000000000000000000000000000008"
Host: get_storage
"0000000000000000000000000000000000000000000000000000000000000006" -> "0000000000000000000000000000000000000000000000000000000000000000"
Host: set_storage
"0000000000000000000000000000000000000000000000000000000000000006" -> "000000000000000000000000000000000000000000000000000000000000000d"
Host: get_storage
"0000000000000000000000000000000000000000000000000000000000000007" -> "0000000000000000000000000000000000000000000000000000000000000000"
Host: set_storage
"0000000000000000000000000000000000000000000000000000000000000007" -> "0000000000000000000000000000000000000000000000000000000000000015"
Host: get_storage
"0000000000000000000000000000000000000000000000000000000000000008" -> "0000000000000000000000000000000000000000000000000000000000000000"
Host: set_storage
"0000000000000000000000000000000000000000000000000000000000000008" -> "0000000000000000000000000000000000000000000000000000000000000022"
Host: get_storage
"0000000000000000000000000000000000000000000000000000000000000009" -> "0000000000000000000000000000000000000000000000000000000000000000"
Host: set_storage
"0000000000000000000000000000000000000000000000000000000000000009" -> "0000000000000000000000000000000000000000000000000000000000000037"
Dump storage:
"0000000000000000000000000000000000000000000000000000000000000000" -> "0000000000000000000000000000000000000000000000000000000000000001"
"0000000000000000000000000000000000000000000000000000000000000001" -> "0000000000000000000000000000000000000000000000000000000000000001"
"0000000000000000000000000000000000000000000000000000000000000002" -> "0000000000000000000000000000000000000000000000000000000000000002"
"0000000000000000000000000000000000000000000000000000000000000003" -> "0000000000000000000000000000000000000000000000000000000000000003"
"0000000000000000000000000000000000000000000000000000000000000004" -> "0000000000000000000000000000000000000000000000000000000000000005"
"0000000000000000000000000000000000000000000000000000000000000005" -> "0000000000000000000000000000000000000000000000000000000000000008"
"0000000000000000000000000000000000000000000000000000000000000006" -> "000000000000000000000000000000000000000000000000000000000000000d"
"0000000000000000000000000000000000000000000000000000000000000007" -> "0000000000000000000000000000000000000000000000000000000000000015"
"0000000000000000000000000000000000000000000000000000000000000008" -> "0000000000000000000000000000000000000000000000000000000000000022"
"0000000000000000000000000000000000000000000000000000000000000009" -> "0000000000000000000000000000000000000000000000000000000000000037"
Output:  "0000000000000000000000000000000000000000000000000000000000000037"
GasLeft: 49800000
Status:  EVMC_SUCCESS

If you want to see more runtime information inside SSVM, you can modify rust-ssvm/SSVM/lib/support/log.cpp as below.

 void setErrorLoggingLevel() {
   el::Loggers::addFlag(el::LoggingFlag::HierarchicalLogging);
-  el::Loggers::setLoggingLevel(el::Level::Error);
+  el::Loggers::setLoggingLevel(el::Level::Debug);
 }

EWASM Test

Refer to the EWASM Test Guide for more details.

License

Rust SSVM has dual license, including AGPL 3.0 license and APACHE-2 license.