Lighthouseノードが自分の公開アドレスを自動的に認識する仕組み

例えば一般的なネット環境下にあるラップトップでLighthouseノードを起動した場合、NATの背後でノードが稼働することになる。この場合、ノードは自力で自分の公開IPアドレス/ポートを知ることは難しい。また、インターネットプロバイダの都合により稼働中に公開アドレスが変更になる可能もある。

Lighthouseには公開IPアドレス/ポートを自動的に認識する仕組みがあるので、どのようにして実現されているのか調べた。

まず前提知識としていくつかおさらいしておく。

ENR (Ethereum Node Records)

Ethereumのコンセンサスクライアント(旧称: Eth2クライアント)は、ノードの接続情報等を Ethereum Node Records という形式で表現する。これに IPアドレス、ポート番号やチェーンの情報等を含めて ノード間で交換している。

ただし上記のENRの仕様に記載されているとおり、IPアドレスやポート番号は「任意」のフィールドである。

Node Discovery Protocol v5

Ethereumのコンセンサスクライアントは、Node Discovery Protocol v5 というプロトコルを利用してノードディスカバリを行っている。Lighthouseでは、このプロトコルのRust実装である sigp/discv5 を利用している。

後に説明する仕組みは、このプロトコルで規定されている PONGレスポンス に含まれる recipient-iprecipient-port と、 sigp/discv5 に実装されている IpVote によって実現されている。

なお、現時点の Node Discovery Protocol v5 の仕様を見る限りでは IpVote は規定されていない。なので sigp/discv5 が独自に実装しているのかもしれない。他のコンセンサスクライアントにも同じような実装があるかもしれないが調べていない。

公開アドレスを認識する仕組み

文章でまとめるのが難しかったためシーケンス図に整理したので参照されたい。

補足:下図のノードAとノードBが直接通信できるかどうかは、NAT超えの課題があるので、まだ別の問題になる。

lighthouse-behind-nat.png

2022-07-28 追記

関連するトピックとして、NAT越えのための Rendezvous protocol というのが議論されて いて、まだ仕様は固まっていないが先んじて sigp/discv5 で実装が進められている