Develop with pleasure!

福岡でCloudとかBlockchainとか。

BitcoinのP2Pネットワークにおけるトランザクションパッケージのリレー(BIP-331)

BitcoinP2Pネットワークにおいて、トランザクションパッケージのリレーをサポートするBIP-331が先日登録された↓

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

トランザクションリレーとmempool

現状のBitcoinトランザクションリレーは、基本的に1つのトランザクションをリレーするようになっている。

新しいトランザクションを受信したノードは、そのトランザクションを自身のmempoolに追加するかどうかを判断する。mempooolのサイズには上限があり、無限にデータを格納することはできないので、mempoolがいっぱいになった場合は、手数料率の低いトランザクションがmempoolから削除されようになっている。

手数料不足でmempoolから排除されたトランザクションについては、そのタイミングのmempoolの手数料率を考慮して高い手数料率を持つトランザクションを新たに作成して送信することになる。このようなトランザクションが自分1人が関連するトランザクションであれば特に問題はないけど、2人以上が参加するマルチパーティコントラクトにおいては、問題が生じる。

ライトニングネットワークのチャネル更新時には2人の参加者が協力してトランザクションを作成し、そのトランザクションをオフチェーンで管理し、チャネルを一方的に閉じる必要がある場合、そのトランザクションをネットワークにブロードキャストする。このような場合、トランザクションを作成した際のネットワークの手数料率とトランザクションをブロードキャストする際の手数料率は異なる可能性がある。

比較的手数料率が低いタイミングでトランザクションを作成し、その後手数料率が上がると、作成したトランザクションはブロードキャスト時には手数料率が低すぎてネットワークの各ノードのmempoolに入らないレベルになってしまう可能性がある。相手がオンラインで協力できる状態であれば協調クローズのために新たな手数料を設定することも可能だけど、1人ではトランザクションの手数料を引き上げる術がなくなってしまう。CPFPにより子トランザクションで手数料を引き上げようとしても、親子の各トランザクションはそれぞれ別々にブロードキャストされ、個別にmempoolに対して評価されるため、その親トランザクションがmempoolに受け入れもらえないような手数料率では手数料が引き上げられないといった状況が発生する。

また、BIP-133feefilterメッセージを使用するとピアに指定した手数料率以下のトランザクションを通知しないよう要求することができるが、親トランザクションがこの設定値を下回り、子トランザクションは高手数料率である場合も同様の状況が発生する。

このような状況を回避するためには、トランザクションをパッケージ(親子トランザクションのセット)として扱えるようにし、個別のトランザクションがmempoolの手数料要件を満たさない場合に、パッケージ対応したmempoolポリシーで評価できるようにする必要がある。

そのために必要なトランザクションパッケージの要求やリレーを可能にするP2Pメッセージを新たに追加しようという提案がBIP-331の内容。

Ancestor Package Relay

トランザクションパッケージをリレーする仕組みがAncestor Package Relay。親子のセットだけでなく、さらにその親、その親の親と祖先を最大100個を1つのパッケージで送信できる。

このパッケージリレーをサポートするために以下の4つ新しいP2Pメッセージが追加される。

sendpackages

sendpackagesは、パッケージリレーをサポートしていることを相手に通知するためのメッセージで、ピアとの接続を開始する際のハンドシェイク中(versionメッセージとverackメッセージの間)に送信される。

https://github.com/bitcoin/bips/raw/master/bip-0331/version_negotiation.png

パッケージリレーを有効にする場合、両方のピアがwtxidベースのリレーをサポートしている必要がある(BIP-339)。

ペイロード

sendpackagesメッセージのペイロードは↓

フィールド サイズ 目的
versions uint64_t 4バイト 送信者がサポートするパッケージのバージョン

versionsは、64 bitの値で、サポートするパッケージの機能を各bit値で指定するようになっている。現在定義されているのは以下の2つのbit↓

  • PKG_RELAY_PKGTXNS(1 << 0):パッケージリレーのデータのダウンロードラウンドをサポートするシグナル
  • PKG_RELAY_ANC(1 << 1):パッケージリレーのパッケージ情報ラウンドをサポートするシグナル

↑2つのシグナルがあるが、パッケージリレーでは、パッケージの情報を通知する(ancpkginfo)パッケージ情報ラウンドと、その後実際に不足しているパッケージ内のトランザクションをダウンロードするラウンド(getpkgtxnspkgtxns)で構成される。

パッケージリレーのメッセージフローの例が↓。例では、feefilterメッセージで3 sat/B未満のTxをリレーしない設定で、A, Cを受け取っている状態で、親Bをパッケージリレーしている。

https://github.com/bitcoin/bips/raw/master/bip-0331/package_cpfp_flow.png

ancpkginfo

ノードが未承認の親トランザクションを持つ子トランザクションを受信し、その親トランザクションを知らない場合、その子トランザクションのwtxidと識別子MSG_ANCPKGINFOを指定してピアにgetdataメッセージを送信することで、未承認パッケージの情報を要求することができる(パッケージ情報ラウンド)。この要求を受け取ったピアがパッケージ情報を送信するのに使用するのがancpkginfoメッセージ。要求されたwtxidの祖先パッケージがない場合は、notfoundメッセージを返す。

MSG_ANCPKGINFOgetdataメッセージを受信したピアは、その祖先トランザクションwtxidのリストをancpkginfoメッセージで送信する。

※ これに伴いgetdatainvタイプにMSG_ANCPKGINFOタイプが追加されている。

ペイロード

ancpkginfoメッセージのペイロードは↓

フィールド サイズ 目的
txns_length CompactSize 1 or 3バイト パッケージ内のトランザクション
txns wtxidのリスト txns_length*32バイト パッケージ内の各トランザクションのwtxidのリスト

この時、txnsの最後のwtxidはgetdataで指定された子トランザクションのwtxidで、リストのそれより前はその祖先のトランザクションのwtxidになる(祖先のwtxidのリストはトポロジー的にソートされている=祖先順にソートされることが推奨される)。

getpkgtxns

ancpkginfoメッセージで未承認の祖先パッケージをのwtxidのリストを受信したピアは、getpkgtxnsメッセージを使って、自分が持っていない祖先のトランザクションを要求する(トランザクションデータのダウンロードラウンド)。

ペイロード

getpkgtxnsメッセージのペイロードは↓

フィールド サイズ 目的
txns_length CompactSize 1 or 3バイト 要求するパッケージ内のトランザクション
txns wtxidのリスト txns_length*32バイト 要求するパッケージ内の各トランザクションのwtxidのリスト

txns_lengthの最大数は100個。

pkgtxns

getpkgtxnsメッセージを受信したピアは、指定されたトランザクションのリストをpkgtxnsメッセージを使って送信する。既存のtxメッセージと比べて、不足しているトランザクションを一括で送信できる。

要求されたトランザクションについて、1つでも自分が持っていないものがある場合は、getpkgtxnsのwtxidのリストをSHA-256ハッシュした値と識別子MSG_PKGTXNSを使ってnotfoundメッセージを返す(これに伴いnotfoundinvタイプにMSG_PKGTXNSタイプが追加されている)。

ペイロード

pkgtxnsメッセージのペイロードは↓

フィールド サイズ 目的
txns_length CompactSize 1 or 3バイト 送信するトランザクション
txns トランザクションのリスト 可変長 トランザクションのリスト

現状の使用例と今後の拡張

↑の現状の使用例は、子トランザクションを受信したノードが自信がもっていない未承認の祖先を要求し、それをリレーしてもらうものになっている。つまり、未承認のパッケージをinvで通知する機能はない。以下のように送信者がinvメッセージを使って未承認のパッケージをトリガーするような機能については、今後の拡張になるっぽい。

https://github.com/bitcoin/bips/raw/master/bip-0331/sender_init_future_version.png