ブロックチェーンのマイニング模擬実験

Interface8月号のブロックチェーン特集をちょこちょこ読んでいる。

その中のマイニングの体験が面白かったのでメモしておく。

マイニング

マイニングとは、ブロックチェーン上に新規ブロックを作成するための作業。

実際何をやっているかというと暗号学的ハッシュ関数を用いてハッシュ値を計算している。
ハッシュ値の入力は、前のブロックのハッシュ値と未承認の取引履歴のハッシュ値、そしてナンスと呼ばれる32ビットの数値の3つ。
新規ブロック生成の条件は、そのブロックのハッシュ値がある値以下(例えば0が16個並ぶ)となるようなブロック。

マイニング実施者(マイナー)は、ある数以下のハッシュ値(例えば0が16個並ぶ値)を見つけるため、ナンスをランダムに変化させてひたすらハッシュ値を計算する。
条件を満たすナンスを発見できたらマイニング成功となり、マイナーはマイニング報酬を得ることができる。

Pythonによるマイニングの体験

ナンス値を変えてある値以下(先頭文字に0が複数並ぶ)のハッシュ値を見つける。
コードはInterface8月号のコードを一部改変し使用している(ほぼ引用)。

なお、python3.7.1を使用した。

まずは、先頭4文字が0になるハッシュ値を見つけてみる。

import random
import hashlib
import re

transaction_1 = "A -> B 1BTC"

def text2hash(mynonce):
    hash_object = hashlib.sha256(transaction1.encode() + str(mynonce).encode())
    chk = re.match('0000', hash_object.hexdigest())
    if chk != None:
        print("Nonce: " + str(nonce))
        print("HASH: " + hash_object.hexdigest())
        print("=================================")

max_nonce = 10**7
extract_nonce_num = 10**6 

nonce_list = random.sample(list(range(0, max_nonce)), k=extract_nonce_num)
for nonce in nonce_list:
    text2hash(nonce)

実行すると以下のような結果になった。すぐ計算結果がでた(1秒もまってない)。

結果を見るとたしかにハッシュ値の先頭4文字が0になっている。
ハッシュ値全体からすると、先頭4文字が0になる確率は16^60/16^64 = 1/16^4 = 1/65536だから大体0.0015%くらい。
今回、100万個のナンスから12個の条件を満たすナンスを見つけたから確率は12/10^6で、大体0.0012%くらいなので整合的かな。

Nonce: 6487403
HASH: 00006660c4c89abf1cc9654dff2a5ffac1ed65e7f0d9d43d008924a5d775f6f5
=================================
Nonce: 8845617
HASH: 00005943b43aa3f90987d07d6d6755af11ed20e4096ad5ed30ba466653f8aff1
=================================
Nonce: 8949731
HASH: 000015497ca43abb7e07322361be25955e83dac3f60014a0d253800513ae7092
=================================
Nonce: 7875493
HASH: 0000109c55bb3ae22deba78eccc3fe7ae5e259f2f3f47f407d35ae00a530ef79
=================================
Nonce: 6319689
HASH: 000023b6c8e4f9925c28bb749b7e2b07850471f852e1dfa76615abe0c57a763c
=================================
Nonce: 1908741
HASH: 00002634d326f64212aaf6f15b2ea60fd69a0d6c1ef4c8f8c2f3b596f5b83bd5
=================================
Nonce: 1739868
HASH: 0000bd16e990309b203ad6b620e2f59c75747d2fc91a7a6e8d52e958ae02c275
=================================
Nonce: 1579836
HASH: 00009958c87100b48c79e8be3602a5ba94150c5454ad3a9a1b43ce75081fa581
=================================
Nonce: 3768602
HASH: 00005cddc0bac1e2d6c3825bef4a4edc2c0901531d4039822857583bf3cbbbe7
=================================
Nonce: 7397948
HASH: 0000cc416e9872b5af5b45bbf94ba1dbaec984b5f80b7ee86c1268d7ab77dcf3
=================================
Nonce: 2561779
HASH: 0000c4137ca7636f9475069585f170271a899de1c55f20c56507f8d597403b0f
=================================
Nonce: 8532683
HASH: 000076388f9767d973ce8090bb3de94759c73f93743d880adbe096573bb3375a
=================================

次に、先頭5文字が0になるナンスを見つけてみる。

コード内のtext2hash関数内のパラメータchkの値を変えて実行する。

何回か実行すると、条件を満たすナンスが下記のように1件発見できたり、できなかったりする。大体0~2個くらいの発見数。

先頭文字の0を一つ増やすと条件を満たすナンスを見つける確率は16分の1に減るので、先程の結果(発見したナンスの個数:12)と比べるとまあ整合的かと思われる。

Nonce: 4196833
HASH: 000002e0c4d4158f51626be52ea8a53da9bc55cba1a272cfc9509b2548b1889e
=================================

ビットコインでのマイング

ビットコインでは先頭文字が16個(難易度によって増減するが)の0になるハッシュ値を見つけなければならない。
条件を満たすナンスを見つける確率はめちゃくちゃ低い。確率は、1/16^16。約0.00000000000000001% (10^-17 %)

マイニングは大変ってことがよく分かった。勉強になりました。