Develop with pleasure!

福岡でCloudとかBlockchainとか。

Segwitにおける新しいメッセージとシリアライズフォーマットの仕様(BIP-144)

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ハッシュは通常のハッシュと同じ値になることに注意すること。)

https://github.com/bitcoin/bips/blob/master/bip-0144/witnesstx.png?raw=true

Relay

getdataでのみ使用可能な新しいinvタイプMSG_WITNESS_TXMSG_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 に感謝する。

参照実装

github.com

まとめ&所感