Skip to content

dorname/mini-evm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mini-evm

mini-evm 是一个基于 Rust 的简单以太坊虚拟机(EVM)实现,旨在帮助个人学习和理解 EVM 的指令集与执行机制。本项目主要参考了 WTF Academy 的 Python 实现思路、evm.codes 的文档,并通过单元测试验证结果。

当前版本正在进行模块化重构,目标架构为 Interpreter + Host 分离模式,并面向 Shanghai 硬分叉 的 Gas 规则做合规对齐。


架构亮点 / Architecture Highlights

Interpreter + Host 模式

我们将 EVM 拆分为两个核心角色:

  • Interpreter (src/interpreter.rs):负责字节码的取指、译码、执行,管理 PC、Stack、Memory 与控制流。
  • Host (src/host.rs): trait 抽象层,定义所有状态访问接口(sloadsstorebalancecall 等)。

这种分离让执行引擎与底层状态解耦:

  • 单元测试可注入 MockHost(内存实现),无需真实数据库。
  • 未来对接链上数据时,只需实现 Host trait。
        ┌─────────────────┐
        │   Interpreter   │  ← 执行引擎:PC / Stack / Memory
        │  interpreter.rs │
        └────────┬────────┘
                 │ 调用 Host trait 方法
        ┌────────▼────────┐
        │  Host (trait)   │  ← 状态边界:账户、存储、调用
        │    host.rs      │
        └────────┬────────┘
                 │
      ┌──────────┴──────────┐
      │                     │
┌─────▼──────┐      ┌───────▼────────┐
│  MockHost  │      │  Journal       │
│(测试专用)   │      │(状态回滚日志)   │
└────────────┘      └────────────────┘

InstructionResult 统一控制流

所有 opcode handler(src/ops/handlers.rs)不再直接修改 Interpreter 内部状态,而是通过 InstructionResult 返回标准化信号:

  • Continue — 正常进入下一条指令
  • Stop — 执行结束(如 STOPRETURN
  • Revert — 回滚当前调用帧的所有状态变更
  • CallOrCreate — 需要进入新的子调用帧

Interpreter 的主循环根据该结果统一调度,避免控制流散落在各 opcode 实现中。

Journal 状态回滚

src/journal.rs 记录每一次状态修改(storage、balance、nonce),支持多层 checkpoint:

  • 子调用前打快照。
  • 成功则 commit;失败或 REVERT 则按日志逐条恢复。

这让 mini-evm 具备了与生产级客户端(如 revm、geth)一致的事务语义。

Shanghai Fork Gas 合规

当前实现针对 Shanghai 升级的关键 EIP 做了对齐:

EIP 内容 状态
EIP-2929 冷热访问列表:首次状态访问加收 cold cost,后续 warm access 仅 100 gas 部分实现
EIP-3529 降低 refund:上限从 gas_used/2 降至 gas_used/5;移除 SELFDESTRUCT refund 简化实现
EIP-3855 新增 PUSH0 指令,固定 2 gas 已实现
EIP-3860 Initcode 长度上限 49,152 字节,并加收 jumpdest-analysis 费用 未完整 enforcing

完整偏差列表请见 DEVIATIONS.md


快速开始 / Quick Start

环境要求

  • Rust >= 1.79

运行测试

# 运行全部单元测试
cargo test

# 运行指定测试(示例)
cargo test test_push

# 带日志输出调试
cargo test -- --nocapture

注意:项目使用 log4rs 做日志输出,运行前请确保根目录存在 log4rs.yaml

在 VS Code 中调试

本项目可直接在 VS Code 中通过 CodeLLDBrust-analyzer 插件进行断点调试。


项目结构

mini-evm
├── src/
│   ├── interpreter.rs      # 字节码执行引擎
│   ├── host.rs             # Host trait(状态访问抽象)
│   ├── mock_host.rs        # 内存实现的 Host,用于测试
│   ├── journal.rs          # 状态变更日志与 revert
│   ├── primitives.rs       # 基础类型(U256、Address 等)
│   ├── gas.rs              # Gas 计量(EIP-2929 / EIP-3529)
│   ├── ops/
│   │   ├── handlers.rs     # Opcode 实现
│   │   └── ...             # 其他 opcode 分类模块
│   ├── stack.rs            # EVM 栈实现
│   ├── transaction.rs      # 交易结构
│   └── ...
├── docs/
│   ├── ARCHITECTURE.md     # 架构说明(本文档)
│   └── DEVIATIONS.md       # 与主网规范的已知偏差
├── Cargo.toml
└── README.md

测试说明 / Testing

MockHost

MockHost 是一个纯内存的 Host 实现,内置若干预设账户(如 0x9bbfed6889322e016e0a02ee459d306fc19545d8),方便在无数据库环境下验证:

  • 合约间调用(CALLDELEGATECALLSTATICCALL
  • 存储读写(SLOADSSTORE)与冷热 gas 差异
  • 余额转账与 SELFDESTRUCT

Journal 测试

journal.rs 的测试模块中,我们构造了多层嵌套调用场景,验证:

  1. 子调用修改 storage 后 revert,父层状态保持不变。
  2. 跨层 balance transfer 在失败时全额回滚。
  3. Checkpoint 合并后,变更正确渗透到上层。

版本

Version Release Date Major Features Compatibility
0.1.0 2024-11-02 Initial implementation of basic EVM instructions Rust 1.79
0.2.0 (WIP) Interpreter+Host 重构、Journal 回滚、Shanghai Gas 对齐 Rust 1.79+

参考文档


其他

这个项目目前仍属我个人的 Rust 练手项目,除了帮助我学习 EVM 的指令集之外,也在帮助我熟悉 Rust。欢迎交流和提建议!

About

A simple evm implement based on rust.Only for personal studying opcodes. 本项目是evm大部分指令集的简单实现,当前仅用于个人学习和理解evm的指令集,目前仅为初版。

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages