FABRKNT
Reth Fundamentals — Alloy で動かす最初の一歩
EVM の中身を覗く
レッスン 7 / 11·QUIZ15 分30 XP
コース
Reth Fundamentals — Alloy で動かす最初の一歩
レッスンの役割
QUIZ
順序
7 / 11

クイズ — ミニEVMスタック

問い

EVM のスタック操作を Rust の Vec で再現 する。pop + push + wrapping arithmetic + unwrap_unchecked の安全パターン — Revm のホットパスでも同じ仕組みが使われている。

原理(最小モデル)

  • Vec::pop の戻り値は Option<T>. 空 → NoneSome(v) → 値取り出し、null チェックを型システムで強制。
  • EVM スタックリミット 1024. Revm に pub const STACK_LIMIT: usize = 1024;、超えると StackOverflow
  • EVM ADD は wrapping_add. mod 2²⁵⁶ wrap、saturating_addchecked_add はコンセンサス外、+ は debug/release で挙動分岐。
  • unwrap_unchecked() + unsafe. 直前で長さチェック済 → パニックパスがデッドコード → unwrap_unchecked でホットパスから消去、手動チェック後 unsafe で不変条件を符号化する最適化。
  • スタックマシン vs レジスタマシン. 命令セット小 + オペランドエンコード単純 = ZK 回路化 / 形式検証容易、レジスタコード並みの速度は出ない。

具体例 + ステップで組み立てる

クイズ:ミニEVMスタック

Rust で小さな EVM 風スタックを 3 操作だけで作ります:

  • push(n): スタックに数値を積む
  • add(): 上から2つ pop し、合計を push
  • peek(): 上の値を読むだけ(pop しない)

前レッスンで読んだ本物の Revm Stack と同じ形を、シンプル化のため U256 の代わりに i64 で作るだけである。

必要な要素

  • Vec<i64> をラップする struct
  • impl ブロックに new()push(&mut self, n)add(&mut self)peek(&self)
  • Vec::popVec::last の戻り値の型 — 空の Vec のとき Rust は何を返してくる?
  • underflow 処理:要素が 2 つ未満のとき add() はどうする?

EVM 仕様に忠実に、加算はオーバーフローで ラップアラウンド する(飽和もパニックもしない)。整数のメソッドで正しいものを探す。

自分で書いてみる

Rust Playground でスケルトンから始める:

struct MiniEvmStack {
    data: Vec<i64>,
}

impl MiniEvmStack {
    fn new() -> Self {
        Self { data: Vec::new() }
    }

    // TODO: push, add, peek
}

fn main() {
    let mut s = MiniEvmStack::new();
    s.push(100);
    s.push(200);
    s.add().unwrap();
    println!("{:?}", s.peek()); // 出力は Some(300) になるはず
}

ヒント:

  • Vec::popOption<T> を返す — 空のケースが戻り値の型に符号化されている
  • Vec::lastOption<&T> を返す — コピーではなく借用(安い)
  • add の戻り値は Result<(), &'static str> にすると、pop 呼び出しに .ok_or("stack underflow")? が付けられる
  • EVM 互換の加算は、名前に「wrap」を含む整数メソッド

動いたら、前のレッスンの本物の Revm Stack と頭の中で設計を比較してみてください — 同じ形のはず。

クイズ

まとめ(3行)

  • Vec::pop -> Option<T> で空チェック型強制、EVM スタックリミット 1024 = Revm STACK_LIMIT、ADD は wrapping_add(mod 2²⁵⁶)。
  • unwrap_unchecked + unsafe = 事前長さチェック後の最適化、ホットパスからパニックパス消去、手動チェック後 unsafe で不変条件符号化。
  • スタックマシンは命令セット小 + ZK / 検証容易 = レジスタコードに対するランタイム速度とのトレードオフ、次は async / トレイト / ジェネリクス。