マークル木
詳解ビットコインの続きを読む。
P2SHアドレスについて、スクリプトのハッシュ値20バイトの先頭にバージョン(0x05)を付けて、base58checkでエンコードするので先頭は必ず「3」になる、とさらっと書いてあり、何故なのかよく分からなかった。P2PKHアドレスは先頭に付けるバージョンが0x00であり、base58checkでは先頭の0x00のバイト数分だけ、先頭に「1」を付けるので、P2PKHアドレスが「1」で始まるというのは分かりやすい。しかし、先頭バイトを0x05に固定したからといって、それをエンコードした時に先頭が必ず「3」になるというのがすぐには分からなかった。 実際に計算をして納得した。base58checkでは58の剰余を計算する前に、チェックサムを後ろに付ける。元のデータ20バイトの先頭にバージョン(1バイト)と、この21バイトに対するチェックサム(4バイト)を足して、剰余計算の対象となる値は25バイトになる。
| 25バイトデータ(16進数表記) | エンコード後の表記(33桁) |
|---|---|
05 00000000 00000000 00000000 00000000 00000000 00000000 | 31h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj |
05 00000000 00000000 00000000 00000000 00000000 00000001 | 31h1vYVSYuKP6AhS86fbRdMw9XHiZAvAak |
05 00000000 00000000 00000000 00000000 00000000 00000002 | 31h1vYVSYuKP6AhS86fbRdMw9XHiZAvAam |
| … | … |
05 ffffffff ffffffff ffffffff ffffffff ffffffff fffffffd | 3R2cuenjG5nFubqX9Wzuukdin2YfGQVzu2 |
05 ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe | 3R2cuenjG5nFubqX9Wzuukdin2YfGQVzu3 |
05 ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff | 3R2cuenjG5nFubqX9Wzuukdin2YfGQVzu4 |
同じ値に対する2つの表記を見比べると、先頭が0x05の25バイトデータがとりうる値の範囲(5 * 256^24 〜 6 * 256^24 - 1)が、エンコード後に先頭が「3」になる値の範囲(2 * 58^32 〜 3 * 58^32 - 1)にすっぽり入っている。なのでP2SHアドレスは必ず「3」で始まる。
6章はブロックチェーンについて。ブロックチェーンの全ての情報を持つフルノードに対し、一部分しか情報を持たないノード(簡易ウォレット)は、ある、例えば自分が作成したトランザクションがどのブロックに格納されているかを知りたい時にはフルノードに問い合わせる必要がある。この問合せに対して、素朴には、指定されたトランザクションを含むブロックを丸ごと応答すればよい。ただブロックには大量の無関係のトランザクションも含まれるため、通信量が大きくなってしまう。通信量を減らそうとして、単純に無関係のトランザクションを削った情報を応答したのでは、期待のトランザクションがそのブロックに含まれる事を確認するためのハッシュ値(マークルルート)を算出できなくなってしまう。要求しているトランザクション以外のデータを削る事で通信量を減らし、それでもなお期待したトランザクションがブロックに格納されている事を確認するため、部分マークル木を使用する。部分マークル木を使用して、要求されていないトランザクションについてはマークルルートを算出するための途中の値を応答する。格納されている事を確認したいトランザクションについては手元でハッシュ値を算出し、応答された途中の値と合わせてマークルルートを算出して、ブロックヘッダに記載されたものと一致すれば、そのトランザクションがブロックに格納されている事が確認できる。