前回の記事で、マイニングとは「帳簿の次のページを書く係を決める、計算が要るくじ引き」と説明しました。ただ、言葉だけだとやっぱり理解しにくいです。

そこで、ターミナルで「小さいマイニング」をやってみました。使うのはsha256sumというコマンドです。

sha256sumが作るハッシュ値

sha256sumはLinuxのコマンドで、SHA-256というハッシュ計算をしてくれます。ビットコインなど多くのブロックチェーンのマイニングでも、このSHA-256が使われています(前回の記事で触れたMoneroのRandomXのように、コインによっては別の種類のハッシュ計算を使います)。

sha256sumが何をするかというと、「何らかの値を受け取って、64桁の英数字(ハッシュ値)を1つ出す」という計算です。

実際にsha256sumを使ってみます。「何らかの値」には、適当に"hatake"という文字列を使います。

# sha256sum に "hatake" を渡して計算する
$ echo -n "hatake" | sha256sum
f4f04fcdce45e8fe289499c9d762749c8ef422808e7079031c44e6d638f18e20  -

f4f04・・・という64桁の英数字が返ってきましたね。(echo-nは末尾に改行を付けないためのオプションです。忘れると改行つきの値を渡すことになり、別のハッシュ値になりますのでご注意を)

次は、値をすこーしだけ変えて、“hatake!“を渡してみます。

# sha256sum に "hatake!" を渡して計算する
$ echo -n "hatake!" | sha256sum
21823b187065dbf35ecf1cff7ae355269b5213139e3738c63e05eeddb0b04713  -

21823b・・・になりました。先ほどと全く違う文字列ですが、ちゃんと64桁です。

もう一度、最初の"hatake"でやってみましょう。

# sha256sum に "hatake" を渡して計算する
$ echo -n "hatake" | sha256sum
f4f04fcdce45e8fe289499c9d762749c8ef422808e7079031c44e6d638f18e20  -

f4f04・・・最初と全く同じ64桁が出てきました。

sha256sumを経由して出てくるこの64桁の英数字には、以下の特徴があります。

  • 「元の値」と出てきた64桁はペアになっている(何度やっても同じ結果となる)
  • 「元の値」が少しでも違えば、出てくる64桁も変わる
  • 出てきた64桁から逆算することはできない(元の値を計算で割り出す方法はない)
  • そのため、「こんな64桁の英数字を出したい」と意図して出力することはできない

sha256sumから出る64桁は元の値とペアである、という点が重要です。指紋のように、他と被ることはまずありません。

「先頭がゼロで始まるハッシュ値」を探す

くじ引きには、sha256sumのようなハッシュ計算が使われるということまで何となくわかりました。次は条件を決めましょう。

くじ引きマシン(sha256sum)によって出た値(ハッシュ値)の「先頭が000だったら、アタリ!」とします。

そして、sha256sumに渡す元の値が必要ですね。マイニングで言うと、送金などのコインの手続きがまとまったデータがこの元データにあたります。

ただし!ここで先ほどの「元の値と出てきた64桁はペアであり、何度やっても同じ結果となる」を思い出してください。

sha256sumに渡す元の値が同じなら、何度sha256sumに入れても、結果がハズレなら永遠にハズレです。

となると、アタリを引くためには元のデータを変える必要がありますよね。

でも、送金などのコインの手続きのまとまりは改変できません。というか改変してはダメです。

そこで役に立つのがノンス(nonce)です。ノンスとは、意味を持たない使い捨ての数字のことです。

ノンスとは

ノンスは意味を持たない数字なので、内容はなんでも良いのです。この自由なノンスをsha256sumに渡す元データに加えます。そうすると何が起こるでしょう。

さきほどまで

sha256sum(変更不可な元の値)-- 結果 -->  固定値。一度ハズレると永遠にハズレ

こうなっていたのが

sha256sum(変更不可な元の値 + ノンスをコロコロ変える)-- 結果 -->  000が出るまで計算できる!

なんと、ノンスのおかげで大事な元の情報をそのままに、sha256sumに渡すデータを変えることができました・・・!

ノンスをコロコロ変えるという点がポイントです。アタリのハッシュ値が出るまでひたすらノンスを変えて計算しまくります。このひたすら計算しまくるのがマイニングです。

やっとミニマイニング開始

ミニマイニングに必要な知識が揃ったところで、いよいよやってみましょう。

主な登場人物は以下です。

  • くじ引きマシン:sha256sum
  • 元データ:”hatake
  • ノンス:0スタート

全員配置につきました。以下のコードで、ノンスを0、1、2・・・と変えながら、000始まりのハッシュ値が出るまでくり返し計算します。

# アタリの条件(先頭3桁がゼロ)
target="000"
# ノンス(0スタート)
n=0

while :; do
  h=$(printf 'hatake%d' "$n" | sha256sum | cut -c1-64)
  case "$h" in ${target}*) break;; esac
  n=$((n+1))
done

echo "nonce=$n hash=$h"

実行結果は・・・

nonce=10328 hash=000f56303cb921cac78fee7ee9e6748fb69b56762405194fc733de3f487ce7b9

10328というノンス(0から数えて10,329回め)で、000始まりを引き当てました!

難易度 = ゼロの桁数

マイニングの難易度は、ハッシュ値に求められる「先頭のゼロの桁数」によって変わります。

ここで、「先頭1桁が0ならアタリ」だった場合で考えてみましょう。

ハッシュ値の1文字1文字は、0〜9とa〜fの16種類のどれかです(16進数といいます)。なので、先頭1桁が0になる確率は16分の1。平均して16回に1回アタリが出るという計算です。あくまで平均ですが。

次に、「先頭2桁が00ならアタリ」に変えてみます。

すると、先ほどは16回に1回アタリだったのに、その16倍256回に1回という計算になります。

もう1つ増やして「先頭3桁が000ならアタリ」ならどうでしょう。

なんと、4,096回に1回です。求められるゼロの桁数が増えるたびに難易度はうなぎのぼりです。

しかし、これはあくまで単純計算です。実際にはバラツキがあるので、運が悪ければ試行回数が多くなり、強運であれば早くみつかる、ということになります。

今回は、sha256sumを使った小さいマイニングをやってみました。Linuxがあれば誰でも試せるので、マイニングがいまいちよくわからないという方は、ぜひ試してみてください。