フルノードのUTXOセット内にある出力が存在するかチェックするためのP2Pメッセージを定義したBIP-64についてみてみる↓
https://github.com/bitcoin/bips/blob/master/bip-0064.mediawiki
※ マイクハーンによる提案で、Bitcoin Coreにはservice bitの定義は存在するけど、機能自体は実装されていない。
動機
Bitcoinの全フルノードは、未使用のトランザクション出力のセットを維持しており、このデータセットを使ってコインの二重使用をチェックしている。未使用の出力を使用する有効なトランザクションの場合、その入力の未使用出力の識別子OutPointが、このデータセット内にある。使用済みの出力を再度使用するトランザクションの場合、このデータセットの中に対象のOutPointがなく、無効と判断される。
完全なUTXOデータを保持しない軽量/SPVクライアントなどが、このフルノードのデータセットにアクセスできると役に立つ。例えば、保証契約などを実装するアプリケーションでは、新しい契約が出てきた際に、その契約が既に二重使用によって取り消されているかどうかすぐにテストして判断できるようになる。こういったアプリケーションはブロックチェーンのデータを全てダウンロードすれば実装できるので絶対必要な機能ではないが、実装してもパフォーマンスは許容範囲で、さまざまなUIケースを解決するのに便利だ。
このデータが有用なもう1つのケースは、SPVウォレット内で変動手数料の計算を行うケースだが、このケースではBitconプロトコルにいくつかの変更が必要なため、ここでは説明しない。
仕様
新しく以下のデータで構成されるgetutxos
というメッセージを定義する。
バイト数 | 定義 | タイプ | コメント |
---|---|---|---|
1 | check mempool | bool | 計算中のmempool内のトランザクションを適用するかどうか。 |
? | outpoints | vector | 照会するOutPointのリスト。各OutPointのデータはtx メッセージの場合と同じ方法でシリアライズされる。 |
このメッセージの応答メッセージが以下のデータで構成されるutxos
メッセージ。
バイト数 | 定義 | タイプ | コメント |
---|---|---|---|
4 | chain height | uint32 | 対象のUTXOが存在するかチェックした際のチェーンのHeight |
32 | chain tip hash | uint256 | 対象のUTXOが存在するかチェックした際のブロックハッシュ |
? | hit bitmap | byte | 照会された各OutpointがUTXOセット内で見つかったかどうかを示すビット列。 |
? | result utxos | resutl | resultオブジェクト(後述)。bitmap にbitがセットされている未使用の各OutPoint毎にresultオブジェクトが存在する。 |
↑のresultオブジェクトの構造は以下の通り↓
バイト数 | 定義 | タイプ | コメント |
---|---|---|---|
4 | tx version | uint32 | 検出されたUTXOを持つトランザクションのバージョン |
4 | height | uint32 | 検出されたトランザクションが含まれるブロックのHeight。もし対象のトランザクションがmempoolにある場合は0x7FFFFFFF 。 |
? | output | CTxOut | 出力自身で、tx メッセージと同じ方法でシリアライズされている。 |
後方互換性
ノードは70003より上のプロトコルバージョンを宣言し、nServiceフィールドに2(フィールドの2番目のビット)をセットした新しいNODE_GETUTXO
フラグを設定することで、このメッセージをサポートすることを示す。
認証
チェック結果のデータは今のところ、それが確実な結果であることを認証されたデータではない。ブロックでUTXOセットのルートハッシュにコミットする新しいコンセンサスルールを導入することでこれを解決する提案があるが、この機能は現在のBitcoinプロトコルでは利用できない。もし実装されるとutxos
メッセージには、コミットされたUTXOセットに含まれていることを示すMerkleブランチを含むようアップグレードできる。
このメッセージを要求するクライアントが、ローカルに保持している署名付きトランザクションの出力を探している場合、クライアントはそのトランザクションの入力と、このメッセージで帰ってきた出力を使ってスクリプトの検証ができる。現状はスクリプトが正しいか検証できるだけだが、将来のBitcoinプロトコルでは、この方法で値をチェックすることも可能になる。しかし、出力が実際に使用されてないか、ブロックチェーンで実際に作られたものかは明らかにならない。さらに、提供されたscriptPubkey
の形式を実行前にチェックし、リモートピアがスクリプトにOP_TRUE
をセットしてないか確認する必要がある。
メッセージを要求したクライアントが、(getheaders
メッセージなどを介して)ベストチェーンのHeightとブロックハッシュのマッピングを持っていれば、追加でそのブロックデータを要求し、ブロック内の出力を検索するkとで、ある時点でその出力が存在した証拠を入手することができる。Bloom Filterと組み合わせると合理的で効率的になる。
注意:このプロトコルはBloom Filterと同じセキュリティモデルがある。リモートノードは要求されたUTXOが存在しない or 既に使用されている嘘をつくことができる。BitcoinのP2Pネットワークには認証機能は無いので、ネットワークの参加者が中間者攻撃のように間違った結果を返すことも考えられるため、同じデータを複数のノードに照会して結果を検証する必要がある。