はじめに
『DApps開発入門』という本や色々記事を書いているかるでねです。
以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください!
今回は「EIP7949」についてまとめていきます。
Ethereumネットワークを起動する時に必要なgenesis.jsonファイルの構造を標準化するための提案です。
これまで事実上の標準(Gethの実装)はありましたが、公式な仕様書がなかったことで、クライアント間の非互換性や混乱が生じていました。
genesis.jsonとは
Ethereumネットワークの起動ファイル
Ethereumノードを立ち上げる時、そのネットワークがどんな設定から始まるかを定義するファイルがgenesis.jsonです。
メインネットを動かすノードでは既定の設定が使われますが、テストネットやプライベートネットを自分で立ち上げる時には、このファイルを用意して渡す必要があります。
genesis.jsonには以下のような情報が含まれています。
- どのチェーンIDで動作するか(メインネット・テストネット・プライベートネットの区別)
- 各ハードフォークをどのブロック高またはタイムスタンプで有効化するか
- ネットワーク開始時点でどのアドレスにETHやコードを事前配置するか
- ブロックのガスリミットや難易度などの初期パラメータ
現状の課題
このファイルはEthereumネットワークを動かすうえで必須ですが、これまで公式な仕様書が存在しませんでした。
事実上の標準として機能していたのはGeth(Go-Ethereum)の実装で、他のクライアント(Besu、Nethermindなど)もこれに倣ってきました。
しかし「Gethの実装を見て推測する」状態では、以下のような問題が起きます。
- クライアントによってフィールドの解釈が微妙に異なる
- テストネットを複数クライアントで動かす際に設定ミスが発生する
- 新しいフォークやパラメータを追加するEIPが、基礎の仕様を参照できない
EIP7949はこの「根本となる設定仕様が未定義」という問題を解決するために提案されました。
EIP7949の概要
提案の目的
EIP7949の目標は、genesis.jsonのCanonical(正規)な構造をJSON Schemaとして定義することです。
この提案自体はInformational(情報提供型)のEIPです。新しい機能を追加したり、既存の動作を変えたりするものではなく、すでにGethで動いている実装をドキュメント化・標準化することが主眼です。
具体的には以下を達成しようとしています。
- 各フィールドの型・意味・形式を明確に定義する
- JSON Schemaでバリデーション可能にする
- 後続のEIP(ジェネシス設定を変更するもの)が参照できる基盤を作る
関連するEIPとの関係
この提案が「基礎仕様」として位置づけられているのには理由があります。
近年、ジェネシス設定を変更するEIPがいくつか提案されています。
以下の図はEIP7949と関連するEIPの関係を示しています。
EIP7840・EIP7892・EIP7910はいずれもgenesis.jsonの構造を変更・拡張する提案です。GethのデファクトスタンダードをベースにしたEIP7949が定義されることで、これらが共通の仕様を参照できるようになります。
これらはすべて「ジェネシス設定の何かを変える」提案ですが、その変更対象であるgenesis.jsonの構造が未定義のままでは、変更内容を正確に記述できません。
EIP7949はそうした提案が参照できる土台を作ることで、Ethereumの仕様整備を進める役割を担っています。
仕様
トップレベルフィールド
genesis.jsonはJSONオブジェクトで、以下のトップレベルフィールドを持ちます。
| フィールド | 型 | 説明 | 例 |
|---|---|---|---|
config |
Object | チェーン設定オブジェクト | 後述 |
alloc |
Object | 事前配置するアドレスと残高・コードのマップ | 後述 |
nonce |
String | ブロックnonce(16進数文字列) | 0x0 |
timestamp |
String | UNIXタイムスタンプ(16進数文字列) | 0x6720f180 |
extraData |
String | 任意の追加データ(16進数文字列) | 0x00 |
gasLimit |
String | ブロックのガスリミット(16進数文字列) | 0x1c9c380 |
difficulty |
String | ブロック難易度(16進数文字列) | 0x1 |
mixhash |
String | Mixハッシュ(16進数文字列) | 0x000...000 |
coinbase |
String | Coinbaseアドレス(16進数文字列) | 0x000...000 |
数値を16進数文字列で表現している点が特徴的です。これはEthereumのRLP(Recursive Length Prefix)エンコードと整合するためで、0xプレフィックスで始まる形式が標準です。
以下の図はgenesis.jsonのフィールド構造全体を示しています。
genesis.jsonはトップレベルにconfigとallocという2つの主要オブジェクトを持ち、その下にそれぞれのフィールドが展開されます。オレンジ色のフィールドはハードフォークと連動して変化する動的な設定です。
configオブジェクト
configフィールドはハードフォークの有効化タイミングとチェーン固有の設定を保持します。
| フィールド | 型 | 説明 | 例 |
|---|---|---|---|
chainId |
Integer | チェーンを識別する一意のID(10進整数) |
1(メインネット) |
<hardfork名>Block / <hardfork名>Time
|
Integer | ハードフォークを有効化するブロック高またはタイムスタンプ(10進整数) | shanghaiTime: 1681338455 |
terminalTotalDifficulty |
String | PoWからPoSへ切り替わる総難易度(16進数文字列) | 0xc70d815d562d3cfa955 |
depositContractAddress |
String | デポジットコントラクトのアドレス | 0x00000000219ab540356cBB839Cbe05303d7705Fa |
blobSchedule |
Object | ハードフォークごとのBlob設定 | 後述 |
ハードフォークの有効化タイミングには2種類の指定方法があります。
Merge以前のフォーク(Homestead、Berlinなど)はブロック高(xxxBlock)で、Merge以降のフォーク(Shanghai、Cancunなど)はUnixタイムスタンプ(xxxTime)で指定します。
これはEthereumがPoW(ブロック高が増加)からPoS(時刻ベースのスロット)に移行したことを反映しています。
blobScheduleオブジェクト
EIP4844で導入されたBlobトランザクション(大容量データを安価に送受信する仕組み)のパラメータを、ハードフォークごとに設定するオブジェクトです。
EIP4844(Proto-Danksharding)は、Blob(Binary Large Object)と呼ばれる大きなデータ領域を持つ特殊なトランザクション形式を導入したアップグレードです。
L2(レイヤー2チェーン)がロールアップのデータをEthereumに書き込む時のコストを大幅に削減しました。Cancunアップグレード(2024年3月)で本番導入されています。
| フィールド | 型 | 説明 | 例 |
|---|---|---|---|
target |
Integer | 1ブロックに含める目標Blob数(10進整数) | 3 |
max |
Integer | 1ブロックに含める最大Blob数(10進整数) | 6 |
baseFeeUpdateFraction |
Integer | Blob基本手数料の調整に使う係数(10進整数) | 3338477 |
これらの値はハードフォーク名をキーとするオブジェクトで指定します。たとえば以下のような形式になります。
"blobSchedule": {
"cancun": {
"target": 3,
"max": 6,
"baseFeeUpdateFraction": 3338477
},
"prague": {
"target": 6,
"max": 9,
"baseFeeUpdateFraction": 5007716
}
}
ハードフォークごとに値を変えられるため、Blobの許容量を段階的に引き上げるロードマップ(Danksharding)に対応できる設計になっています。
allocオブジェクト
allocフィールドはネットワーク起動時点での初期状態を定義します。
アドレス(16進数文字列)をキーとして、そのアドレスに事前配置する内容をマッピングします。
| フィールド | 型 | 説明 | 例 |
|---|---|---|---|
balance |
String | 残高(weiの16進数文字列) |
0xde0b6b3a7640000(1 ETH) |
code |
String | EVMバイトコード(16進数文字列) | 0x6060604052... |
nonce |
String | アカウントnonce(16進数文字列) | 0x0 |
storage |
Object | ストレージスロットのキー・バリューマップ | 32バイト16進数文字列のペア |
allocが特に重要になるのはプリコンパイル済みコントラクト(ecrecoverなどのネイティブ実装)やシステムコントラクト(デポジットコントラクトなど)の事前配置です。
Ethereumメインネットやテストネットでは、これらが起動時点から存在している必要があり、allocでコードや残高を設定します。
JSON Schema
この提案の中核となるのがJSON Schemaです。スキーマを使うことで、genesis.jsonの構造をプログラムで自動検証できるようになります。
以下がEIP7949で定義されたスキーマです。
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$defs": {
"hexUint": {
"type": "string",
"pattern": "^0x[0-9a-fA-F]+$"
},
"address": {
"type": "string",
"pattern": "^0x[0-9a-fA-F]{40}$"
},
"hash": {
"type": "string",
"pattern": "^0x[0-9a-f]{64}$"
}
},
"title": "Ethereum Genesis File",
"type": "object",
"required": ["alloc", "gasLimit", "difficulty"],
"properties": {
"config": {
"type": "object",
"properties": {
"chainId": { "type": "integer" },
"homesteadBlock": { "type": "integer" },
"daoForkBlock": { "type": "integer" },
"eip150Block": { "type": "integer" },
"tangerineWhistleBlock": { "type": "integer" },
"eip155Block": { "type": "integer" },
"spuriousDragonBlock": { "type": "integer" },
"byzantiumBlock": { "type": "integer" },
"constantinopleBlock": { "type": "integer" },
"petersburgBlock": { "type": "integer" },
"istanbulBlock": { "type": "integer" },
"muirGlacierBlock": { "type": "integer" },
"berlinBlock": { "type": "integer" },
"londonBlock": { "type": "integer" },
"arrowGlacierBlock": { "type": "integer" },
"grayGlacierBlock": { "type": "integer" },
"terminalTotalDifficulty": { "$ref": "#/$defs/hexUint" },
"mergeNetsplitBlock": { "type": "integer" },
"shanghaiTime": { "type": "integer" },
"cancunTime": { "type": "integer" },
"pragueTime": { "type": "integer" },
"osakaTime": { "type": "integer" },
"depositContractAddress": { "$ref": "#/$defs/address" },
"blobSchedule": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"target": { "type": "integer" },
"max": { "type": "integer" },
"baseFeeUpdateFraction": { "type": "integer" }
}
}
}
},
"additionalProperties": true
},
"nonce": { "$ref": "#/$defs/hexUint" },
"timestamp": { "$ref": "#/$defs/hexUint" },
"extraData": {
"anyOf": [
{ "type": "string", "const": "" },
{ "type": "string", "pattern": "^0x([0-9a-fA-F]{2})*$" }
]
},
"gasLimit": { "$ref": "#/$defs/hexUint" },
"difficulty": { "$ref": "#/$defs/hexUint" },
"mixhash": { "$ref": "#/$defs/hash" },
"coinbase": { "$ref": "#/$defs/address" },
"alloc": {
"type": "object",
"patternProperties": {
"^0x[0-9a-fA-F]{40}$": {
"type": "object",
"properties": {
"balance": { "$ref": "#/$defs/hexUint" },
"nonce": { "$ref": "#/$defs/hexUint" },
"code": { "type": "string", "pattern": "^0x([0-9a-f])*$" },
"storage": {
"type": "object",
"patternProperties": {
"^0x[0-9a-f]{64}$": {
"$ref": "#/$defs/hash"
}
}
}
}
},
"additionalProperties": false
},
"additionalProperties": false
}
},
"additionalProperties": true
}
スキーマの設計で注目すべき点がいくつかあります。
まず$defsで再利用可能な型を3つ定義しています。hexUintは0xから始まる16進数文字列、addressは40文字の16進数アドレス、hashは64文字の16進数ハッシュです。これらをスキーマ各所で$ref参照することで、同じパターンを何度も書かずに済む構造になっています。
次にrequiredフィールドはalloc・gasLimit・difficultyの3つだけです。他のフィールドはオプションで、additionalProperties: trueを指定しています。これは将来のハードフォークで新しいフィールドが追加されても、スキーマを更新しなくてもバリデーションが通るようにするための設計判断です。
allocのパターン定義も興味深い構造です。キーはアドレス形式の正規表現でマッチングし、値にはbalance・code・nonce・storageを持てるようにしています。alloc直下にadditionalProperties: falseが指定されており、アドレス形式でないキーを持つことを禁止しています。
設計方針
なぜGethの実装を基準にしたか
このスキーマはGethが長年使ってきたフォーマットを定式化したものです。
新しい形式を設計して既存の実装を置き換えるのではなく、すでに動いている実装を標準として文書化するアプローチが取られています。
これには実用上の理由があります。Gethはシェアが高く、テストネットツール(Kurtosis、Assertoor等)もGeth互換のgenesis.jsonを前提に作られています。
新形式を定義してもエコシステム全体の移行コストが大きいため、既存フォーマットをそのまま仕様として採用するのが現実的な判断です。
また、この提案はあくまで「今ある実装の文書化」であって、すべてのクライアントが完全に準拠することを強制するものではありません。
additionalProperties: trueでクライアント固有の拡張を許容しているのも、このスタンスを反映しています。
後続EIPの基盤として
もう一つの重要な設計意図は「参照できる仕様書を作ること」です。
EIP7840(BlobスケジュールをEL設定ファイルに追加)やEIP7892(Blobパラメータのみを変更するフォーク)など、ジェネシス設定を変更する提案が増えています。
これらのEIPはそれまで「変更対象の構造が未定義のまま変更を記述する」という状態でした。
EIP7949が正式に採用されれば、後続のEIPは「EIP7949のスキーマを拡張する」「EIP7949のblobScheduleに新しいフィールドを追加する」という形で正確な変更内容を記述できるようになります。
セキュリティの考慮事項
EIP7949はInformational(情報提供型)の提案であり、新しい機能を追加するものではありません。
また、genesis.jsonを操作できるのはノードへの管理者アクセスを持つオペレータに限られます。
そのため、この提案自体が新たなセキュリティリスクを生み出すことはなく、セキュリティ上の考慮事項は特にないとされています。
実務的な観点では、genesis.jsonのallocフィールドは初期配置するコードやETHを定義するため、プライベートネットやテストネットの設定ミスには注意が必要です。
ただしこれはJSON Schemaのバリデーションがあることで、型エラーや形式ミスを事前に検出できるようになり、むしろ安全性が向上する方向です。
最後に
今回は「EIP7949」についてまとめてきました。
genesis.jsonの標準化は地味に見えますが、テストネットやL2チェーンを複数クライアントで安定して動かすうえで重要な基盤整備です。
特に、EIP7840やEIP7892など今後のジェネシス関連EIPが「参照できる仕様書がある」状態になることで、仕様の記述精度が高まり、クライアント間の互換性維持がしやすくなります。
他でも色々記事を書いているのでぜひよろしければ読んでいってください!

