Bitcoinのノードは、接続しているリモートピアにgetaddr
メッセージを送信すると、リモートピアが知っているノード情報をaddr
メッセージで返してくれ、addr
メッセージによって、ネットワーク上の分散ピアが発見できる。
このaddr
メッセージでは、各ノードのネットワークアドレスを128 bitのIPアドレスとして表現している。ただ、最近Tor v3 hidden serviceなどのアドレスはこの範囲に収まらないアドレスも出てきており、I2Pなどより多様なネットワークの接続をサポートするため、128 bitよりも大きなアドレス表現をサポートできる新しいaddr
メッセージとしてaddrv2
メッセージがBIP-155として提案されている↓
https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki
以下、BIPの意訳↓(2021/01/25時点の内容で更新)
イントロダクション
概要
このドキュメントはP2Pネットワークにおいてより長いアドレスをゴシップするための新しいP2Pメッセージを提案する。これは、新世代のオニオンアドレスやI2Pおよび現在のaddr
メッセージの128 bitに収まらないエンドポイントアドレスを持つ可能性がある他のネットワークをサポートするのに必要になる。
動機
TorのV3 Hidden Serviceバージョン0.3.2.9以降のTorの安定版リリースの一部だ。これは以前のHidden Serviceと比較してさまざまな利点を持っているが、その中でも暗号化とプライバシーの利点が大きい。ただ、これらは256 bitのアドレスを持っているため、OnionCatのIPv6アドレスにオニオンアドレスをカプセル化する現在のaddr
メッセージには収まらない。
I2Pなどの他のトランスポート層プロトコルは、常により長いアドレスを使用してきた。このBIPの変更により、そのようなアドレスをP2Pネットワークでゴシップすることが可能になり、他のピアがそれらに接続できるようになる。
仕様
addrv2
メッセージはpchCommand == "addrv2"
のメッセージとして定義され、P2Pメッセージの標準エンコーディングでシリアライズされる。フォーマットは現在のaddr
メッセージと似ているが、16バイト固定のIPv6アドレスがネットワークIDと可変長アドレスに置き換えられ、services
のフォーマットがCompactSize形式に変更されている点が異なる。
これはメッセージに以下の構造のシリアライズされたstd::vector
が含まれること意味する。
タイプ | 名前 | 定義 |
---|---|---|
uint32_t |
time |
このノードが最後にネットワークに接続していたと思われるUNIXエポックタイム形式の時刻。 |
CompactSize |
services |
CompactSizeでエンコードされた64bit幅のサービスビットフィールド |
uint8_t |
networkID |
ネットワーク識別子。どのネットワークに対応するか示す8 bitの値。 |
std::vector<uint8_t> |
addr |
ネットワークアドレス。解釈はnetwork IDに依存する。 |
uint16_t |
port |
ネットワークポート。ネットワークに無関係の場合は0でなければならない。 |
1つのメッセージに最大1,000個のアドレスを含めることができる。クライアントはそれ以上のアドレスを含むメッセージは拒否すべきだ。
フィールドaddr
は可変長で、最大512バイト(4096 bit)。クライアントはネットワークIDに限らず、それより長いアドレスは拒否すべきだ。
予約済みのnetwork IDのリストは以下のとおり。
Network ID | Enumeration | アドレス長(バイト) | 定義 |
---|---|---|---|
0x01 |
IPV4 |
4 | IPv4アドレス |
0x02 |
IPV6 |
16 | IPv6アドレス |
0x03 |
TORV2 |
10 | Tor v2 hidden serviceアドレス |
0x04 |
TORV3 |
32 | Tor v3 hidden serviceアドレス |
0x05 |
I2P |
32 | I2Pオーバーレイネットワークアドレス |
0x06 |
CJDNS |
16 | Cjdnsオーバーレイネットワークアドレス |
クライアントは、現在いくつかのネットワークに接続していなくても、全ての既知のネットワークからアドレスをゴシップすることを推奨する。これはマルチホームノードを支援し、どのネットワークに接続しているのかオブザーバーが見分けるのを困難にする可能性がある。
クライアントは未知のネットワークからのアドレスをゴシップしてはならない。これは、それらのアドレスを検証する術がなく、無効なアドレスをゴシップするよう騙される可能性があるため。
ネットワークIDの番号は必ず新しいBIPで予約されなければならない。
クライアントは、特定のネットワークIDについて、この表に記載されているものとは異なる長さのアドレスを含むようなメッセージを拒否する必要がある。これらは無意味であるため。
さまざなネットワークで使用されるアドレスエンコーディングについてはAppendix参照。
シグナリングのサポートと互換性
新しいメッセージタイプsendaddrv2
を導入する。このメッセージを送信することは、ノードがaddr
メッセージではなくaddv2
メッセージを理解し、受信したいこと示す(つまりaddv2
をメッセージ送ってほしいと)。このメッセージを送信するかしないかは、要求されていないアドレスメッセージの受信に関する優先順位を意味するものではない。
sendaddrv2
メッセージは、ピアからのversion
メッセージに対して、verack
メッセージを返す前に送信する必要がある。
ピアが特定のプロトコルバージョン(もしくはそれ以降)である場合のみ、メッセージを送信する。
sendaddrv2
メッセージを送信しなかった古いピアの場合、新しく導入されたアドレスタイプのアドレスを無視して従来のaddr
メッセージを送信し続ける。
参照実装
予定されているがまだ記載されていない。
Appendix A: Tor v2 アドレスエンコーディング
新しいメッセージはTORV2
用の別のネットワークIDを導入する。
クライアントはアドレスフィールドに80 bitのhidden service IDを入れて、このネットワークIDを持つ、Tor hidden serviceアドレスを送信しなければならない。これは従来のaddr
メッセージの表現と同じだが、OnionCatのラッピングの先頭6バイトが除かれている。
クライアントはもしIPV6
ネットワークIDでこれらが送られてきた場合、受信時にOnionCat(fd87:d87e:eb43::/48
)アドレスを無視する必要がある。
Appendix B: Tor v3アドレスエンコーディング
仕様によると、次世代の.onionアドレスは以下のようにエンコードされる。
onion_address = base32(公開鍵 | チェックサム | バージョン) + ".onion" CHECKSUM = H(".onion checksum" | 公開鍵 | バージョン)[:2] where: - 公開鍵はhidden serviceの32バイトのed25519マスター公開鍵 - VERSIONは1バイトのバージョンフィールド(デフォルト値は'\x03') - ".onion checksum" は固定文字列 - チェックサムはonion_addressに挿入される前に2バイトにトランケートされる - H()はSHA3-256暗号学的ハッシュ関数
Tor v3アドレスはアドレスフィールドの32バイトの公開鍵と一緒にTORV3
ネットワークIDと共に送信されなければならない。v3アドレスの場合バージョンは常に\x03
になるので、これで十分オニオンアドレスを再構築できる。
Appendix C: I2Pアドレスエンコーディング
Torと同様、I2Pのネーミングはbase32エンコードされたアドレスフォーマットが使われる。
I2Pは52文字(256 bit)を使って完全なSHA-256を表現し、その後に.b32.i2p
が続く。
I2Pアドレスは、アドレスフィールドとしてデコードされたSHA256ハッシュと一緒に、I2P
ネットワークIDと共に送信されなければならない。
Appendix D: Cjdnsアドレスエンコーディング
Cjdnsアドレスはfc00::/8
範囲内のシンプルなIPv6アドレスで、CJDNS
ネットワークIDと共に送信されなければならない。