Develop with pleasure!

福岡でCloudとかBlockchainとか。

プルーニングピア向けのservice bitを定義したBIP-159

Bitcoinのmainnetのブロックチェーンのデータサイズは現在150GB弱ほどだが、プルーニングモードで動作させると使用済みのTXOを指定サイズ分だけ保持し、古いTXOデータは削除されていくようになり、とても少ないディスクスペースでフルノードを動作させることができる。

ただ、昔の履歴ブロックは消えてしまうため、IBD(Initial Block Download)などでジェネシスブロックからの古いブロックの要求があってもそれに答えることはできない。そのためプルーニングモードを使用している場合は、nServiceFlagsNODE_NETWORKがアンセットされるようになっている。

ただIBDはできないけど、最近リレーされたブロックであれば提供することができるため、プルーニングノード向けに新たにservice bitを定義して、直近のブロックやヘッダ、トランザクションは他のフルノードと同様リレーできるようにしようということでBIP-159が提案された↓

https://github.com/bitcoin/bips/blob/master/bip-0159.mediawiki

動機

プルーニングモードで動作しているピアは、全ブロックの歴史を提供することはできないが、それ以外は従来のピアと同じサービスを提供できる。Bitcoinは現在、ピアが全ての履歴ブロックを提供できることを示すNODE_NETWORKのservice bitのみを提供している。

  1. プルーニングされているピアは、ブロック、ヘッダ、トランザクション、アドレスをリレーすることができ、履歴ブロックも限られた数であれば提供できるため、プルーニングピアもそのserviceをアナウンスする方法を持つべきである。
  2. 他のピアが非プルーニングピアからブートストラップできるようにするため、IBDが終わったピアは、プルーニングされたピアへのいくつかのアウトバウンド接続を考慮する必要がある。

仕様

新しいservice bits

このBIPでは2つの新しいservice bitsを定義する↓

名称 bit 内容
NODE_NETWORK_LIMITED_LOW bit 10 (0x400) このservice bitが通知された場合、ピアは少なくとも最新の288ブロック(現在のBitcoin Coreの最小値で約2日分のブロック)に対応できなければならない。
NODE_NETWORK_LIMITED_HIGH bit 11 (0x800) このservice bitが通知された場合、ピアは最新の1152ブロック(約8日分)に対応できなければならない。

NODE_NETWORK_LIMITED_*のservice bitをシグナリングしているピアに接続する際は、チェーンの再編成を処理するため144ブロックのセーフティバッファを考慮する必要がある。

アドレスのリレー

このBIPに従うフルノードは、(NODE_NETWORK_LIMITED_*のservice bitをシグナリングしているピアを含む)接続中のピアから(addrメッセージ等で送られる)address/servicesをリレーする必要がある。

ピアのフィンガープリント対策

(ディスク容量など各ピアの構成は違うので)プルーニングしいてるピアがどれだけのブロック数を保持しているかはピアによって異なり、それがフィンガープリンティングの弱点につながるかもしれない(getdataメッセージでピアがプルーニングしている深さを知ることができる)。NODE_NETWORK_LIMITEDをサポートするピアは、プルーニングしている深さを漏らさないようにしなければならない。そのため、通知されたNODE_NETWORK_LIMITED_*閾値(↑よりそれぞれ288ブロックと1152ブロック)より深いブロックを要求するメッセージが来ても処理してはならない。

リスク

このBIPに従うプルーニングピアは、より多くのアウトバウンドの帯域幅を消費する可能性がある。

リレーされたaddrメッセージのnServiceFlags(service bits) をチェックしていない軽量クライアントは、意図せずプルーニングピアに接続し、プルーニング済みのブロックを要求する可能性がある。この場合プルーニングピアは対象のブロックデータを返せないので、そういう事態を避けるために軽量クライアントはservice bitsをチェックしなければならない。DNSシードを介してピアのIPを取得する軽量クライアントは、DNSフィルタリングオプションを使う必要がある。

互換性

この提案は後方互換性がある。

参照実装

github.com

2017年8月8時点ではまだマージはされてない。

所感

  • 接続先のノードがプルーニングノードかどうかは、今までNODE_NETWORKがセットされてないノードという識別方法だったけど、上記のservice bitsが追加されたことで明示的にプルーニングノードが識別できるようになる。
  • プルーニングピアにプルーニングされたブロックを要求した場合、そのピアの挙動としては何も応答を返さない?