Published Date : 2021年7月15日6:46

008 Pythonで遊ぶ (ノンス 2)
008 Playing with Python (nonce 2)


This blog has an English translation


ニコニコ動画にアップした動画のまとめ記事です。

This is a summary blog post about a video I uploaded to NicoNico.

細かい部分は動画を参考にしてください。

Please refer to the video for details.


目次

Table of Contents




① 動画の説明
① Video Description



前回の続きです。

Continued from last time.

このことから分かるのは、ゼロの数が多くなると計算に時間がかかること、ノンスの値も大きくなること、そして複数のノンスが存在していることです。

This tells us that the more zeros there are, the slower the calculation, the larger the nonce value, and there are multiple nonce.

しかし最初に計算に使われるハッシュ値が異なれば、ノンスの値は小さくなったり大きくなったりと変動するでしょう。

However, if the hash value used for the first calculation is different, the nonce value will vary from small to large.

それを踏まえてアルゴリズムを少し変えてましょう。

So let's change the algorithm a little bit.

数多の採掘者が常に計算を行っていると仮定します。

Assume that a number of miners are constantly making calculations.

一つの計算作業に対して、10分程度で計算が終わるようにオフセットを設定します。

For each calculation task, set the offset so that the calculation can be completed in about 10 minutes.

そのオフセットを基に一組ずつからなる配列を用意します。

An array of pairs is prepared based on the offset.

それをランダムモジュールを用いて、ランダムに一組を選びだし、その組の範囲内で計算を行うようにします。

It uses a random module to select a random set and perform calculations within that set.

こうすれば、採掘者の数が多いほどノンスを制限時間内に見つけられる確率が上がります。

This way, the more miners you have, the more likely you are to find Nonce within the time limit.

数人の採掘者の内、少なくとも一人はノンスを見つけることができるようにするわけです。

So that at least one of the several miners can find Nonce.

参加者が多ければ多いほど、その確率は大きくなります。

The more participants, the greater the probability.

つまり、10分以内に100人のうち誰かが当たるくじ引きのようなものにする。

In other words, It's like a lottery in which one of 100 people can win within 10 minutes.

# 10分以内に100人のうち誰かが当たるくじ引きのようなものにする。
# It's like a lottery in which one of 100 people can win within 10 minutes.
"""
[(0, 300000000),
(300000000, 600000000),
(600000000, 900000000),
(900000000, 1200000000),
(1200000000, 1500000000),
(1500000000, 1800000000),
(1800000000, 2100000000),
(2100000000, 2400000000),
(2400000000, 2700000000),
(2700000000, 3000000000),
(3000000000, 3300000000),
(3300000000, 3600000000),
(3600000000, 3900000000),
(3900000000, 4200000000),
(4200000000, 4500000000),
(4500000000, 4800000000),
(4800000000, 5100000000),
(5100000000, 5400000000),
(5400000000, 5700000000),
(5700000000, 6000000000),
(6000000000, 6300000000),
(6300000000, 6600000000),
(6600000000, 6900000000),
(6900000000, 7200000000),
(7200000000, 7500000000),
(7500000000, 7800000000),
(7800000000, 8100000000),
(8100000000, 8400000000),
(8400000000, 8700000000),
(8700000000, 9000000000),
(9000000000, 9300000000),
(9300000000, 9600000000),
(9600000000, 9900000000),
........................,
........................,
]"""

この方法は個人の完全なる思いつきですので、しつこいようですが、厳密なノンスの求め方を知りたい人は各自で調べてください。

This method is a complete personal thought, so it may seem persistent, but if you want to know exactly how to get a nonce, look it up yourself.

一つ一つの動作をPythonのREPL(対話型ウィンドウ)で確認してみましょう。

Let's see how each one works in the Python REPL (interactive window).

ではスクリプトを試してみましょう。

Let's try the script.

ビットコインエクスプローラーで過去のブロックを調べてみましょう。

Let's check the past blocks with Bitcoin Explorer.

ビットコインの初期のブロックを見てみましょう。

Let's take a look at the early blocks of Bitcoin.

ノンスによって導かれたハッシュ値の先頭のゼロの数は8個です。

The hash value derived by the nonce has 8 leading zeros.

一方、最近のハッシュ値の先頭のゼロの数は19個となっています。

Recent hash values, on the other hand, have 19 leading zeros.

つまり、初期の頃と比べると採掘に必要な計算量が増加していることが分かります。

In other words, the amount of calculation required for mining has increased since the beginning.

ビットコインエクスプローラーを眺めていると、難易度とビットと呼ばれるパラメーターがあることが確認できます。

If you look at the Bitcoin Explorer, you can see there are parameters called difficulty and bits.

今回のスクリプトでは物事を単純にするためゼロの数ということで説明していました。

In our script, we looked at the number of leading zeros as the hash value we needed to simplify things.

実際にはこのビットと呼ばれるパラメーターを使って目標値を生成し、その値よりも低いハッシュ値を計算することになります。

In practice, you use a parameter called this bit to generate a target value and compute a hash value lower than that value.

そして、難易度はその求めるべき値を見つけるのがどれだけ難しいかを表す指標になっています。

The difficulty is an indicator of how difficult it is to find the desired value.

では難易度とビットと目標値についてPythonでスクリプトを書きながら理解していきましょう。

Now you'll learn about difficulty, bits, and target value by writing a script in Python.

このハッシュ値を16進数表記としてみれば、整数に直せますよね。

This Hash value can be converted to integers when converted to hexadecimal notation.

hash_vstr = 'da8b70ca315adfce5db80b35129685357748488b6a0aa11f549d42083bc4d8e1'
hash_int = int(hash_vstr, 16)
hash_int
98850571179854021181634014274774554575893887225100812692452879611060384225505
hash_hexstr = hex(hash_int)
hash_hexstr
'0xda8b70ca315adfce5db80b35129685357748488b6a0aa11f549d42083bc4d8e1'
hash_vstr == hash_hexstr[2:]
True

そう考えれば直観的に先頭のゼロの数が多くなれば、その値はどんどん低い値になっていることが理解できると思います。

So you can intuitively see that the more leading zeros there are, the lower the value gets.

hash_vstr2 = '000070ca315adfce5db80b35129685357748488b6a0aa11f549d42083bc4d8e1'
hash_int2 = int(hash_vstr2, 16)
hash_int2
778446697753094437269000710492370893645646600558842423377467342185617633
hash_int > hash_int2
True

0xda8b70ca315adfce5db80b35129685357748488b6a0aa11f549d42083bc4d8e1 > 0x000070ca315adfce5db80b35129685357748488b6a0aa11f549d42083bc4d8e1
True

例えば目標値が[abc]という16進数なら、整数に直すと2748です。

For example, if the target value is [abc] in hex, it is 2748 when converted to an integer.

int('abc',16)
2748

これよりも低い値の範囲は[000からabb]となり、整数に直すと[0から2747]です。

Values lower than this range from [000 to abb], and to integers they range from [0 to 2747].

int('abb',16)
2747
int('abc',16) > int('abb',16)
True

仮にハッシュ値が12ビットからなる[000からfff]しかないなら2の12乗の4096通りのパターンがあることになります。

If the hash value consists of only 12 bits [000 to fff], there are 4096 possible patterns (2 to the power of 12).

16進数表記で計算するなら16の3乗で4096通りです(1バイトは8ビットです)。

In hexadecimal notation, 16 raised to the power of 3 is 4096 (1 byte is 8 bits).

2 ** 12
4096
16 ** 3
4096

そうすると[abc(2748)]より低い値が見つかるの確率は、全体の4096個の中から[000からabb]の2747個を見つけるわけですから、[2747/4096]で約67%。

Then the probability of finding a value lower than [abc (2748)] is about 67% for [2747/4096], because we find 2747 of [000 to abb] out of the total 4096.

2747/4096
0.670654296875

そして何度も説明しますが、1ビットでも中身が変わればハッシュ値はまったく異なる数値になります。

And, as I'll explain over and over again, if even a single bit changes, the hash value will be a completely different number.

from hashlib import sha256

sha256('00000001'.encode('ASCII')).hexdigest()
'ae5ce162888ee3ebe974976cac5ab94a3f55049f8515884883d579fb3fa378d2'

sha256('00000002'.encode('ASCII')).hexdigest()
'5c6bed0d94b9be8afbc5c8cac1e9d4be03f556917c2611ec56f4e6f341ef60d9'

そしてハッシュ値の特性から導きたいハッシュ値をピンポイントで計算するのは非常に困難です。

Also, given the characteristics of the hash value, it is very difficult to calculate the hash value you want to derive exactly at once.

ですから、ハッシュ値の基となるものの中身を1つずつ変えていき総当たりで求めていくしかありません。

Therefore, we have no choice but to change the contents of the base hash value one by one and calculate the desired hash value one by one.

sha256('00000003'.encode('ASCII')).hexdigest()
'50a9b9163ebb829080aecf9a7a5990715de9fd63d48e3ea3734f6bd77aa3df07'

sha256('00000004'.encode('ASCII')).hexdigest()
'cfb51ebe5fc1cd1482a9a65716dad756b1374b3bc507a712e416947eeb51a058'

sha256('00000005'.encode('ASCII')).hexdigest()
'9294ef4a2f92785dd933c51b99f2aabd0f8da54a2536349b46c708039eff4c9b'

sha256('00000006'.encode('ASCII')).hexdigest()
'405391cdcba508299713f0df3491fc39ee8044c599aac506de3456b6b3dd79e6'

例えば目標値が[abc]ではなく、[01e(30)]というとても小さい値だとします。

For example, suppose the target value is not [abc], but a very small value of [01e(30)].

In [1]: int('01e', 16)
Out[1]: 30

目標値より低い値のハッシュ値を見つけられる確率は[29/4096]で0.7%となり、かなり低い確率になりました。

The probability of finding a hash value that is lower than the target value is [29/4096] at 0.7%, which is quite low.

29/4096
0.007080078125


以上です。お疲れ様です。

That's all. Thank you for your hard work.