⛓️

【東京大学ブロックチェーン公開講座第4週】ビットコイン③

2024/05/04に公開

本記事は、2024年東京大学ブロックチェーン公開講座の3つ目のレポートです。

【東京大学ブロックチェーン公開講座第1週】ブロックチェーン概論
【東京大学ブロックチェーン公開講座第2週】ビットコイン①
【東京大学ブロックチェーン公開講座第3週】ビットコイン②
【東京大学ブロックチェーン公開講座第4週】ビットコイン③(本記事)

なお、本記事は講座の要約ではなく、講座のポイントを抽出しつつ、筆者の理解や考察を添えてアウトプットしたものとなります。講座内容との差異や筆者の主張(オレンジ背景)が含まれます。

Multi-Signature

送金時に複数の署名を必要とする。主に法人の高額決済などのユースケースがある。M of Nという形で満たすべき署名の数を指定する。1 of 1から15 of 15まで任意の組み合わせ(M <= N)が指定できる。

Locking Scriptには対象のすべての公開鍵を並べ、Unlocking ScriptにはそのうちMつの秘密鍵による署名を使う。

例:2 of 5のマルチシグスクリプト

Script Contents Transaction maker
Locking Script 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 CHECKMULTISIG 送金者
Unlocking Script Sig1 Sig2 マルチシグウォレットの持ち主

Locking Scriptは送金者がトランザクションに含めるため(UTXOモデル)、以下2つの課題がある。

  • 複数の公開鍵を事前に受取人に問い合わせる必要がある
  • データ量(トランザクションサイズ)が増えるため、より高額な手数料を負担しなければならない(マルチシグを利用するのは受取人の勝手なので送金者には合理的な理由がない)

Pay-to-Script-Hash(P2SH)

マルチシグの課題を解決するための方式で、Redeem Scriptを使用することで、送金者ではなく受取人が(そのトランザクションを次に利用するときに)マルチシグによる余計な手数料を負担する。

Redeem Scriptは、Multi-SignatureにおけるLocking Script(公開鍵を並べたもの)。これをハッシュにかけて得た20bytesをLocking Scriptとする。Unlocking Scriptは、Mつの秘密鍵による署名+Redeem Script(公開鍵の羅列)。

Script Contents Transaction maker
Redeem Script 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 CHECKMULTISIG None
Locking Script HASH160 <20bytes hash of redeem script> EQUAL 送金者
Unlocking Script Sig1 Sig2 <redeem script> マルチシグウォレットの持ち主

また、Redeem Scriptのハッシュ値をBase58Checkエンコードしてアドレスを生成できる。このアドレスを顧客に教えておけば、他の支払いと同様に利用できる(ウォレットがP2SHに対応する必要あり)。

ブロックチェーン

ブロックチェーンの構造

ブロックチェーンでは、トランザクションは一定の単位で束ねられてブロックという単位で保存される。ブロックには、大まかに以下の項目が含まれる。

  • ブロックヘッダー
    • 前ブロックのブロックハッシュ
  • トランザクションのリスト

ブロックヘッダーをハッシュ化することでブロックをユニークに特定するID(ブロックハッシュ)が得られ、各ブロックは『前のブロックのブロックハッシュ』をブロックヘッダー内に保持している。

つまり、前のブロックハッシュをたどることで、あるブロックから親ブロック→親の親ブロック→と辿ることができる。

マークルツリー

ブロック内に含まれるトランザクションを要約するための木構造のデータ(2分ハッシュ木)で、32bytesでブロック内の全てのトランザクションを表現できる。マークルツリーを使うことで、任意のトランザクションがそのブロックに含まれているかを簡単に検証できる。

ブロックに含まれるトランザクションのリストをならべ、SHA256を2回(double-SHA256)かけたハッシュ値を末端葉とする。隣り合う2つの葉の値を連結し、SHA256を2回かけたハッシュ値を親葉とし、これを再帰的に繰り返すことでルートを算出できる。

このルートをマークルルートといい、ブロックヘッダーに含まれる。

H_A = SHA256(SHA256(TransactionA)), H_B = SHA256(SHA256(TransactionB))...
H_{AB} = SHA256(SHA256(H_A + H_B))...
H_{ROOT} = SHA256(SHA256(H_{AB} + H_{xx}))

ブロックの構造

ブロックは最大1MBで、以下の構造になっている。平均的に1900トランザクションが含まれる。

Bytes Contents Description
4 ブロックサイズ このブロックのサイズ(本フィールドを含まない)
80 ブロックヘッダー 後述
1-9 トランザクション数 このブロックに含まれるトランザクション数
可変 トランザクション このブロックに含まれるトランザクションのリスト

ブロックヘッダーの構造は以下。

Bytes Field Description
4 Version このブロックのサイズ(本フィールドを含まない)
80 Previous Block Hash 後述
1-9 Marcke Root このブロックに含まれるトランザクション数
可変 Timestamp このブロックに含まれるトランザクションのリスト
可変 Difficulty Target PoWの難易度
可変 Nonce ナンス値(後述)

ブロックハッシュ

ブロックをユニークに指定するためのID。ブロックヘッダーにSHA256ハッシュを2回かけたアウトプット(32bytes)。各ブロックには前のブロックのブロックハッシュが含まれるが、そのブロック自体のブロックハッシュは含まれない。

Genesisブロック

ビットコインネットワークの最初のブロックをGenesisブロックといい、2009年1月4日に作成された。Genesisブロックはクライアントソフトにハードコードされており、Coinbaseトランザクションに2009年1月3日のタイムズ紙の見出し文字列が入っている。

ブロックチェーンの耐改ざん性

ブロックヘッダーには、マークルルート(マークルツリーのルート)がふくまれる。つまり、任意のブロックに含まれるトランザクションを1つでも改ざんすると、そのブロックのブロックハッシュが変わる(ブロックヘッダーが変わる=ブロックハッシュが変わる)。

ブロックハッシュは次のブロックに保存するため、改ざんしたブロック以降のブロックの内容をすべて連鎖的に書き換えなければデータとして矛盾が生じてしまう。PoWの仕組み上、ブロックを書き換え続けるのは現実的に不可能なので、ブロックチェーンのデータを改ざんするのは困難である。

マイニングとコンセンサス

Proof of Work(PoW)

ビットコインではPoWというコンセンサスアルゴリズムを採用している。これはブロックの作成に一定の計算量(=コスト)を支払うことを強制させる仕組み。

成功時にはビットコイントークンが得られるというインセンティブと併せて、間違ったブロックを生成するモチベーションを下げ(コストを払って悪意のあるトランザクションを仕込んでも他のノードに却下される)、正しいブロックを生成するモチベーションを上げる(マイニング報酬+トランザクション手数料)。

分散化コンセンサス

中央集権者なしにブロックの『正しさ』に『合意』する仕組みとして、以下の4要素がある。

  • 独立したトランザクション検証: どこか他のノードを頼るのではなく、各ノードがそれぞれ検証する
  • 独立したトランザクション集積: マイナーノードはブロックに入れるトランザクションを自由に決めてよい
  • 独立した新規ブロック検証: マイナーが提案した新規ブロックは、各ノードがそれぞれ検証する
  • 独立したブロックチェーン選択: 各ノードで最長のブロックチェーンを正しいとみなす

マイニングノード

ブロックの作成を行っているノードで、マイナーとも呼ばれる。
ブロック生成に成功すると新たなビットコイントークンが発行されるため、そのプロセスをマイニング(採掘)とよぶ。

マイニング(ブロック作成)が成功すると、マイニング報酬(新たに発行されるBTC)+トランザクション手数料(そのブロックに含まれるトランザクションのトランザクション手数料の合計値)を受け取ることができる。

大きく以下の流れでブロックを生成する。

  1. トランザクションプールから、ブロックに入れるトランザクションを選ぶ(基本的には容量単価の高いトランザクションを優先)
  2. マイナー自身への報酬トランザクション(Coinbaseトランザクション、Unlocking Scriptがない代わりに任意のデータを追加できる)をブロックの最初のトランザクションとして追加する
  3. トランザクションリストからマークルツリーを作成し、マークルルートを算出する
  4. ブロックヘッダーの必要情報をうめる(バージョン、前ブロックハッシュ、マークルルート、タイムスタンプ)
  5. PoWのdifficultyターゲット条件に合致するナンスを求める(マイニング)
  6. 上記の値からブロックヘッダーを生成する

Difficultyターゲットとマイニング

マイニングとは、ブロックハッシュ(ブロックヘッダーのダブルハッシュSHA256を2回)がDifficultyターゲット未満になるナンス値(4bytes)を探すプロセス。基本的にしらみつぶしに計算するしか手段がなく、解が求まる=それだけの計算量がつぎ込まれたと考えることができる(PoW)。

Difficultyターゲットは4bytesで表現され、うち1バイトが指数(exponent)、残り3バイトが係数(coefficient)。

target = coefficient * 2^{(8 * (exponent - 3))}

ターゲットが小さいほど、ナンス値を見つける難易度はあがる(条件が狭くなるため)。

Difficultyターゲットはビットコインネットワーク上で定期的(2016ブロック、だいたい2週間)に調整される値で、ブロック生成時間が10分に保たれるようになっている。

ナンス値の領域は4bytesで、表現できる正整数の最大値はだいたい43億。ブロックハッシュのインプットの候補数は垓などのオーダーのため、ナンス値で取りうる値をすべて調べても条件を満たせない可能性がある。

その場合、以下のようにブロックヘッダの他の要素を変更することがある。

  • マイニング報酬トランザクション(Coinbaseトランザクション)に含められる任意のデータ領域を使う(Extra Nonce)
  • タイムスタンプを変更する(数秒から数十秒ずれても問題ない)
  • ブロックに入れるトランザクションや、その順序を変更する

チェーンの組み立てと選択

各ノードは受け取った新規ブロックについて、定められたルールに則っているか検証する。問題がなければ、チェーンに追加し他のノードに伝播する。

各ノードは3つのブロックセット(チェーン)をもつ。

  • メインチェーン: 最大累積ディフィカルティをもつ(最長チェーン)
  • セカンダリチェーン: メインチェーンから分岐したチェーン、将来的にメインに置き換わる可能性がある
  • オーファンブロックプール: 親が不明なブロック

ブロック内の『前ブロックハッシュ』をみて、どのチェーンにつなげるか判断する。セカンダリチェーンを伸ばすブロックを受け取った場合、結果としてメインチェーンが置き換わることがある。

マイニングプール

複数のマイナーを集めてマイニングをし、報酬を分配する仕組み。管理者がいるマネージドプール、管理者のいないP2PPoolがある。

特定のマイナーが高いハッシュレートをもつ(他のマイナーノードと比較して大きな計算力を持っておりマイニングが成功しやすい)場合、先端のブロック伸長をある程度操作できる。これを51%アタックと呼び、ビットコインにおけるファイナリティとされる6ブロック以上を無効化できる可能性がある。

まとめ

第2回の最初に挙げた、アリスがボブに0.01BTC送金する例をおさらいすると、以下のようになる。

  1. (アリスのウォレット)アリスのUTXOをインプットとし、Locking Scriptに対して自身の秘密鍵からUnlocking Scriptを生成する
  2. (アリスのウォレット)ボブへの送金アウトプットを作成する。ボブのアドレスから公開鍵ハッシュを算出し、Locking Scriptとする
  3. (アリスのウォレット)トランザクション手数料を設定する
  4. (アリスのウォレット)おつりを自身への送金アウトプットとする。自身のアドレスから公開鍵ハッシュを算出し、Locking Scriptとする
  5. (アリスのウォレット)作成したトランザクションをビットコインネットワークにブロードキャストする
  6. (各ノード)受け取ったノードはそれぞれトランザクションを検証し、問題なければトランザクションプールにいれ、隣接ノードに伝搬する
  7. (マイナーノード)トランザクションプールからトランザクションを選択し、ブロックにいれる
  8. (マイナーノード)自身へのCoinbaseトランザクションを作成する
  9. (マイナーノード)Difficultyを求める
  10. (マイナーノード)マイニングを行い、ナンス値を求める
  11. (マイナーノード)作成したブロックをブロードキャストする
  12. (各ノード)ブロックを検証し、問題なければチェーンにつなげ、隣接ノードに伝搬する
  13. (各ノード)メインチェーンの先端ブロックとして登録する
  14. (ボブのウォレット)受け取ったブロックの中に、自分あてのトランザクションが含まれていることを確認する

第4回ここまで

Discussion