なぜビットコインなどのブロックチェーンでマイニングをするとお金が支払われるのか、について簡単に説明します。 ちなみに私はブロックチェーンへの攻撃方法について考える側の人なので、仮想通貨やりたいとか、マイニングしたいとかそういう人ではないので悪しからず。
一応、文中で使う言葉の確認です:
- ネットワーク … ブロックチェーンの分散台帳技術におけるネットワークのこと
- ノード … ネットワークに参加しているパソコンのこと。ブロックの検証・生成・追加などを行う
- ブロック … トランザクション(取引)をまとめたもの
- ナンス … nonce (Number used once の略) は、一度だけ使用される使い捨ての数字のこと
ブロックの構造
まず、ビットコインのブロックの構造は次のようになっています1。
- ブロック
- マジックナンバ … 識別用番号
- ブロックサイズ … ブロックの大きさ
- ブロックヘッダ
- バージョンナンバー
- 前のブロックのハッシュ値
- マークルルート … このブロックの全てのトランザクションからハッシュ木を作ったときのルートハッシュ
- ブロックを作った時刻
- ブロックを作る難易度 … このブロックのハッシュ値の先頭の 0 の数
- ナンス … このブロックのハッシュ値の先頭が 000…0 となるもの
- トランザクションカウンタ … トランザクション(取引)の数
- トランザクション … トランザクション(取引)の一覧
ブロックを作るには、このブロックのハッシュ値の先頭が 000…0 となる「ナンス」を見つける必要があり、最初に条件を満たすナンスを見つけたノードにブロックを追加する権利が与えられます。そして、ブロックを追加したノードにはマイニング報酬が支払われます。
余談ですが、改竄防止のおいて重要なのは「前のブロックのハッシュ値」を求めることです。全てのブロックが前のブロックのハッシュ値を持っていることで、改竄を防ぐことができるようになります。
ブロックが作られるまでの流れ
ブロックが作られるまでの大まかな流れは以下の通りです。
- トランザクション(取引)発生
- トランザクションはトランザクションプールに貯められる
- 10分ごとにマイナーがトランザクションプールからトランザクションを集める
- 前のブロックのハッシュ値とルートハッシュを計算する
- このブロックのハッシュ値の先頭が 000…0 となるナンスを見つける(この作業が一番時間がかかる)
- 条件を満たすナンスを最初に見つけたマイナーがブロックを追加できる(Proof-of-Work)
- マイナーに報酬が仮想通貨で支払われる(自分の作ったブロックの一番最初のトランザクションで支払われる)
次はブロック作成について例を使いながら説明していきます。
ブロックの作成とマイニング
ブロックチェーンは分散台帳技術なので、複数のノードでブロックが作られるとチェーンが分岐してしまいます(フォーク)。フォークした場合はチェーンが長い方を正当なブロックとするというルールがありますが、頻繁にチェーンが発生しないようにするために、ブロックを作る難易度をあげる対策が取られています。
一方で、ブロックを作る難易度が高すぎてブロックが数時間後に追加されるようになると、トランザクションが確定するまでに時間がかかってしまい、送金などの利便性が悪くなります。
そこでビットコインでは10分に1つのブロックが作られるようにし、ブロックを作る難易度も今日のコンピュータ資源の計算速度などに合わせて、難易度が調整されています。
ブロックの作成にはブロックを作る難易度に合った条件を満たす、ナンスの見つける必要があります。 ブロックのハッシュ値の先頭に $n$ 個の 0 が並ぶようなナンスが必要ですが、 この $n$ の値がブロックを作る難易度になります。
適当な例で計算してみましょう。例えば、計算を簡単にするためにブロックの構造が「blockheader + nonce + transaction」というものだとします。blockheader と transaction にはそれぞれ「hogehoge」と「fugafuga」という内容が書かれているとします(適当ですが)。 では、ブロックを作る難易度として $n = 4$ としてみましょう。つまり、求めたハッシュ値の先頭の 4 文字が 0 になるようなナンス(nonce)を見つけることが目標になります。 これを見つける Python は次のようになります。
import re
import hashlib
blockheader = b"hogehoge"
transaction = b"fugafuga"
for i in range(100000):
# ナンスは数字をバイト列に変換したもの
nonce = i.to_bytes(4, byteorder='big')
# ブロックの作成
block = blockheader + nonce + transaction
# ブロックのハッシュ値をSHA-256で求める
res = hashlib.sha256(block).hexdigest()
# ハッシュ値の先頭4文字が0になっているか
if re.match(r'^0000.*', res):
print(i, block, res)
break
実行すると次のようになります。 左から「ナンス」「ブロックの中身」「ハッシュ値」です。
32505 b'hogehoge\x00\x00~\xf9fugafuga' 0000863b42e71c357a3a21365b3749efa2adb1473922f22372b77e8f196ec88d
ハッシュ値(0000863b42e71c357a3a2…)の先頭が 0000 となるようなナンス(32505)を見つけることができました。 $n=4$ だとすぐに計算が終わりますが、実際には難易度が $n=18,19$ とかになっていて、簡単にはナンスを求めることができないようになっています。
余談ですが、ビットコインで使用されるハッシュ関数は SHA-256 と RIPEMD-160 です。 これらのハッシュは GPU で計算するのに向いているためです 2。 今回のプログラムでは SHA-256 をハッシュ関数として使いました。
マイニングはこのように、ナンスをどんどん変更させてハッシュ値を計算していきますが、大量の電気を消費して永遠と計算してはゴミのような結果を出し続けるところを、一獲千金を狙う採掘者(マイナー)が永遠と土を掘り続けてゴミのような結果を出し続けるのになぞらえて、マイナーやマイニングという単語が生まれたと言われています。 もちろん、条件を満たすナンスを見つけることができれば報酬が得られ、大金を手にすることができますが…
マイニング報酬がもたらす安全性
ブロックチェーンのネットワークはインターネットを通して繋がっているので、世界中の人がブロックの追加によってマイニング報酬を得ることができ、より一層マイニング競争に拍車がかかっています。実は、このことはブロックチェーンの安全性をも高めています。
ビットコインに対する攻撃として51%攻撃というものがあります。偽のトランザクションを加えたブロックを作り、そのブロックをチェーンに加えることでフォークを発生させ、ネットワーク全体のマイニング速度よりも早くナンスを求め、次々とチェーンを伸ばすことで正当なブロックにしてしまう攻撃です(ネットワーク全体の51%以上の計算能力を支配しているところが名前の由来)。
ですが、この攻撃をするためには非常に膨大な計算力と、そのための大量の資金が必要です。 また、偽のトランザクションを含むブロックが混入されたことが知られれば、その仮想通貨の価値は下がり、せっかく不正をして得たお金の価値が下がってしまうことになりかねません。 なので、膨大な計算力を持っているのなら、それをマイニングに使ってマイニング報酬で儲ける方が、ローリスクハイリターンとなるので、不正をする動機がなくなり、結果としてブロックチェーンの安全性を保つことができているのです3 4。
まとめ
- マイニングとは、ブロックを作成すること
- ブロックが簡単に作れるとフォークが頻発するので、ブロック作成には適切な難易度が設定されている
- 「ブロックチェーンが正しく機能するため」と「51%攻撃をする動機を減らすため」にマイニング報酬が支払われている
-
岡嶋裕史『ブロックチェーン 相互不信が実現する新しいセキュリティ』, 講談社, 2019 ↩
-
SHA-256はGPUで計算するのに向いているので、機械学習といいマイニングといい、GPUを作っている会社はとても好調のようです ↩
-
マイニング報酬はブロックの一番最初のトランザクションで支払われるので、いくらなのか確認することができる。2019/05/14 に作成されたブロックを見ると5、約 13 BTC(執筆時のレートで日本円で約1100万)のマイニング報酬が支払われたことになる。 ↩
-
ただし、マイニング報酬には半減期が設定されており、ブロックが伸びるほど報酬は少なくなっていく。最近では「マイニング報酬が限りなく0に近づいたとき、ブロックチェーンは正しく機能しているのか&それでも安全性は保たれるのか」という議論が専ら盛んに行われている ↩
-
ブロックチェーンを可視化するサイト:chainFlyer | Blockchain Explorer ↩