暗号通貨に関する事など

暗号通貨に関する覚書など。メモや日記。

※技術的なことに関して、間違っていたらコメントから指摘していただけると泣いて喜びます

Segwitに関して調べた記録2


前回の続き



2,トランザクションと新たに追加されるWitnessという構造に関して

 これを書かないと始まらないので、いきなりになるが構造に関して書こうと思う。今までのトランザクションの構造を知っているものとして書くので、わからない方は

 Transaction - Bitcoin Wiki

 (“general format of a Bitcoin transaction (inside a block)”以下の部分)

を見よう。



トランザクションとWitnessの構造

 トランザクションとWitnessの構造に関して文字で書いて伝える自信もないので、新旧対比を図にして載せる。文字が小さくてごめんね。

 (※tx_outの数が2つあった間違いを修正しました)


 赤色に着色された箇所がSegwitで新たに追加されるフィールドだ。赤色着色部の一番下、Witnessの部分が今までのトランザクションとは別に保管される場所であるWitnessの本体である。(特に理由はないが、tx_in,tx_outは2個ずつのパターンで書いた)
 以下、新たに追加されるmaker、flag、witnessの部分について書く。



maker

 makerは1byteのフィールドで、必ず「0x00」に固定される。
 何故このフィールドを追加して必ず「0x00」で固定するのかというと、後方互換のためである。


 makerがセットされている位置は旧トランザクションでは「tx_inの数」となっている。Segwit非対応のクライアントがSegwit形式のトランザクションを受け取った時に「これはtx_inの数が0個となっているので、つまり何もない空のトランザクションだ」と判断してくれるので、makerを0にセットしておけば意図しない形のトランザクションとして読み込まれるようなことがない。makerフィールドを新たに設けて0x00をセットするのはそのためだ。


 また、Segwit対応のクライアントはここを見てこのトランザクションがSegwit形式か旧形式かを見分けることができる。



flag

 flagは1byteのフィールドで0以外をセットするフィールドとされている。正直、これの使いみちはまだ良く分かっていないのだが、トランザクションの作用に影響を与えないフラグのようなものだと理解している。(間違ってたらごめんなさい)



Witness

 Witnessは署名検証に使われる構造体で、参照先のロックスクリプトがP2WPKHまたはP2WSHの時に対応することになる。ここで注意しておきたいのが、Witnessはビットコインスクリプトとは違う構造体であり、ここにビットコインスクリプトを書いて入れておくわけではない。


 Witnessはスタックデータの数を示すvar_int(compact size uint などと書かれることもある1-9byteで数を表すバイト配列)から始まり、その後ろにvar_intで指定した数のスタックデータがつく。スタックデータの頭にはスタックデータの長さを示すvar_intがつけられる。
 
 詰まるところ、下記図のようなデータが格納されることになる。
 (図はStackDataの数が2個の場合)

 これが、Witnessプログラムに読み込まれて、署名検証として利用される。なお、Witness内でインデックスがレガシーなP2PKHスクリプトに対応するとき(署名にwitnessを利用しないパートが現れた時)は、"0x00(スタックデータ無し)"としておく。


 繰り返しになるが、これはビットコインスクリプトとは別の構造体になるので、stackDataの長さを示すのはvar_intであってビットコインスクリプトのPUSH_DATAコマンドではない。また、スクリプトではないので520byteの制限も受けない。



tx_idとwitness_idについて

 この記事の次にトランザクション展性について書こうと思っているが、その予備知識として、tx_idとwitness_idについて知っておかなくてはならない。


 Segwit導入後も、tx_idを計算するときに使う要素は旧トランザクションのそれをそのまま利用する。つまり、新しくSegwitで追加されたmaker、flag、witnessは、Segwit導入後もtx_idを計算するのには利用されない。


 代わりに、witness_idと呼ばれるものが追加され、その計算は、上記に示したSegwitトランザクションをまるまるシリアライズしたものをSHA-256doubleHashして導かれる。


 詳しくはまた別の機会に書くが、tx_idの計算にwitnessのデータを含めないということはつまり、witnessの中身を変更してもtx_idの値は変わらないということになるので、今までのように「署名用スクリプトを同じ意味になるように書き換える」というトランザクション展性攻撃が出来なくなる。



Segwitとトランザクションの構造に関しての説明は以上でおわり。
〜3へ続く〜

×

非ログインユーザーとして返信する