Bitcoinの技術面を学ぶにはこれしかないと言われているほどの名著Mastering Bitcoin を今更読んだので、自分の中での復習を兼ねて、ところどころ解説付きでまとめを書いていきます。
元の本ではサラッと流されているところもしっかり解説するつもりでお節介に書いたので初学者の人には分かりやすいかもしれません。
日本語版PDFはここで無料公開されているので翻訳者の方々への感謝を常に感じながら読みました。
無料公開版ということもあって誤字脱字もたまにあったりするので、
しっかり製本されたものが読みたいという方はAmazonで買って読むことをお勧めします。
前回↓
第7章 ブロックチェーン
ブロックチェーンは「多くのトランザクション(誰から誰へいくら送金したか)を含むブロックが数珠つなぎに並べられている」データであり、各ノードによってフラットファイルとしてまたはシンプルなデータベース内に保存されているものです。
(Bitcoin core クライアントはGoogle のlevel DBを用いてブロックチェーンデータを保持しているようです。)
ブロックチェーンのデータ構造の特徴は「各ブロックが1つ前のブロックへのリンクを持つ構造になっている」点です。
この性質から「ブロックが1つ前のブロックの上に積み上がっていく」ようだということで、ブロックチェーンはしばしば”垂直スタック”(縦に積み木を積み上げていくようなデータ構造)として表現されます。
(一番最初のブロック(genesis block)からそのブロックまでの距離を”block height”(ブロック高)といい、 一番最後(最新)のブロックを”top”、”tip”(先端)と表現します。)
また、ブロックチェーンはそれぞれのノードで保持されているものなので、複数のことなるブロックチェーンが存在し得ますが、Bitcoinネットワークでは「最も長いブロックチェーン」が「真のブロックチェーン」とされていることを覚えて置いてください。
⑴ブロックの構造
各ブロックの構造は以下の表のようになっています。
大きく分けると
- ブロックヘッダ
- そのブロックに含まれるトランザクションリスト
によって出来ています。
⑵ブロックヘッダ
各ブロックに含まれるブロックヘッダは以下の表のような構造を持っています。
TimestampとDifficulty Target、Nonceについてはマイニングに関連するものなので次の第8章の記事で説明するとして、ここで重要なのはPrevious Block HashとMerkle Rootです。
①Previous Block Hash (Previous Block Header Hash)
親のブロックのハッシュ値と書かれていますが、正確には「親のブロックのヘッダのダブルハッシュ値」です。
ダブルハッシュは「SHA256アルゴリズムを2回適用して生成される暗号学的ハッシュ」のことでしたね。
これがあることによって、ブロックが一つ前のブロックと繋がっています。
以下の画像のように、ある親ブロックがあったとして、そのブロックの次にくる子ブロックは「親ブロックのブロックヘッダのハッシュ値」をPrevious Block Hashとしてブロックヘッダに持っています。
そしてその子ブロックの次に来る孫ブロックも「子ブロックのブロックヘッダのハッシュ値」をブロックヘッダにもつという連鎖構造になっています。
これによって、親ブロックのトランザクションの中身を改ざんしようとすると、親ブロックのmerkle root、つまりブロックヘッダが変わってしまい、これをハッシュ化したものと、子ブロック以降のPrevious Block Hashが一致しなくなってしまいます。
そのため、もし過去のトランザクションを変更したい場合には、変更したトランザクションのブロック以降のブロックを全て自分で生成して、ブロックチェーンの”現時点でのブロック”を超えるブロックまでを作り上げなくてはなりません。(こうしてメインのブロックチェーンとは異なる内容のブロックチェーンを作っていくことをFork[分岐]と言います)
次章で見ていきますが、一つのブロックを生成する(ナンスを見つける)のにも相当な計算量が必要なので、これには膨大な計算量が必要な上、その計算をしている間に”現時点のブロック”もどんどん生成されて進んでいきますので、最も長いブロックチェーンを作り上げて過去のトランザクションを改ざんするのは現実的に難しいと言われています。
この性質が「ブロックチェーンの改ざん不可能性」を生み出しているのです。
ブロックチェーンは地層に例えられます。これらは表層部分は季節や気候の変化によって変化しやすいものの、十数センチ下の層では状態はより安定し、さらに数十メートル下の層では数百万年前の状態がそのままの形で残っていますよね。
ブロックチェーンでも同様に、ほんの最近の2、3ブロックはフォークによる再計算を行って書き換えられるかもしれません。しかし、一度6ブロック(地層でいうと十数センチ下くらい)より深くのブロックチェーンの奥に入ってしまうとブロックはほぼ変更されないようになりますし、100ブロックまで来るともっと安定的になり、この100ブロック目にあるcoinbaseトランザクションを使うことができるようになります。3000〜4000ブロックまで奥に入ってしまう(1ヶ月分のブロックが積み重なる)と、このブロックは歴史に刻まれ確固たるものと判断できるとされています。
②Merkle Root
そのブロックに含まれる全トランザクションをmerkle treeとして導出したmerkle rootという32byte(256bit)のハッシュ値です。
簡単に言えば「全トランザクションを一つにまとめた要約値」ですね。
merle treeについての説明は以下です。
⑶Merkle Tree
Merkle Treeは「大きなデータを要約し、かつデータ全体を検証可能にするもの」です。
ブロックチェーンでは「ブロックに含まれる沢山のトランザクション」を要約してMerkle Rootという32byteのハッシュにしています。
上の画像において一番下の4つの四角がトランザクションです。
- H~A~ = SHA256(SHA256(Transaction A))
- H~AB~ = SHA256(SHA256(H~A~ + H~B~))
といったように「順番に隣同士を合わせてダブルハッシュ化」していきます。
そうして残った最後の値がMerkle Rootになります。
また、最下層のトランザクションの数が奇数だった場合には、最後の余った一つが複製されて偶数個になります。(以下の画像参照)
また、それぞれのダブルハッシュ値が authentication path, merkle pathと呼ばれるものとして機能します。
これは前回第6章で学んだ「SPVノードがフルノードのトランザクションデータを要求する仕組み」で使われるものですね。
具体例を以下の画像で見ていきます。
SPVノードはこのブロックのMerle Rootは持っており、フルノードから緑色のトランザクションデータを渡されたので、画像の中で緑に塗られている部分のトランザクションが本当にこのブロックに含まれていることを確認したいとします。
この時、青色で塗られた部分が authentication path, merkle pathとして渡されます。
このauthentication path, merkle pathがあることで、SPVノードは
①緑のトランザクションデータをダブルハッシュ化する
②1とauthentication path, merkle pathを順番に合わせて計算していく
③そうしてたどり着いたMerkle Rootと自分の持っているMerkle Rootを比較することで緑色トランザクションが本当にこのブロックにあったと検証できる
わけです。
ここでのポイントは
そのブロックに含まれるトランザクション数をNとすると[log2のN] 個のauthentication path, merkle pathと、[log2のN] 回のダブルハッシュの計算で検証が可能
ということです。
対数の性質により、このブロックに2048 個のトランザクションが含まれている時の計算回数は11回、65,535 トランザクション になっても計算回数は16回にしか増えませんね。
これがMerkle Treeの大きなメリットです。
⑷ブロックの識別子
ブロックの識別子は
- Block Header Hash
- ブロック高
があります。
Block Header Hashは一意にブロックを特定しますが、ブロック高は場合によってはそうではありません。
ブロックチェーンがフォークした場合、同じ高さのブロックが複数存在することになり得るからです。
<感想>
この章は今までの章を理解していればサラッと読めると思います。
続き↓
0コメント