cloud-sre
Polygon Erigon アーカイブノードが 87218600 ブロックで停止した問題を修正した記録
Polygon Erigon アーカイブノードが Chicago hardfork の有効化ブロックで deterministic な gas used mismatch を起こし、0xPolygon/erigon を v3.5.0 から v3.6.0 に上げて解消した調査メモ。
Polygon Mainnet の Erigon アーカイブノードが 87218600 ブロック付近で進まなくなった。
アーカイブノードの障害では、まずディスク、CPU、メモリ、peer 数、snapshot 破損を疑いがちだ。
しかし今回はそこに問題はなかった。
問題は、ノードが Polygon Chicago hardfork の有効化ブロックで deterministic に失敗していたことだった。
修正は、実行中の 0xPolygon/erigon を v3.5.0 から v3.6.0 に上げ、同じ /data ディレクトリを使ってコンテナを起動し直すことだった。
背景
ブロックチェーンノードは、ファイルのダウンロードだけで動いているわけではない。 各ブロックを自分で再実行し、その結果がネットワーク上で受け入れられている block header と一致するかを検証している。 そのため、CPU、メモリ、ディスク I/O が足りていても、ある特定のブロックで止まることがある。 ハードウェアではなく、そのブロックから有効になる新しいルールをクライアントが知らない可能性がある。
Polygon も他の EVM チェーンと同じように、hardfork によって実行ルールを変更する。 hardfork は、指定されたブロック高で有効になるプロトコルアップグレードだ。 その時点から gas pricing、precompile の挙動、Polygon 固有の system transaction の扱いなどが変わることがある。 クライアント binary がその新ルールを含んでいない場合、ネットワークと異なる結果を計算し、そのブロックを invalid と判断する。
今回の 87218600 は Polygon Mainnet の Chicago hardfork activation block だった。
実際に動いていたノードは古い v3.5.0 build だった。
hardfork 前のブロックは replay できたが、新ルールの境界で失敗した。
用語の説明
| 用語 | 意味 |
|---|---|
| Archive node | 過去の state を保持するノード。古い block、receipt、trace、contract state を調べられる。通常の pruned node より大きなストレージが必要。 |
| Erigon | Ethereum client の一つ。この記録の対象は Polygon ルールに対応した 0xPolygon/erigon。 |
| Bor mainnet | Polygon PoS mainnet の execution chain。Erigon では --chain=bor-mainnet で指定する。 |
| Hardfork | 特定のブロックから有効になるプロトコルルール変更。ノードはそのブロックに到達する前に対応バージョンへ上げる必要がある。 |
| Chicago hardfork | Polygon の hardfork の一つ。0xPolygon/erigon v3.6.0 release notes では Mainnet activation block が 87218600 とされている。 |
| Gas used | ブロック実行で消費された gas の合計。ノードはこれを再計算し、block header の値と比較する。 |
| StateSync | Polygon 固有の状態同期イベント。Polygon fork 付近の execution validation に影響する場合がある。 |
| Heimdall | Polygon の consensus/checkpoint layer。Erigon は --bor.heimdall=... で remote Heimdall に接続できる。 |
| Fork choice | どの chain head が有効かを決める処理。execution が block を invalid と判断すると、その block へ進めない。 |
| Datadir | Erigon が DB や snapshot を置くディレクトリ。今回は /data。 |
症状
ノードは最後の valid tip まで unwind し、同じ gas-used mismatch でクラッシュした。
gas used mismatch block=87218600 header=79467913 execution=62712118
Execution failed block=87218600
err="invalid block, txnIdx=186, gas used by execution: 62712118, in header: 79467913"
pos sync failed: unexpected bad block at finalized waypoint
このログでは、エラーメッセージとブロック番号をセットで見る。
ブロック番号 87218600 が手がかりだった。
この番号はランダムではない。
0xPolygon/erigon の v3.6.0 release notes には、Polygon Mainnet の Chicago activation block が 87218600 と書かれており、validators、RPC providers、node operators、infrastructure partners に対して hardfork 前のアップグレードを求めている [1]。
実務上の判断は次のようになる。
- ランダムなブロックで一度だけ失敗するなら、データ、peer、リソース問題の可能性がある。
- 同じ hardfork activation block で何度も失敗するなら、まず client version を疑う。
- 実際に動いている binary version を確認する前に、datadir を削除して再同期すべきではない。
除外したもの
このノードはすでにアーカイブノード向けの基盤調整を済ませていた。
| レイヤー | 状態 |
|---|---|
| Storage | 15TB クラスのデータボリューム、高 IOPS EBS に変更済み |
| Memory | 128GB クラスのホストへ変更済み |
| P2P | 再起動後に peer は復帰 |
| Heimdall | remote Heimdall scraper は継続して進行 |
| Snapshot data | 既存の /data は読めており、失敗ブロック直前まで replay 可能 |
再起動後、ノードはブロックを再取得して挿入できていた。
GoodPeers eth68=3
inserting fetched blocks start=87214502 end=87216293 blocks=1792
この状況は、ランダムなリソース不足や完全なネットワーク断とは違う。 毎回同じ hardfork 境界まで進み、同じ検証で失敗していた。
GitHub 上の類似 issue
0xPolygon/erigon には同系統の open issue があった。
- Issue
#143はbor-mainnetとv3.5.0-230b11a7で同じ gas mismatch pattern を報告し、StateSync gas handling を疑っている [2]。 - Issue
#133はpos sync failed: unexpected bad block at finalized waypointを報告している [3]。 - Issue
#100は古いバージョンで同じgas used by execution ... in header ...pattern を報告している [4]。
これらの issue だけで最終修正を証明できるわけではない。 ただし調査方針を変えるには十分だった。 これはディスクや peer の問題ではなく、client/fork rule mismatch に見えた。
決定的だったバージョン確認
実際に動いていたコンテナはまだ古い build だった。
Build info git_tag=v3.5.0-dirty git_commit=230b11a713...
v3.6.0 のソースを clone しても、実行中の binary は変わらない。
新しい Docker image を build し、その image でコンテナを起動していなければ、実行中の binary は変わらない。
確認に使ったコマンドは次の通り。
docker logs --tail 100 polygon-erigon | grep 'Build info'
docker images | grep polygon-erigon
修正前は local-v3.5.0 image しか存在していなかった。
修正
まず v3.6.0 image を build した。
docker stop polygon-erigon
rm -rf /opt/erigon-v3.6.0
git clone --branch v3.6.0 --single-branch https://github.com/0xPolygon/erigon.git /opt/erigon-v3.6.0
cd /opt/erigon-v3.6.0
DOCKER_BUILDKIT=1 docker build -t polygon-erigon:local-v3.6.0 .
次に古いコンテナを消し、同じ /data mount で新しいコンテナを起動した。
docker update --restart=no polygon-erigon
docker rm -f polygon-erigon
docker network create erigon-net 2>/dev/null || true
重要な変更は image だけだ。
polygon-erigon:local-v3.6.0
アーカイブデータは削除していない。 ノードは引き続き次の設定を使った。
--chain=bor-mainnet
--datadir=/data
--prune.mode=archive
--db.size.limit=12TB
--db.pagesize=16KB
--bor.heimdall=https://heimdall-api.polygon.technology
RPC を再び公開しないように、Docker の port publish は JSON-RPC と metrics を localhost に限定した。
-p 127.0.0.1:8545:8545
-p 127.0.0.1:6060:6060
これでローカル検証は維持しつつ、public RPC は閉じたままにできる。
検証
新しいコンテナでは期待通りの build が表示された。
Build info git_tag=v3.6.0-dirty git_commit=231d67e50b...
Initialised chain configuration ... Chicago: 87218600
起動直後には一時的な peer warning が出た。
can't use any peers to download blocks
No GoodPeers
これは一時的だった。 その後、peer が見つかり、block insertion が再開した。
GoodPeers eth68=3
inserting fetched blocks start=87214502 end=87216293 blocks=1792
検証ポイントは、以前失敗していたブロックを越えたかどうかだった。
blk=87218538
blk=87218647
blk=87218727
blk=87218801
これで v3.6.0 が 87218600 を越えたことを確認できた。
以前のエラーは再発していない。
gas used mismatch block=87218600
unexpected bad block
Execution failed
再利用できる runbook
Polygon Erigon で同種の障害に当たったら、次の順で見る。
- 失敗しているブロック番号を確認する。
- ソースディレクトリではなく、実行中 binary のバージョンを確認する。
- 失敗ブロックと Polygon hardfork activation block を照合する。
- 上流 issue で同じエラー文字列を検索する。
- hardfork rule を含む release へ上げる。
- 上流が DB format 変更を明示していない限り、既存 datadir は消さない。
- 失敗していた正確なブロックを越えたか確認する。
特に有用だったコマンドは次の 2 つ。
docker logs --tail 100 polygon-erigon | grep 'Build info'
そして:
docker logs --since 15m polygon-erigon | \
grep -E 'gas used mismatch|unexpected bad block|Execution failed|polygon.sync.*crashed'
前者は実際の実行バージョンを確認する。 後者は旧エラーがまだ出ているか確認する。
学び
この障害は最初、性能問題に見えた。 すでにストレージやインスタンスサイズの調整を行っていたからだ。 しかし、性能調整では hardfork rule mismatch は直せない。
ブロックチェーンノードが同じブロックで deterministic に止まる場合、特にそれが既知の hardfork activation block であれば、client version を最初から確認対象に入れる。
References
- 0xPolygon/erigon v3.6.0 release notes
- 0xPolygon/erigon issue #143: Block 76879430 - same gas mismatch pattern
- 0xPolygon/erigon issue #133: pos sync failed: unexpected bad block at finalized waypoint
- 0xPolygon/erigon issue #100: gas used by execution mismatch
- Polygon documentation: Erigon archive node