一つ前の記事でも少し触れましたが、ビットコインのフルノードをシングルボードコンピュータで構築してみたので、その手順を書きたいと思います。シングルボードコンピュータとはRaspberry Piに代表される超小型コンピュータのことです。
なお、今回のノード構築には今までにいただいた寄付を利用させていただきました。いつもありがとうございます。
0.機種選び
最低2,3年程度の常時安定稼働を目指しノードを構築することにしました。
本体
まずは本体のコンピュータ選びから。Raspberry Piが超有名ですが、メモリ1GBというのが不安でした。bitcoin.orgにもフルノードの最低動作環境は2GBとありますし、その他いろいろ調べてみると、ノード接続数を絞ったりして工夫すれば動くことは動くらしいのですが、長期安定稼働という点やネットワークへの貢献を考えれば貧弱スペックで無理やり動かすのはためらわれたので別の選択肢を探しました。
結果見つけたのが韓国のHardkernelという企業が作っているOdroid XU-4というコンピュータ。詳細スペックはリンク先を参照してもらえればいいと思いますが、最新機種のRaspberry Piと比較すると、CPUは8コア2GHz、メモリ2GB、eMMC対応、USB3.0対応、1Gbpsとかなり高性能です。ちなみにRaspberry Pi 3は4コア1.2GHz、メモリ1GB、USB2.0、100Mbpsという内容。
肝心の価格はOdroid XU-4が74ドル+22ドル(配送料+Paypal為替手数料)、Raspberry Piは35ドルなので、価格差はあるものの性能を考えれば妥当な感じ。
ちなみにOdroidは公式代理店のリストの中に日本の店が無いようなので、配送料が余分にかかりますが公式から直接買うのが良いようです。
Odroidの日本語記事はほぼ皆無で英語情報に関してもかなり少なかったので、実はRaspberry Piすら触ったことがない身としてはやや不安でしたが、結果からいうとインターネット上に転がっているRasperry Piの情報を頼りにほぼ同様にセットアップできましたし特に大きなトラブルもなかったので良かったです。
ただ、やはり情報も使用ユーザーも少ないですし、トラブルがあったときは英語で問い合わせなければならず公式サポートの評判も怪しいので、慣れていない人にはあまりお薦めできません。
ストレージ
普通はマイクロSDカードを使用しますが、フルノードは容量も要求されますし、かなり頻繁にディスク書き込みがあることを考慮して、HDDを利用することにしました。今後ブロックサイズが上がることも考慮して1TBのものを購入。剪定モード(Pruning mode)で運用する人は容量的にはほとんど必要ありませんが、SDカードだとやはり寿命が心配な気がします。
ディスプレイ
ただビットコインノードを運用するだけでもいいのですが、正直それだけだと面白くないのでコンピュータの情報を表示するLCDディスプレイを取り付けることにしました。OdroidにはCloudshellという、2.5インチHDDの取り付けが可能なNAS用のちょうどいいディスプレイ付きケースが販売されているので購入。Odroidを選んだのも実はこのCloudshellに惹かれてと言うのが大きいです。
まとめ
思ったより高くついてしまいました。合計約24,000円です。一部ビットコインデビットカード(プリペイドカード)を使用したので、手数料等で実質にかかったコストは計25,000円程度。
本体部分
- Odroid XU-4:96ドル(本体+配送料等)
- 2.5インチHDD 1TB:5570円
- マイクロSDカード 8GB:518円
- LANケーブル(CAT6):326円
- 計:約17200円
基本HDDを使用しますが、ブートローダー(起動用プログラム)にはSDカードを使用しなければいけないようのでマイクロSDも購入。容量は必要ないものの、最低クラスでも値段はほとんど変わらないので8GBのものにしました。いらないSDカードが家に転がっている人はそれでもいいと思います。
ちなみに今回は使用しませんでしたが、CPU8コアをフル運用するとかなりCPU温度が熱くなるので、特に夏場は使用コア数を制限するか追加でファンを取り付けることが必要になるかもしれません。CloudShellにはサイドに40mmのファンを取り付けられるようになっています。
ディスプレイ部分
- CloudShell for XU4:39ドル
- 電源アダプタ(5V/6A):2230円
- 計:約6600円
Odroid-XU4にも標準で5V/4AのACアダプタがついてきますが、CloudShellを使用する場合、それだと足りないらしいので、いろいろと探してAmazonで5V/6Aのものを購入。Odroid公式でも売っていますが、PSEマークがついてないらしいので、値段はあまり変わりませんし日本で購入したほうがいいかもしれません。
1.OSイメージをダウンロード
適当なPCからOSイメージをダウンロード。Odroidの公式wikiにXU4用のUbuntuが置いてあるので、最新のUbuntu16.04をダウンロードしました。
2.OSイメージをSDカードに書き込み
ダウンロードしたOSをSDカードに書き込み。方法は検索すればいくらでもでてくるので省略。
3.CloudShell(ケース)の組み立て、起動
公式ページを参考にケースを組み立てます。組み立てが終わったら、SDカードやLANケーブルを接続して起動します。今回は使用しませんでしたが、HDMI端子もついているので必要な人はディスプレイにつないでも良いです。
4.SSH接続
ディスプレイ無しでセットアップしたので、ローカルIPを適当に探して他のPCからSSHで接続。同じく方法は省略。
5.HDDで起動するように設定
セキュリティ設定する前にHDDのみを使用するように設定。方法は省略。
6.セキュリティ設定
24時間自宅サーバーを公開するのはいろいろと危険なので、セキュリティ設定にも気を遣う必要があります。SSHのポート変更、rootログイン禁止、パスワードでのログイン禁止、公開鍵認証の設定などが最低限。その他必要に応じて設定してください。方法は省略。
7.LCDディスプレイの設定・表示
公式wikiに設定方法が書いてあります。CPU使用率やメモリ使用率を表示できるサンプルスクリプトも用意されているので、フルノードの起動前に設定・表示しておくと便利かも。
ちなみに初期状態だとスクリーンセーバーのような感じで起動後しばらくして画面が真っ黒になるのでさらに設定を変更する必要がありました。ここが一連のセットアップの中で一番悩みましたが、/media/boot/boot.ini内の、setenv bootrootfs "console...と続く行に「consoleblank=0」を追加したら常時ディスプレイが表示状態になりました。
8.Bitcoin Coreのインストール
いよいよBitcoin Coreのインストール。普通にソースコードからビルドする方法と、PPA(非公式レポジトリ)からインストールする方法の2種類があります。PPAはインストールやバージョンアップが非常に簡単というメリットがあります。ただし、デメリットとしてUbuntu以外のOSは使えない、バージョンアップの際に更新が遅くなる可能性がある、その他やや信頼性に欠けるという点もありますが、幸いなことにUbuntuを使用していたのと、Bitcoin CoreのPPAの管理者はBluemattというコア開発者の一人ですしかなり利用者も多く信頼性はまあ十分と考えて、今回はPPAを利用しました。
sudo apt-add-repository ppa:bitcoin/bitcoin sudo apt-get update sudo apt-get install bitcoind
この三行でインストール終了。GUIウォレットの画面を利用したい方は「bitcoind」だけではなく「bitcoin-qt」もインストールしてください。
9.OSやBitcoin Core等のチューニング
フルノードのためのチューニング。まずはメモリのスワップ領域が全く設定されていなかったので、4GBほど設定(たぶんそんなにいらないです)。最初は何もやらずにノードを起動したんですが、起動後メモリ使用量が95%を超えていたために今回は後から設定しました。ちなみに同期中のスワップ領域の使用容量は200MB程度でした。その他にもいろいろあるかもしれませんが、ここらへんは全く詳しくないので何もいじってません。
それからBitcoin Coreの設定ファイル(bitcoin.conf)を設定します。なにも設定しなくても動くので、必要に応じて設定してください。Raspberry Pi等の場合、メモリがかなり厳しくbitcoindが落ちる可能性があるので、いろいろと絞ったほうが良い場合があります。以下のページが参考になります。
Reducing bitcoind memory usage · GitHub
ちなみにOdroid XU-4もCPUがかなりオーバーヒート気味になるので、par=1などで使用コア数を制限したりする必要があるかもしれません。今回は何も設定しませんでしたが、同期中に一回だけbitcoindが落ちました。CPUが原因かメモリ不足が原因かは不明ですが、メモリのスワップ領域を設定後は落ちなかったです。
10.Bitcoin Coreを起動、同期を待つ
bitcoind -daemon
で起動し、同期するのをひたすら待ちます。Odroid XU-4では2017年2月時点(約120GB)で同期完了まで丸8日かかりました。今回はテストの目的がありましたが、現在は最新のPCなどスペックによっては1日もかからず同期が終わるらしいので、別のPCで同期させてからノード本体機に移動させたほうが良いかもしれません。
ちなみに昔はbootstrap.datなどをtorrentなどでダウンロードする方法もありましたが、現在ではダウンロード速度というよりもブロック、トランザクションの検証速度がボトルネックらしいので普通にBitcoin Coreから起動するのが一番いいらしいです。
ビットコインノード用にディスプレイ表示をカスタマイズ
サンプルの表示プログラムもCPU使用率等が表示され便利ですが、やはりビットコイン用にノード接続数とかメモリプール、未確認トランザクションのデータなどを表示したいのでプログラムを改変。プログラムはシェルスクリプトになっています。
以下に置いておきますが、スクリプトとしてコマンドを書いたことはほとんどなかったので微妙なコードになってるかもしれません。必要に応じてコードをいじってパラメータを変更しなければならない場合もあるので、少なくともコードを読める人向けです。
GitHub - bitkatana/cloudshell_lcd_bitcoin: ODROID-XU4 Cloudshell LCD Informations for Bitcoin Node
同期中の表示はこちら。
詳細はGithubのページに書きましたが、ビットコイン関連のデータだけ軽く解説。実はブロックの検証中はbitcoin-cliコマンドにほとんど反応せず数十分かかるとかタイムアウトするとか問題があるので、ブロックチェーンの同期中は停止しておいたほうがいいかもしれません。
ノード接続数
ノード接続数をBitcoin Connectionとして表示しています。「bitcoin-cli getconnectioncount」で普通に取得できます。画面だと61とかなり多めになっていますが、Torで接続するとこんなに行かないと思います(画面はTorのIPになっていますが、同期中は普通に接続していました)。接続数が増えるほど負荷が高くなるので、bitcoindやコンピュータが落ちる場合はmaxconnectionをbitcoin.confで制限するのを推奨。
最新のブロック
「getblockcount」で最新のブロック番号を表示。それから「getblockhash ブロック番号」でブロックのハッシュ値を取得し、さらに「getblock ハッシュ値」でブロックの生成時刻を取得します。現在時刻も取得し、「現在時刻-ブロックの生成時刻」でどれぐらい前のブロックか表示しています。
ちなみにブロックチェーンが同期状態にあるかは、blockchain.info等のブロックエクスプローラー(つまり他のノード)のブロック番号と比較する方法もありますが、Bitcoin Coreでは単純に最後のブロックが90分以内だと同期状態と判断するようにGUIウォレット上では表示しているようです。
メモリプール情報
「getmempoolinfo」でメモリプール(未確認トランザクションの保存領域)に関する情報が取得できます。上の方に表示しているmempool usageが実際のメモリの占有領域、下のほうが未確認トランザクションの数とサイズです。写真上では同期中なので、メモリプールには何にも入っておらずゼロ表示です。
手数料予測
「estimatefee 6」で手数料の予測値を表示しています。estimatefeeの後ろはブロック数を表し、この場合は6ブロック(約1時間)以内に確認されるのに最適な手数料を表示するような設定です。
メモリプールから計算するので同期中では計算ができず-1が返されます。ちなみに、Bitcoin Core 0.14からはデフォルトの値が6になるらしいので、ここでも6にしています。最低値は2で、1にすると計算できないので必ず-1が返されます。
価格情報
取引所のAPIにアクセスして最新価格を取得しています。どこでもいいですが、とりあえずbitflyerとbitfinexのAPIを利用させていただきました。
11.同期完了
ということで同期が完了しました。同期中の写真からちょっとスクリプトをいじって表示を変えました。同期後はメモリプールや手数料予測の情報も表示されます。
単なるフルノードだと面白くないし実用性に困りますが、メモリプールや手数料情報、価格情報も表示するとなかなか使えるのではないでしょうか。
12.(オプション)Torとしてノード運用する
IPを隠したい場合や不足気味なTorノードとして運用したい場合はまずTorをインストールします。Torの公式ページにインストール方法があるのでそちらを参照すると良いでしょう。Option1は最新バージョンが入らないらしいのでOption2でインストールするのがおすすめです。
インストールしたら設定ファイルの/etc/tor/torrcを開き以下の行を追加します。
HiddenServiceDir /var/lib/tor/bitcoin-service/
HiddenServicePort 8333 127.0.0.1:8333
再起動後、
cat /var/lib/tor/bitcoin-service/hostname
でビットコインノード用のIPを確認します。
さらにbitcoin.confに以下の行を追加します。
onlynet=onion onion=127.0.0.1:9050 listen=1 bind=127.0.0.1:8333 externalip=yourip.onion
externalipのところはcat~で確認した自分のIPを入力してください。
ちなみにこの設定だとIPが固定になり、Torネットワーク以外の普通のノードには接続しないようになっています。
動的IPや匿名性ではなくネットワークの貢献のための運用で一般ノードにも接続したい場合は以下のページが参考になります。
bitcoin/tor.md at master · bitcoin/bitcoin · GitHub
Setting up a Tor hidden service - Bitcoin Wiki
13.(オプション)どこからでも自分のフルノードに接続してウォレットを使う
前回の記事で書いた通り、フルノードにはセキュリティ(は現実的にSPVとほとんど変わりませんが)、プライバシーが優れているというメリットがあります。今後SPVウォレットのプライバシーも改善される可能性はありますが、現状だといろいろと問題があるらしいので信用できる自分のフルノード以外と通信しないようにすれば大きなメリットとなるでしょう。
残念ながら現状はAndroid用のBitcoin Walletにしか対応していません。同ウォレットの設定メニューからIPアドレスを設定すれば完了です。
ただし、ビットコインの通信というのは実は全く暗号化されていないので、Torを使わないと通信を傍受されて簡単に内容を読み取られる恐れがありあまり意味がありません。プライバシーが気になる方は通信内容を暗号化できるTorを使いましょう。AndroidにOrbotというTorアプリをインストールすると通信できるようになります。
ただし、TorはTorでいろいろと問題があるらしいですし、第三者のソフトに頼るのはあまり良くないので、SSL通信ぐらい実装してくれと思います。ここらへんはBIP150/BIP151で信頼できるノードの認証方法や暗号化通信が提案されており、前向きに検討されているようなので時期は不明ですが今後の実装に期待というところです。
最後に
ということでビットコインのフルノードを構築してみました。ビットコインのプライバシーというとビットコインアドレスの非匿名性が話題に上がるのが普通ですが、軽量型ウォレットの通信のプライバシーも大きな課題の一つであり、フルノードをたてれば軽量型ウォレットから信頼できる自分のフルノードに接続することでその課題がある程度解消されます。
同期中はかなり負荷が高くなりますが、同期後は安定しており負荷も低いようなので、今後はスペック的にできるかどうかわかりませんがElectrumのサーバーでもたててみようかと思います。
Bitcoreという、ブロックエクスプローラーやCopayで利用できるウォレットAPIが使える(つまりCopayから自分専用のフルノードだけに接続できる)便利なライブラリもあるのですが、やる気がないのかもともとこんなものなのか、いまだに最新のBitcoin Core 0.13系には対応していないようなのでとりあえずは見送ります。Bitcoreに関しては、日本語でもかなり情報が多い印象なので気になる人は検索すると良いでしょう。
どちらにしてもBitcoin Core上でBitcoreとかElectrumサーバーとかCounterpartyとかさらにいろいろとやりたい人は、txindex=1オプション等をbitcoin.confとかに書いてトランザクションにインデックスを付けなければならないので、最初に忘れずに設定ファイルに書いておきましょう(今回忘れたので、再度長い日数をかけてreindexしなければいけなくなりそうです・・・。)。
※BitcoreやCounterpartyはトランザクションだけではなくアドレスなどにもインデックスを付けなければならず、そのために別にBitcoin Coreへパッチをあてる必要があります。