segwitに対応したトランザクション及びブロックを伝搬させる際の新しいメッセージやシリアライズフォーマットについて定義したBIP-144を見てみる。
bips/bip-0144.mediawiki at master · bitcoin/bips · GitHub
動機
BIP-141でsegwitのコンセンサスが定義されブロックへのwitness structuresの定義とコミットメントに加えて、新しいメカニズムは、ピアがsegwitをサポートすることを通知し、witness structureを中継し、古いノードとの互換性を壊すことなく他のピアに要求できるよう定義されなければならない。
仕様
シリアライゼーション
トランザクションメッセージのための新しいシリアライゼーションフォーマットがP2Pプロトコルに追加される。
新しいシリアライゼーションフォーマットは以下の構造になる。
サイズ | 名前 | タイプ | 定義 |
---|---|---|---|
4 | version | int32_t | トランザクションのデータフォーマットのバージョン |
1 | marker | char | 0を設定 |
1 | flag | char | 0以外を設定 |
1+ | txin_count | var_int | トランザクションの入力の数 |
41+ | txins | txin | 1つ以上のトランザクションの入力のリスト |
1+ | txout_count | var_int | トランザクションの出力の数 |
9+ | txouts | txouts | 1つ以上のトランザクションの出力のリスト |
1+ | script_witnesses | script_witnesses[] | witness structureをシリアライズしたバイト配列 |
4 | locktime | uint32_t | トランザクションがロックされるブロックHeightもしくはタイムスタンプ |
このBIPをサポートするパーサーはこのフォーマット仕様と古いシリアライゼーションフォーマットを区別することができる。このBIPをサポートしていないパーサーがこの構造を有効なトランザクションとして解析することがないようmarkerバイトには0をセットする。パースが成功するようなことがあれば、そのトランザクションには入力や出力が1つも無いだろう。
witnessが空の場合は、古いシリアライゼーションフォーマットを使わなければならない。
現在サポートされている唯一のwitnessオブジェクトタイプはバイト配列のスタックで構成されるscript witnessesである。これは可変長整数の項目数としてエンコードされており、その後に各項目の文字列のバイトの長さを指す可変長整数がエンコードされ、その後に文字列が続く。各txinは独自のscript witnessを持つ。script witnessesの数は明示的にエンコードされないが、txin_countによって分かる。空のscript witnessesは0バイトとしてエンコードされる。script witnessesの順番は関連するtxinsの順番と同じ。
- 新しいシリアライゼーション仕様が独自のメッセージタイプを持たない根拠
独自のメッセージタイプを持つと、別個の"tx"と"block"メッセージが必要となりrawトランザクション上の操作の全てのRPCコールが重複することになるか、どのタイプが使われるのか知るために非効率または非決定的な当て推量が必要になる。 - markerとして単一の 0x00 byteを使わない根拠
新しくシリアライズされたデータとして解釈される(入力、出力が無い)空のトランザクションにつながるため。 - 0x01 flag byteの根拠
トランザクションに簡単に非コミットメントデータを追加できるようにするため。これはビットベクトルとして解釈することができる。
Handshake
ノードはwitnessを利用できることを以下のservice bitを使って通知する。
NODE_WITNESS = (1 << 3)
Hashes
トランザクションのマークルツリーとtxinのoutpointで使用されるトランザクションハッシュは、常に古い非witnessシリアライゼーションを使って計算される。
witnessデータを含む新しいハッシュのサポートが追加され、それは新しいwitnessシリアライゼーションから計算される。(ただ、witnessが空のトランザクションは常に古いシリアライゼーションを使うため、witnessハッシュは通常のハッシュと同じ値になることに注意すること。)
Relay
getdataでのみ使用可能な新しいinvタイプMSG_WITNESS_TX
とMSG_WITNESS_BLOCK
が追加された。インベントリメッセージ自体はまだMSG_TXとMSG_BLOCKを使用する。また将来のinvタイプとしてMSG_FILTERED_WITNESS_BLOCK
が確保されている。
- invsにwitnessnessを通知しない根拠
(新しいBlockのメッセージを受け取る際に)我々はもうinvメッセージを使用しない(BIP-130のsendheadersに代替された)。各トランザクションやブロックはwitnessを持ち、古いものは単に空であるため。
MSG_WITNESS_TX getdataリクエストは非witnessでシリアライズされたハッシュを使う必要がある。ピアはtxメッセージで応答し、その際witness structureが空でなければwitnessシリアライゼーションが使われる。
MSG_WITNESS_BLOCKリクエストは、witnessシリアライゼーションを使ってwitnessを持つトランザクションとブロックメッセージを返す。
クレジット
このBIPの多くのアイディアを発明したGregory Maxwellとソフトフォークとしてデプロイする方法を考えだしたLuke-Jr に感謝する。