一緒に手計算マイニングをやってみよう!🖊#72
#72 Read BTC 2024年10月18日号
こんにちは、もやしししゃもです。
ところで、みなさんはマイニングをしたことがありますか?
僕はBitcoin Tokyo 2024の際にビタキセを購入し、電源とWi-Fiを繋げてマイニングをしています。
→ビタキセのワクワク感とビタキセ部⛏
でも、本当は僕がマイニングをしているのではなく、ビタキセにマイニングをしてもらっています。僕自身はマイニング未経験ということです。
2014年9月の記事ですが、Ken Shirriffさんという方が手計算でマイニングをするという動画と記事が公開されていました。
これを見て、僕も手計算マイニングをやってみないといけないと思いました。日々ファンを回し続けているビタキセの気持ちを理解したいと思います。
上記の記事からもう少し掘り下げて、必要な情報であるブロックヘッダーの準備から、手計算マイニングでかかる時間をざっくり算出しようと思います。より優しく説明しますので、誰でも手計算マイニングできると思います。
↓LNでのチップはこちら(1satoshiに感謝⚡)
moyashamo@walletofsatoshi.com
ブロックヘッダーの準備🧱
ビットコインのマイニングで必要な情報として、ブロックヘッダーがあります。手計算マイニングするには、ブロックヘッダーも手で作ることを考える必要があります。(できるかは置いておいて)
ブロックヘッダーについて、詳しい情報がこちらに記載されいていました。この記事、すごく詳しいので知らないことが色々書いてあって勉強になります。
参考記事:learn me a bitcoin(Block)
ブロックヘッダーの構造は下記のようになっています。
詳細に書くと次のようになります。
Version(4 Byte)
ブロックのバージョン番号
計算などは不要で簡単に手に入る(はず)
Previous Block(32 Byte)
1つ前のブロックハッシュ
例えば866047番目のブロックであれば次に示すもの
00000000000000000000145fd3f0777286bdfb735887c0757ebb6d2e4564bdc2
0がたくさん並んでいて、マイニングを掘り当てた証でもある
ノードに繋がっていたら簡単に手に入る
ちなみに、ジェネシスブロックでは前のブロックがないのでオール0だったみたい
Merkle Root(32 Byte)
ブロックに含まれる全トランザクションの情報郡
全トランザクションをトーナメント的な方式でハッシュして合体していく
手数料順にトランザクションを入れたり、入れ替えたりしていては手計算では無理そう。。
Time(4 Byte)
ブロックが構築されたUnix時間
正確じゃなくてOKらしく、ネットワークの時間中央値の前後2時間以内であればOKとのこと
手計算マイニング勢は涙目の結末があるかもしれない。。(作業が2時間を超えそうなら未来に設定しましょう)
Bits(4 Byte)
ビットコインマイニングのターゲット値を少ない文字情報で表現したもの(約2週間ごとに難易度調整で変わる)
これよりも小さなハッシュを引き当てたら、マイニング成功
現在の値は下記(前半の2つが32 Byteの中のどこか(桁)を示し、後半の4つがターゲットの値が入ってる)
ターゲット:000000000000000000030ecd0000000000000000000000000000000000000000
Bits:17030ecd
2週間ごとに決まるので、手計算でもなんとかなりそうです
Nonce(4 Byte)
Nonceの数値を変えて、マイニングを繰り返していきます
実際のブロックヘッダーがどのようなものかというと、次のようになります。
000000207045159495ece346f01c67f90a8fa08c9b9670aadc5f07000000000000000000d4d941a971209747353bfac1f47a93a5a2725e89dd3d7fb299fd82ef7fdb23bd42981a5b41f8381737467f70
ただの数字の羅列のように見えますが、上記のVersion、Nonceなどが全部含まれています。分解すると次のようになります。(526,591番目のブロックです)
00000020(Version)
7045159495ece346f01c67f90a8fa08c9b9670aadc5f07000000000000000000(Previous Block)
d4d941a971209747353bfac1f47a93a5a2725e89dd3d7fb299fd82ef7fdb23bd(Merkle Root)
42981a5b(Time)
41f83817(Bits)
37467f70(Nonce)
「あれ、Previous Blockは前に0が並んでなくて、後に0が並んでる。」と思われる方もいるでしょう。リトルエンディアンという並びで、Byteを逆順に並べているらしいです。
実際のPrevious Block:000000000000000000075fdcaa70969b8ca08f0af9671cf046e3ec9594154570
ブロックヘッダー:7045159495ece346f01c67f90a8fa08c9b9670aadc5f07000000000000000000
70, 45, 15,という形で、2つずつ後ろから取って並べていきます。
最難関:Merkle Rootをどうするか🌳
Merkle Rootブロックに入れるトランザクションをハッシュして合体していくという行為によって得られます。手計算マイニングで大変なのは、ハッシュ計算です。
そして、しっかりと2回ハッシュするは、奇数個で相手がいなくてもハッシュします。。
例えば、4096(2^12)トランザクションをブロックに詰めるとすると、4095×2=8190回もハッシュ計算する必要があると思われます。(僕の理解が正しければ)
手数料収入はありがたいとはいえ、手計算マイナーには地獄です。
もう、トランザクションを1つだけにしてしまいましょう。その1つは、自分にマイニング報酬を与えるコインベーストランザクションです。1つだけであれば、ハッシュ計算は不要で、トランザクションをそのままMerkle Rootとして使えるみたいです。
コインベーストランザクションは要件があるみたい。ちょっとこれは難しいですが、1回用意したらどうにかなるのかなと思います。
ところで、コインベーストランザクションの記事ページを見ていたら個人的に衝撃的な事実を知りました。
注記:
マイナーがブロック報酬の全額を請求しないと、コインは永久に失われる可能性があります。たとえば、ブロック526,591のブロック補助金は12.5 BTC でしたが、マイナーはコインベーストランザクションの出力で自分自身に 6.25 BTC しか送信しなかったため、実質的に 6.25 BTC を失いました。マイナーがこのようなことを望む理由はありませんが、マイナーがコインベーストランザクションを正しく構築してブロック補助金の全額とブロックに含まれるトランザクションの手数料を徴収しないと、コインは永久に失われる可能性があることを示しています。参照:https://learnmeabitcoin.com/technical/mining/coinbase-transaction/
たしかに、526,591のコインベース報酬を見ると6.25BTCで、前後のコインベース報酬を見ると12.5BTCでした。つまり、将来的に2100万枚あると言われているビットコインについて、一度も生まれてこなかった6.25BTCが存在しているということです。
勝手に報酬が送られるものかと思っていました。コインベーストランザクション、しっかり設定しないといけませんね。
手計算でマイニングの実行🖊
ブロックヘッダーについて調べました。どうやら、ブロックヘッダーの準備では手動でハッシュ計算をせずに何とかなりそうです。
なぜブロックヘッダーにこだわっていたかというと、マイニング計算というのはブロックヘッダーを2回ハッシュ計算することだからです!
さてさて、最新のブロックのマイニングは大変ですので、ジェネシスブロックの次のブロック1についてマイニングをやってみましょう。おそらくサトシが掘ったブロックです。
ちなみに、僕の真似をすれば誰でもマイニングを手計算できます。ぜひ真似してみてください。マイニングの流れは次のようになります。
ブロックヘッダーを手元に準備
ハッシュ計算①:w0~w63の準備
ハッシュ計算①:abcdefghの更新
ハッシュ計算①:残り部分のw0~w63の準備
ハッシュ計算①:abcdefghの更新
ハッシュ計算②:w0~w63の準備
ハッシュ計算②:abcdefghの更新
1回目のハッシュ計算では2周くらいするのでヤバイです。笑
手順1. ブロックヘッダーを手元に準備
まず、すでにブロックとして存在するブロックヘッダーはmempoolからゲットできます。下の方にある詳細ボタンを押すと「ブロックヘッダーの16進値」が獲得できます。
010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e36299
もし、新しくブロックを作りたい方は、先ほど紹介した方法でどうにかブロックヘッダーを作成してみてください。コインベーストランザクションの作り方はしっかり読んでないので、そこが大変そうなイメージです。
あとはハッシュ計算するだけです。ハッシュ計算のシミュレーションとしてオススメのサイトは下記です。
→ https://sha256algorithm.com/
ブロックヘッダーは16進数なので、Hexとしたうえでペーストしてみてください。手計算だけだと不安だと思いますので、答えを見ながらだとやりやすいと思います。
手順2. ハッシュ計算①:w0~w63の準備
さて、ようやく手計算をします。久しぶりにシャーペンと消しゴムを使ったような気がします。
いきなり、w0~w63の準備とは意味不明ですよね。さっきのハッシュ計算シミュレーションサイトが非常にわかりやすいので、画像を元に説明します。
下の画像の左側の「Message block」というのがありますよね。これは、16進数のブロックヘッダーを2進数にしたものです。それらのうち、16行(512 bit)分だけを右側の「Message schedule」へとそのままコピペします。これで、w0~w15は完了です。
そして、w63までは次の計算を元に埋めていきます。
w(n) = w(n-16) + σ0 + w(n-7) + σ1
σ0 = (w(n-15) RightRoate 7) xor (w(n-15) RightRoate 18) xor (w(n-15) RightShift 3)
σ1 = (w(n-2) RightRoate 17) xor (w(n-2) RightRoate 19) xor (w(n-2) RightShift 10)n = 16のとき
w16 = w0 + σ0 + w9 + σ1
σ0 = (w1 RightRoate 7) xor (w1 RightRoate 18) xor (w1 RightShift 3)
σ1 = (w14 RightRoate 17) xor (w14 RightRoate 19) xor (w14 RightShift 10)
はい、なんだかやばそうですね。これをw16~w63まで1つずつやっていくことになります。w16を計算するだけでも、w0, w1, w9, w14を使うので大変です。
実際にw16を手計算したのがこちら。(方眼紙がおすすめです。僕はもってなかったので、印刷してコピー用紙を方眼紙化しました。)
いきなり完成品を見せられても困りますよね。この用紙の進め方は次のようになります。
一番上の塊はσ0の計算、二番目はσ1の計算、三番目はw16の計算
まずは左側の記号を書いていきます
w1, Rr7(w1), Rr18(w1), Sr3(w1):RrはRotate right、SrはShift rightという意味
w14, Rr17(w14), Rr19(w14), Sr10(w14)
w0, σ0, w9, σ1, w16
その後、w0, w1, w9, w14と右回転したり、右シフトしたりした情報を埋めていきます
右回転:書いてある個数分右に回転し、左から戻ってくる
右シフト:書いてある個数分右に移動し、左の空いているところには0で埋める
最後に、上2つはxor計算、下は「+」の計算をします
xor:繰り上げを意識しない筆算のたし算のようなもの
+:繰り上げを意識した筆算のたし算
大変だけど、やればできるという。ただ、まだこれでw16です。さすがにw63まで48回やるのは骨が折れます。一旦ここまでで時間を計ってみました。
w16の計算にかかった時間:16分40秒
w63まで計算した場合の推定時間(x48):13時間20分😲
長すぎる。僕の計算、やり方が遅いだけかもしれません。ぜひ挑戦してみてください(まだ序章ですよ!)
完成したw0~w63の姿がこちら。紙にメモすることさえ大変そうだ。
手順3. ハッシュ計算①:abcdefghの更新
次は、w0~w63をもとに、a,b,c,d,e,f,g,hというそれぞれの記号を更新していきます。下図は大文字になっていますが、このように更新していきます。
図を見てもよくわからないと思うので簡単に説明します。(僕も見た時よくわかりませんでした。笑)
T1 = Wt + Kt + h + Ch(e, f, g) + Σ1(e)
Wt:先ほど出したw0~w63の64個をラウンドごとに入れていく。つまり64ラウンドあります。。
Kt:64個の事前に決められた固定数値。素数64個の立方根(^1/3)の小数部分らしい
Ch(e, f, g):Choice関数と呼ぶらしい。eが0なら後者のgを選択、eが1なら前者のfを選択するという計算
Σ1(e): Rr6(e) xor Rr11(e) xor Rr25(e) 右回転したeをxorする
T2 = Maj(a, b, c) + Σ0(a)
Maj(a, b, c):Majority関数と呼ぶらしい。a, b, cで0と1の多数決。例えばaが1, bが1, cが0なら多数決で1
Σ0(a): Rr2(a) xor Rr13(a) xor Rr22(a) 右回転したaをxorする
a = T1 + T2
b = a
c = b
d = c
e = d + T1
f = e
g = f
h = g
複雑ですね。複雑そうに見えますが、手計算でもできるくらい理解ならできます。御覧の通り、a, eはガラッと変わりますが、b,c,d,f,g,hは1つスライドするだけです。しかしながら、64ラウンドを回すので、a~hが8文字だとするとそれぞれ8周するイメージです。
sha256はハッシュ関数なので情報が復元できないようグチャグチャにされます。(xor、Choice、MajorityなどでWtの情報が粉微塵になります)
ちなみに、Ktは次の64個セットです。これはもう決まっているので、こちらを使う必要があります。(素数64個の立方根の小数部分)
そして、a~hの初期値も決まっています。こちらは素数8個の平方根(^1/2)の小数部分。なんか、素数が好きなんですかね。たしかに、素数であれば平方根、立方根しても小数部分に規則性は出なさそうな気がします。笑
さて、やりますか。
こちらもいきなり完成品をお見せします。
進め方は次のような形です。
上の塊:Σ0(a)、Maj(a, b, c)の計算
下の塊:Σ1(e)、Ch(e, f, g)の計算
まずは左側に記号を並べます
上の塊のa, b, cと右回転したaを3種類書きます
下の塊のe, f, gと右回転したeを3種類書きます
上の塊でΣ0(a)のxor計算、Maj(a, b, c)の多数決をします
下の塊でΣ1(e)のxor計算、Ch(e, f, g)のeが0ならg, eが1ならfをします
完成
右側にnew bなど書いています。b,c,d,f,g,hはこの時点で更新完了です
ふ~。大変でした。Maj関数、Ch関数はいつもと違う計算なので、なんとなく気分転換になります。お待ちかね、かかった時間はこちら。
Σ0,Σ1,Maj,Chの計算にかかった時間:17分6秒
まだ終わりません。a,eを更新します。完成品はこちら。
進め方は下記です。
上から、T1、T2、new e, new aの計算となります
左側に記号を並べます(すべて足し算なので、16進数の足し算に慣れ親しんでいる方は2進数でなくて、16進数でやってしまってokです)
先ほど求めたΣやらCh、固定値のK0や序盤に計算したw0など書き込みます
最後にそれぞれ足し算します(xorと異なり繰り上げがあるので注意)
a, eの更新完了
かかった時間はこちら。
a,e更新の計算にかかった時間:13分57秒
abcdefghの更新1ラウンドにかかった時間:31分3秒
abcdefghの更新を64ラウンドやった場合:33時間7分12秒
寝ずにやっても24時間以上かかってしまう。。笑
最後の一息の計算
おまけに、最後の1周では最後の一息の計算があります。それは、sha256の結果を出す計算です。
てっきり、abcdefghの更新結果がsha256だと思っていましたが違うようです。最後何をするかというと次の計算です。
h0 = h0(aの初期値) + a(64周後のa)
h1 = h1(bの初期値) + b(64周後のb)
・・・
h7 = h7(hの初期値) + h(64周後のh)
地味ですがめんどくさい。これを16進数にして、sha256となります。
同じ計算をしましたが、ココのタイミングじゃなくて、最後のsha256の最終計算のところを手計算しました。そのため、写真の数値は異なっています。(上の画像が正しい)
最後の一息の計算にかかった時間:27分10秒
↑よく見ると、h7のところが0だらけになってますね。マイニング成功の証
最後の一息は、地味に時間もかかります。(まだ終わっていない)
手順4, 5. ハッシュ計算①:残り部分のw0~w63とabcdefghの更新
すっかり終わった気になっていましたが、実はまだ1周目のsha256は完成していません。
手順4. ハッシュ計算①:残り部分のw0~w63の準備
手順5. ハッシュ計算①:abcdefghの更新
思い出してみてください。最初のw0~w63の準備をしたときに使ったのは、ブロックヘッダーの512 bit分だけ。残りの部分も処理してあげないといけません。
512でキリが悪いときは0で埋めます。そして最後にこの情報が何ビットだったかがMessage Blockの右下に書いてあります。(10 10000000の部分)
もう手計算はうんざりです。笑
ちなみに、得られたsha256結果がこちら!まだ全然0が並んでなくて、成功する気がしません。
a76dd73790def7b57776f22fa211d19cf43121a709a37eaeda17230eaac258f5
お得情報:まさかの時短可能🔔
ここに来てお得情報です。
実は、ハッシュ計算①の1周目を2回目のマイニング以降省略できます。(2周目は結局やらないといけない。笑)理由をお伝えします。
ブロックヘッダーの情報を思い出します。
Version(32 bit)
Previous Block(256 bit)
Merkle Root(256 bit)
Time(32 bit)
Bits(32 bit)
Nonce(32 bit)
そして、sha256のMessage Scheduleの性質は512 bitで区切ります。512の区切り位置がどこかというと、Merkle Rootの途中です。
Versionは変わらないし、Previous Blockも同じであれば変わりなし、Merkle Rootはブロックに入れるトランザクションが変わらないなら変わりなし。つまり、下記部分は2回目以降のマイニングでは同じ計算値を使いまわせます。(2回目にはブロックが変わっていそうですが。笑)
変わるのはTimeとNonceですね。こちらはいくら変えても問題ないです。
手順2. ハッシュ計算①:w0~w63の準備
手順3. ハッシュ計算①:abcdefghの更新
しかし、ビットコインのマイニングを考える上で、時短要素は重要だと思いますので、知っておくとお得でしょう。
手順6, 7. ハッシュ計算②:1回目の結果を元に2回目のsha256
さてさて、あとはsha256のハッシュ計算の2周目をします。何の2周目かがこんがらがってしまったらすみません。
手順6. ハッシュ計算②:w0~w63の準備
手順7. ハッシュ計算②:abcdefghの更新
もうこれは同じ要領なので手計算はしません。下記をsha256シミュレーションに入れましょう。
a76dd73790def7b57776f22fa211d19cf43121a709a37eaeda17230eaac258f5
ありがたいことに、sha256の結果は512 bitに収まりますので、2周目のsha256は一発で完了です。
その最後の計算に使ったのが、先ほどもあげた最後の一息の計算です。
大変お疲れ様でした。もしちょっとでも取り組まれた方には拍手をお送りします。これでマイニング経験者と名乗れるでしょう。
sha256の結果はこちら。Block1は誰が掘ったかは不明ですが、おそらくSatoshiでしょう。
最後の方に0が並んでいます。リトルエンディアンなので、これで良いということなのでしょう。Target値はわかっているので下から計算して、0が続かなかったら切り上げもできそうですよね。マシンではそんなに時短にはならないか。
4860eb18bf1b1620e37e9490fc8a427514416fd75159ab86688e9a8300000000
512 bit以上あったブロックヘッダーも上記の通り短くなりました。
Block1のハッシュ値はこちら。たしかにリトルエンディアン。
00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048
手計算マイニング全体にかかる時間⌚
さて、みなさんお疲れ様でした。この記事、こんなに長くなると思っていませんでした。気軽にやることではありません。
手計算マイニングでどれくらい時間がかかるか計算してみましょう。ブロックヘッダーはコインベーストランザクションが0秒で用意されているものと仮定します。
ブロックヘッダーの準備:0秒と仮定(コインベーストランザクションだけならハッシュ計算が不要そうなため)
1回目のハッシュ計算:93時間48分44秒
w0~w63の準備:13時間20分
a~hの更新:33時間34分22秒
残りのw0~w63の準備:13時間20分
a~hの更新:33時間34分22秒
2回目のハッシュ計算:46時間54分22秒
w0~w63の準備:13時間20分
a~hの更新:33時間34分22秒
合計:140時間43分6秒(1日あたり0.17ハッシュ)
2回目マイニングの短縮ver:93時間48分44秒(1日あたり0.255ハッシュ)
1秒ですらなく、1日で0.17ハッシュです。僕の計算が遅いだけと信じたいが、実際どうなのでしょう。試したくもありません。笑
Ken Shirriffさんは1日0.67ハッシュと算出されましたが、w0~w63の準備などもなかったので、もっとかかるのではないかと思います。たぶん
マイニングを手計算するならお触り程度にして、お仕事や家族と過ごしたり、何か特技を身に付ける方が有意義だと思います。140時間もあれば、簡単なピアノの演奏ができたり、本も何冊か読めるのではないでしょうか。
そして、稼働しているビタキセに感謝をして電気エネルギーを注ぎましょう。ちなみにビタキセの性能は「700 Gハッシュ/秒」です。僕の何倍性能が良いかは計算したくもありません。
ちなみに、ブロックに4096トランザクションを入れる場合、Merkle Rootで8190回(4095×2)のsha256をしなければなりません。少なく見積もって46時間×8190!?考えたくもありません。(計算したら43年と出ました。コンピューター作った方が早そう)
まとめ:手計算マイニングは地獄😈
ブロックヘッダーの準備から、手計算マイニング(sha256の手計算)までやってみました。非常に大変でした。
手計算をやってみるのは良いのですが、記事にまとめるのも結構難しかったです。珍しく技術というか、学術的な内容に触れたような気がします。
面白いなと思ったのは、sha256の時短の可能性があることです。512 bitの区切りを利用して前半部分は同じ値を使いまわすこともできます。常識として使われているのか気になります。
他には、コインベーストランザクションの失敗例があったことですね。一度も生まれなかったビットコインがいたことには衝撃を受けました。(ブロック526,591)
そして何より、1回のマイニングに140時間かかりそうというのがわかったのが良かったです。一連の流れをメモすることができて、マイニングの流れを知ることができました。
Nonceが変わるとか、ブロックヘッダーがどう計算に使われているとか、そういうのが実体験を持って理解できました。ぜひ興味があったらシミュレーションを見ながら手計算をしてみてください。僕が貼った写真の繰り返しです。
今回参考にしたリンク集を並べておきます。
Mining Bitcoin with pencil and paper: 0.67 hashes per day
手計算マイニングの始祖
sha256のシミュレーションが見れるサイト
ビットコインの技術的な仕組みはすべてココで解説されているのではないか?と思わせる素晴らしいサイト
↓LNでのチップはこちら(1satoshiに感謝⚡)
moyashamo@getalby.com
おすすめ関連記事📚
関連記事やおすすめ記事一覧です。よろしければこれらの記事も読んでみてください。
また、Read BTCの有料プラン、無料プランの説明は次の記事にまとめております。
すべての記事一覧は次の記事にまとめています。



























