1 个不稳定发布
0.1.0-rc2 | 2021年2月4日 |
---|---|
0.1.0-rc1 |
|
0.0.4 |
|
0.0.1-rc1 |
|
#2 in #evmc
每月 24 次下载
在 2 crates 中使用
190KB
4.5K SLoC
Rust SSVM
本项目通过使用EVMC (Ethereum Client-VM Connector API) 提供了 SSVM 的 Rust 接口,用于绑定 SSVM 和用 Rust 编写的宿主程序。
我们扩展了基于 evmc 版本 6.3.1 的 evmc rust 绑定模块,包括 evmc-client。
evmc-client 的软件架构灵感来源于 go-ethereum,关于如何使用 EVMC 连接 Ewasm VM (Hera) 以及用 golang 编写的宿主程序。
- EVMC-Client 设计架构
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 │
│<─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │<─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─│
│ │ │ │
构建环境
构建 rust-ssvm 需要准备一个构建 ssvm 环境,包括 rust 编译工具。
- 复用 ssvm 构建环境 docker 镜像
> docker pull secondstate/ssvm
- 获取 rust-ssvm 源代码
> git clone --recursive [email protected]:second-state/rust-ssvm.git
- 启动 docker 容器
> docker run -it \
-v $(pwd)/rust-ssvm:/root/rust-ssvm \
secondstate/ssvm:latest
- 安装 rust 编译工具
(docker) $ curl https://sh.rustup.rs -sSf | sh
(docker) $ source ~/.cargo/env
- 构建 rust-ssvm 库
(docker) $ cd ~/rust-ssvm && cargo build -v
示例
我们提供了一个简单的示例,展示了如何使用 dummy HostContext (宿主函数) 和 fib.wasm
演示字节码来启动 ssvm 实例并调用 vm 执行函数。
- HostContext 特性需要由链的后端实现。
fib.wasm
由 Yul 语言编写的 fib.yul 生成。
Yul 是由以太坊基金会设计的一种中间语言。
我们公司另一个项目 SOLL 可以帮助您将 Yul 编译成 EWASM。 (更多...)
(docker) $ cd ~/rust-ssvm && cargo run --example execute_vm -v -- -f=examples/fib.wasm
结果应该与以下内容相同。
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
如果您想查看 SSVM 内部的更多运行时信息,可以修改 rust-ssvm/SSVM/lib/support/log.cpp 如下。
void setErrorLoggingLevel() {
el::Loggers::addFlag(el::LoggingFlag::HierarchicalLogging);
- el::Loggers::setLoggingLevel(el::Level::Error);
+ el::Loggers::setLoggingLevel(el::Level::Debug);
}
EWASM 测试
请参考EWASM 测试指南获取更多详细信息。
许可证
Rust SSVM 采用双重许可证,包括AGPL 3.0 许可证和APACHE-2 许可证。
依赖
~1.2–3.5MB
~56K SLoC