レッスン5 — 本物の Network トレイト + Ethereum / Optimism 実装を読む
問い
10 関連型 + トレイト境界を組み立ててきた。本物のソースで関連型ごとのトレイト境界、alloy の Ethereum 実装、Optimism 実装の並列比較、TransactionBuilder ヘルパートレイトを確認。一貫性の性質は具体的にどう働くか?
原理(最小モデル)
Network自身の境界 6 種.Debug + Clone + Copy + Send + Sync + Sized + 'static。Copy = ゼロサイズマーカー型として値で気軽渡し。- マーカー struct パターン.
struct Ethereum;は 1 バイト(Copy 可能)。チェーン設定(chain_id / hardfork)は別の場所、Network は「型ファミリの選択」のみ。 TxType: Into<u8> + TryFrom<u8>. EIP-2718 型付きエンベロープ仕様、高位 enum とワイヤ 1 バイトのマッピング。Optimism の0x7E(Deposit) で拡張。type TxEnvelope: TransactionEnvelope<Self>. 関連型ごしに揃ったヘルパートレイト、Self でパラメータ化。- Ethereum 実装.
alloy_consensus(コンセンサス形)+alloy_rpc_types_eth(RPC 形)の 2 クレートにまたがる。クレート境界 = 概念境界。 - Optimism は 10 中 8 がオーバーライド. Tx 5 スロット + Receipt 2 スロット + BlockResponse がオーバーライド、Header と HeaderResponse のみ共有。
TransactionBuilder<N>ヘルパートレイト. 流暢な.with_to(addr).with_value(eth(1))を chain-agnostic に。AnyNetwork= 寛容な逃げ道. 任意フィールド受け入れる serde 風型、ブロックエクスプローラ / マルチチェーンインデクサ向け。
具体例
トレイト全境界:
pub trait Network: Debug + Clone + Copy + Send + Sync + Sized + 'static {
// トランザクション側
type TxType: Into<u8> + PartialEq + Eq + TryFrom<u8> + Send + Sync + 'static;
type TxEnvelope: TransactionEnvelope<Self> + ...;
type UnsignedTx: From<Self::TxEnvelope> + ...;
type TransactionRequest: TransactionBuilder<Self> + ...;
type TransactionResponse: Transaction<Self> + ...;
// レシート側
type ReceiptEnvelope: ReceiptEnvelope<Self> + ...;
type ReceiptResponse: ReceiptResponse + ...;
// ヘッダー / ブロック側
type Header: BlockHeader + ...;
type HeaderResponse: HeaderResponse + ...;
type BlockResponse: BlockResponse<Self> + ...;
}
Ethereum 実装:
#[derive(Debug, Clone, Copy)]
pub struct Ethereum;
impl Network for Ethereum {
type TxType = alloy_consensus::TxType;
type TxEnvelope = alloy_consensus::TxEnvelope;
type UnsignedTx = alloy_consensus::TypedTransaction;
type ReceiptEnvelope = alloy_consensus::ReceiptEnvelope;
type Header = alloy_consensus::Header;
type TransactionRequest = alloy_rpc_types_eth::TransactionRequest;
type TransactionResponse = alloy_rpc_types_eth::Transaction;
type ReceiptResponse = alloy_rpc_types_eth::TransactionReceipt;
type HeaderResponse = alloy_rpc_types_eth::Header;
type BlockResponse = alloy_rpc_types_eth::Block;
}
注目点 2 つ:
- クレート境界 = 概念境界: コンセンサス形(
alloy-consensus)vs RPC 形(alloy-rpc-types-eth) UnsignedTx = TypedTransaction: EIP-2718 型付き tx バリアントのいずれか、完全埋まり署名直前
Optimism 実装:
#[derive(Debug, Clone, Copy)]
pub struct Optimism;
impl Network for Optimism {
type TxType = op_alloy_consensus::OpTxType; // ← 異なる (Deposit 追加)
type TxEnvelope = op_alloy_consensus::OpTxEnvelope; // ← 異なる
type UnsignedTx = op_alloy_consensus::OpTypedTransaction; // ← 異なる
type ReceiptEnvelope = op_alloy_consensus::OpReceiptEnvelope; // ← 異なる (l1_fee フィールド)
type Header = alloy_consensus::Header; // ← Ethereum から再利用
type HeaderResponse = alloy_rpc_types_eth::Header; // ← 再利用
type TransactionRequest = op_alloy_rpc_types::TransactionRequest; // ← 異なる (mint フィールド)
type TransactionResponse = op_alloy_rpc_types::Transaction; // ← 異なる
type ReceiptResponse = op_alloy_rpc_types::OpTransactionReceipt; // ← 異なる
type BlockResponse = op_alloy_rpc_types::Block; // ← 異なる (OP tx を運ぶ)
}
10 スロット中 8 がオーバーライド、2 が共有:
- 5 Tx 関連スロット(TxType、TxEnvelope、UnsignedTx、TransactionRequest、TransactionResponse)すべて違う = Optimism deposit-tx バリアントが波及
- 2 Receipt 関連(ReceiptEnvelope、ReceiptResponse)違う = L1 ガス / L1 ブロック フィールド波及
- Header と HeaderResponse 共有 = OP は コンセンサスヘッダレベルで EVM 互換
- BlockResponse 違う = ブロックの tx リストに OP 型が含まれる
TransactionBuilder<N> ヘルパートレイト:
pub trait TransactionBuilder<N: Network>: ... {
fn input(&self) -> Option<&Bytes>;
fn set_input(&mut self, input: Bytes);
fn with_input(mut self, input: Bytes) -> Self { ... }
fn from(&self) -> Option<Address>;
fn set_from(&mut self, from: Address);
fn with_from(mut self, from: Address) -> Self { ... }
fn to(&self) -> Option<Address>;
fn set_to(&mut self, to: Address);
fn with_to(mut self, to: Address) -> Self { ... }
// ...with_value、with_gas_price、with_chain_id、with_nonce 等
}
chain-agnostic ジェネリック関数:
fn build_request<N: Network>() -> N::TransactionRequest {
<N::TransactionRequest>::default()
.with_to(Address::ZERO)
.with_value(U256::from(1_000))
}
Ethereum / Optimism / AnyNetwork / カスタム L2 すべてで動く。
AnyNetwork(寛容な逃げ道):
impl Network for AnyNetwork {
type TxType = WithOtherFields<...>;
type TxEnvelope = AnyTxEnvelope;
type TransactionResponse = AnyRpcTransaction;
// ...
}
ブロックエクスプローラ / マルチチェーンインデクサ / 汎用 RPC プロキシ向け。代償 = チェーン固有フィールドの静的型付けを失い、.other() で取り出し。
失敗例(誤解)
「Network はチェーン設定 struct」— 間違い。ゼロサイズマーカー型、チェーン設定(chain_id / hardfork)は別の場所。Network の問いは「どの型ファミリ を使うか」 — 静的・型レベル。
「Optimism は Ethereum 型を全部オーバーライド」— 間違い。10 中 8 オーバーライド、Header と HeaderResponse は 共有(OP コンセンサスヘッダレベルで EVM 互換)。一貫性の性質が共有を許す。
「TransactionBuilder メソッドを関連型に直接置く」— 間違い。別トレイトにすることで N 上ジェネリック関数が書ける(Ethereum / Optimism / AnyNetwork 横断で動く)、メソッドを関連型に置くと chain-agnostic コード書けない。
ステップで組み立てる
Step 1: Network 自身の 6 境界
Debug + Clone + Copy + Send + Sync + Sized + 'static。Copy = ゼロサイズマーカー型。
Step 2: TxType: Into<u8> + TryFrom<u8>
EIP-2718 wire-byte ↔ enum mapping、Optimism 0x7E で拡張。
Step 3: 関連型ごしのヘルパートレイト
type TxEnvelope: TransactionEnvelope<Self> パターン、Self でパラメータ化、chain-agnostic ヘルパー。
Step 4: Ethereum 実装の 2 クレート構造
alloy-consensus + alloy-rpc-types-eth = コンセンサス vs RPC の概念境界。
Step 5: Optimism vs Ethereum を 10 スロット並列比較
8 オーバーライド + 2 共有(Header / HeaderResponse)。
Step 6: TransactionBuilder<N> 別トレイトの利点
chain-agnostic ジェネリック関数書ける。
Step 7: AnyNetwork の使い分け
アプリ = 具体的 Network(Ethereum / Optimism)/ ツール = AnyNetwork。
答え合わせ
NetworkがCopyを要求する理由: ゼロサイズマーカー型(struct Ethereum;は 1 バイト or 0)→ ライフタイムを気にせず値で気軽渡し可能。Clone だけだと借用が必要、Copy で関数引数 / フィールドに直接書ける。- Header が共有で BlockResponse が違う理由: Optimism コンセンサスヘッダは EVM 互換(同じ Merkle ルート構造)→ Header / HeaderResponse 共有 OK。BlockResponse は ブロックの tx リストに OP 型が含まれる → Ethereum の
Blockを再利用すると OP deposit が Ethereum 型 tx として誤シリアライズ → 別物必須。tx リスト含むものは波及、ヘッダレベルは共有可能。 TransactionBuilderが別トレイトである利点: 同じビルダーメソッドが Ethereum / Optimism / カスタム L2 で動く + N 上ジェネリック関数(fn build_request<N: Network>() -> N::TransactionRequest)が書ける = 型レベル辞書 + ヘルパートレイト = チェーン横断で移植可能なコード。
合格基準
- Network 6 境界(Debug + Clone + Copy + Send + Sync + Sized + 'static)を即答できる。
- マーカー struct パターンと Copy の意味を 1 文で説明できる。
- Ethereum 実装の 2 クレート構造を言える。
- Optimism vs Ethereum の 10 スロット並列比較(8 違 + 2 同)を即答できる。
TransactionBuilder<N>別トレイトの利点を 1 文で説明できる。AnyNetworkを使う場面を言える。
まとめ(3行)
Network全境界Debug + Clone + Copy + Send + Sync + Sized + 'static、関連型ごしのヘルパートレイト(type TxEnvelope: TransactionEnvelope<Self>)+ TxType の EIP-2718 マッピング。- Ethereum vs Optimism 並列 = 10 中 8 オーバーライド + 2 共有(Header / HeaderResponse)、コンセンサス(
alloy-consensus)と RPC(alloy-rpc-types-eth)のクレート境界 = 概念境界。 TransactionBuilder<N>別トレイト = chain-agnostic ジェネリック関数、AnyNetwork= 任意チェーン扱うツール向けの寛容な逃げ道。