2017年10月15日日曜日

[Bitcoin]マイニングはじめました

Bitcoinと言えばやっぱりマイニングですよね。
成功するかどうかは別としてプログラムをかける方なら、特別なハードウェアは不要で誰でもマイニングをすること自体はできます。

nonceを変えながら条件を満たすブロックを作ればいいのです。
これだけ聞くと自分でそれほど長くないプログラムを書いてそれを実行すると私は運がいいので当たるだろうとおもってしまいます。
実際にはオートレースの三連単(336通り)もなかなか当たらないのですが、桁が途方もなく大きいとなんだか自分だけは引き当てられる気がしてくるので不思議です。

Bitcoin coreインストールしておく必要があります。
他にはPython 2系を使います。

理論的なところは他の記事に譲ることとしまして、私の理解を開陳いたします。
Bitcoinを技術的に理解する

regtestで検証してみます。
regtestとはなんだろうというのは以下の記事をご参照ください。

Bitcoinを使ったアプリケーションのテスト環境

regtest環境

私のコンピュータはMacなのですが、bitcoin.confを書き換えます。
オプションの意味は bitcoind --help でご確認ください。

# /Users/${USER}/Library/Application Support/Bitcoin/bitcoin.conf
Bitcoin coreを開始します。 /Users/${USER}/Library/Application Support/Bitcoin/regtest
ウォレットとブロックチェーンなどのデータはここに保存されます。
これをノード1と呼ぶことにします。

ビットコインアドレスもあります。
本番やtestnetだと自動的に他のノードとつなぎますがregtestではつながりません。
今回はマイニングを試したいのでgetblocktemplateコマンドが通らないといけません。
そのためにはもう1つノードが必要なようです。
とりあえず同じマシンでもう1つノードを動かしてみます。
場所はどこでもいいとおもうのですが以下はmacOS High Sierraの場合の例です。
ノード2のウォレットとブロックチェーンなどのデータは指定したディレクトリに保存されます。
bitcoin-cliの実行結果はノード1での話になるようです。 getblocktemplateの結果が変わりました。
ブロックを1個作ってみます。
blocksが1になっています。 ブロックの中身をみてみます。
トランザクションの内容をみてみます。
"value": 50.00000000をmjZ48ydjRa7nhp1zpwjbbudS8dVPbP8qAsが使えるようになっています。
mjZ48ydjRa7nhp1zpwjbbudS8dVPbP8qAsは一体だれだ???
ノード1 ノード2 どちらにもありませんがこのあとすぐにノード1 ⇒ ノード2への送金(トランザクション)をやってみて、送金はできるのでlocking scriptをノード1の秘密鍵で解錠できるのでしょう。

まだ残高は0です。
ブロックが100個作られると使えるようになるそうです。
そこで100個ブロックを作ってみます。
ノード1は最初のコインベーストランザクションが残高になっています。
ノード2の残高は0のままです。
ノード2のほうもbitcoin-cliでなにかオプションかなにか渡せばいけるのかもしれませんがよくわからなかったのでcurlで実行しています。
ノード1のビットコインアドレスからノード2のビットコインアドレスに10.0あげてみます。 以下Rawtransactions群のコマンドを使っていますが、sendtoaddress使うと簡単に送金トランザクションを発行してくれます。 コマンドの一覧はbitcoin-cli helpで確認できます。 ここではRawtransactions群のコマンドを使ってみます。 Outputにはノード1のビットコインアドレスへのおつりを返します。 Outputの合計が50.0にならない分の差額はマイナーへの手数料です。 それではトランザクションを作ってみます。 ↑ vinのscriptSigのところは空なのでまだ署名はされていません。
前のトランザクションのアウトプットに署名をすることで自分が使えることを示すって寸法です。

署名してみます。
↑正しそうです。

まだ減ってはいません。
送ってみます。
ノード1は残高が減りました。
ノード2を確認してみます。
confirmation=0で確認してみると、残高が増えています。
を実行するとさきほどのトランザクションが1個含まれています。
このトランザクションを含むブロックをマイニングしてみます。
前置きが長くなりました……
トランザクションはなくてもマイニングはできるのでここまでの手順は不要といえば不要なのですがそこはまあまあ、Bitcoinの授受をやってみました。
実際本番のBitcoinでもブロック高20,000台のブロックはコインベーストランザクションしか入っていないブロックばかりです。

いよいよ本題です。


コマンドだけではできないのでプログラムが必要です。
自分でも作ってみたのですが、エンディアンがどうのこうのでけっこう苦労します。
ブロックを作ってsubmitblockしてエラーが返ってきて、そのキーワードをググると下記に行き当たりました。
bip-0022.mediawiki
一応regtestでは受け入れてもらえるものはRubyで作れはしましたが……
自分で書いたのは150行くらいで難しいところはbitcoin-ruby様です。




今回はntgbtminer様を使います。 Python 2系で書かれた430行くらいのプログラムです。 nightminer から ntgbtminer に鞍替え 〜 簡単なpythonプログラムを使ってbitcoinの採掘を試してみる、その5 をたいへん参考にさせていただきました。
ありがとうございます。
↓この記事を書いたときに使ったソースのコミットIDです。
先頭の方の以下のように書き換えてノード2がマイニングすることにしてみます。
最後のほうを書き換えます。
第1引数はgenesisブロックの"The Times 03/Jan/2009 Chancellor on brink of second bailout for bank"みたいなメッセージのことです。
第2引数は今回はノード2のビットコインアドレスを指定します。

マイニングを無限に続けるので、今回はブロックを1個みつけたらbreakするようにしました。
マイニング難易度は低いのですぐに掘り当てます。
bitcoin-cli getblockchaininfoを実行するとblocksが1個増えていることを確認できます。


=> コインベーストランザクションとさきほど送信したトランザクションが含まれていることが確認できます。


まだノード2の残高には含まれていません。

100ブロックconfirmationされると増えるはずです。
ノード2の残高を確認してみます。
10(ノード1からもらった) + 0.00001(手数料) + 50(報酬)になっています!

最後にntgbtminer様で作ったブロックの先頭のトランザクション(コインベーストランザクション)を見てみます。
vin[coinbase]のところを確認します。
先頭の0x01は、次に続く1byteがブロックの高さを表すことになっています。
次の0x66は10進数で102で確かにブロックの高さが合っています。
746f726966756b75206b61696f75はたとえばirbで実行すると、さきほど指定した文字列になっています。
本番のbitcoinでは2017/10/15現在のブロック高が43万くらいなので先頭は03でブロック高は3byte続いています。
10分に1回くらいで新しいブロックが作られるのでそのペースで行くと、300年後までは03(ブロック高3byte)なのだそうです。

ntgbtminerはブロックを探す処理自体は本番でも動きます。
動かす際には一番最後の行を自分のビットコインアドレスにするのを忘れないようにしてください。
デフォルトは作者のビットコインアドレスが指定されているようです。

もし仮にブロックを見つけたときに送信したブロックが本番で受け入れてもらえるのかどうかはわからないです。
regtest環境でOKだったんで大丈夫だとはおもいます。
天文学的に低い確率なのでブロックを探し当てることは難しいのでしょうけど、私は宝くじは積極的に買いに行くタイプなので動かすだけ動かしています。
追加のライブラリは不要ですし、処理を見る限り問題ないとおもうのですが、使う際は自己責任でお願いします。






0 件のコメント:

コメントを投稿