レッスン6 — カスタム Opcode を配線する — そして失敗モード
問い
Hyperliquid は perp 用オーダーブック専用 Opcode を追加 — 200 命令の Solidity 関数が 1 バイトのネイティブディスパッチに。配線は 3 行、ショートカットは 100 倍ガス削減。それでも大半のチェーンが 50 個出さない理由は? オプションではない 3 注意点。
原理(最小モデル)
- メカニクス 3 行. 未割当バイト選択 +
standard_tableをコピー + 1 スロット上書き = 配線完了、関数は前レッスンのaddと同形。 - 複利的勝ち 2 つ. ① 内部ステップごとのインタープリターループ オーバーヘッドなし、② Rust 側で SIMD / FFI / 事前計算テーブル利用可能。
- 実利の桁. 複雑オプションプライサ = Solidity 500K ガス → カスタム Opcode 5K ガス(100 倍)。
- 注意点 1: コンセンサス互換性. 標準 EVM から外れる → メインネットとブロック共有不可、自前チェーン限定。
- 注意点 2: ガス価格. 強力ショートカットには適切ガス、誤価格 = DoS ベクター、方法論 = 最悪ケースベンチ + ガス予算変換 + 安全マージン 2-3 倍。
- 注意点 3: 検証性 (ZK). 新 Opcode の zkVM 統合 = Opcode あたり数週間の追加作業、暗号演算はさらに重い。
- 正しい数. 各 Opcode はコンセンサスリスク + 価格リスク + 検証コスト = 大半のチェーンの正解は 0-3 個。
具体例
メカニクス:
const HYPER_FAST_SWAP: u8 = 0x0C;
let mut table = standard_table();
table[HYPER_FAST_SWAP as usize] = Instruction::new(my_hyper_fast_swap);
関数は add と同形:
pub fn my_hyper_fast_swap<IT: ITy, H: ?Sized>(context: Ictx<'_, H, IT>) -> Result {
popn_top!([amount_in, pool_id], amount_out, context.interpreter);
*amount_out = compute_swap_native(*amount_in, *pool_id);
Ok(())
}
フロー:
flowchart LR
Std[standard_table — 256スロット] -->|複製| Mine[フォーク用テーブル]
Mine -->|0x0C を上書き| Custom[my_hyper_fast_swap]
Bytecode[bytecode 0x0C ...] -->|interpreter dispatch| Mine
Mine --> Custom
Custom --> Result[結果がスタックへ]
ガス価格方法論 3 文:
- 最悪ケースをベンチ — 病的入力(最大 pool ID、最大 amount)で実時間測定
- ガス予算に変換 — スループット目標を最悪時間で割る
- 安全マージン 2-3 倍 — 分散・将来のハードウェア変化・あなたのベンチ vs 攻撃者のベンチギャップ
失敗例(誤解)
「Revm がモジュラーだからカスタム Opcode は無料」— 間違い。各 Opcode = コンセンサスリスク + 価格リスク + 検証コスト、大半のチェーンの正解は 0-3 個。
「自前チェーンならコンセンサス互換性を無視できる」— そのとおりだが代償。メインネットとブロック共有不可 = go-ethereum とピア不可能、0x0C を触る最初の tx で state-root 不一致 → ピア切断。
「ガス価格は試行錯誤で決められる」— 致命的。誤価格 = DoS ベクター、攻撃者が病的入力を低ガスで実行 = ノードリソース枯渇。3 文の方法論なしにリリースしない。
ステップで組み立てる
Step 1: 未割当バイト選択
crates/interpreter/src/instructions.rs で代入の左辺に出現しないバイト = 未割当。
Step 2: 関数を add 同形で書く
<IT: ITy, H: ?Sized> + popn_top! + その場書き込み。
Step 3: standard_table をコピーして 1 スロット上書き
table[BYTE as usize] = Instruction::new(my_fn); = 配線完了。
Step 4: 注意点 1 (コンセンサス) を理解
自前チェーン限定、メインネット非互換、ブロック共有不可。
Step 5: 注意点 2 (ガス価格) の 3 文方法論
最悪ケースベンチ + ガス予算変換 + 安全マージン 2-3 倍。
Step 6: 注意点 3 (検証性) で ZK ロードマップ確認
zkVM 統合 = Opcode あたり数週間、暗号演算はさらに重い。
答え合わせ
- メカニクスが 3 行で済む構造的理由: 命令テーブルが 既にディスパッチを抽象化済み(前レッスン)= 1 スロット上書きで配線完了、関数自体は
addと同形(<IT: ITy, H: ?Sized>+popn_top!+ その場書き込み)。テーブル設計の合成性が「ディスパッチに触れずに Opcode 追加」を可能にする。 - 100 倍ガス削減の根拠: 複雑 Solidity 関数 200 EVM 命令 = 200 ディスパッチ + 200
gas!+ スタック移動、カスタム Opcode 1 = 1 ディスパッチ + Rust ネイティブコード(SIMD / FFI / 事前計算テーブル可)。Solidity 500K ガス → カスタム 5K ガス。 - 大半のチェーンの正解が 0-3 個の理由: 各 Opcode = 3 コスト(コンセンサスリスク = 実装バグごとにフォーク、価格リスク = 誤価格で DoS、検証コスト = zkVM 統合に数週間)。利益(100 倍ガス削減)と費用(数週間 × 3 リスク領域)のバランスで、ホットパスに集中する 0-3 個が大半のチェーンの最適。
合格基準
- メカニクス 3 行(バイト選択 + テーブルコピー + スロット上書き)を即書ける。
- 関数が
add同形である理由を即答できる。 - 注意点 3 つ(コンセンサス互換性 + ガス価格 + 検証性)を即答できる。
- ガス価格 3 文方法論(最悪ケースベンチ + 予算変換 + 安全マージン)を即答できる。
- 大半のチェーンの正解が 0-3 個の理由を 1 文で説明できる。
まとめ(3行)
- カスタム Opcode 配線 = 3 行(未割当バイト + テーブルコピー + スロット上書き)、関数は
add同形(<IT: ITy, H: ?Sized>+popn_top!)、Solidity 500K → カスタム 5K ガス(100 倍削減)。 - 注意点 3 = コンセンサス互換性(自前チェーン限定)+ ガス価格(DoS 防止の方法論必須)+ 検証性(zkVM 統合 Opcode あたり数週間)。
- 大半のチェーンの正解 = 0-3 個、各 Opcode の 3 コスト(リスク + 価格 + 検証)がホットパスに集中させる、次レッスンでクイズ + ドリルでフォーク出荷。