ビットコインとか忘年会
こちらのイベントで「フルノード職人の朝は早い」というタイトルでフルノードの建て方をLTしました。
この記事ではEVM系のチェーンであるEthereum(メインネット)およびArbitrum、Optimism、Binance Smart Chain、Avalancheと、LTでは触れられなかったPolygonのフルノードの建て方を紹介します。
マシン構成
クラウド課金地獄
クラウドを使ってもいいのですが、普通にこれらすべてのチェーンを動かそうとするとメモリが最低でも64GB、SSDが15TBとか必要になりますので、月額何千ドルもかかってしまいます。
実際、DigitalOceanという格安VPSで作っていたのですが、月1,200ドル(当時のレートで約20万円)を請求されて泣きそうになりました。
そこで僕は自宅にワークステーション(という名の自作PC)を作り、自宅サーバとして運用しています。
ちなみにOSはUbuntu 22.04 LTSです。
マシン構成
CPUは8コア以上、メモリ64GB以上、SSDが15TB以上あれば十分かと思います。
僕の場合には以下のような構成で組みました。
種類 | モデル | 参考価格 |
---|---|---|
マザーボード | ASRock B550M Phantom Gaming 4 | 11,680円 |
CPU | AMD Ryzen 9 3950X 16コア | 廃盤(現世代では7950X=80,000円相当) |
メモリ | A-DATA 32GB DDR4 3,200MT/s x 4 = 128GB | 1枚15,000円 x 4 = 60,000円 |
SSD (OS) | NVMe 2TB x 2 (RAID 1) | 1枚10,000円 x 2 = 20,000円 |
SSD (データ) | SATA 8TB x 4 (RAID 5 + LVM) | 1枚56,800円 x 4 = 227,200円 |
その他 | 電源、ケース、GPUなど | 40,000円くらい |
合計 | 438,880円 |
初期投資としてはかなり高額かと思います。
特にSSD代で半分以上を占めており、ストレージに一番お金がかかっています。
ちなみに安いHDDで組むと、IOが足らずに同期が終わらなくなりますのでSSDへの課金は必須です。
CPUについては16コアのものを使いましたが、8コアぐらいでも大丈夫かと思います(試していないので分かりませんが)。
メモリについては最低でも64GBくらいないとgethがキャッシュとしてメモリを大量に食いますのでスワップしまくって大変になります。
メモリは正直載せれば載せるほどディスクキャッシュに回りますので、多ければ多いほどよいです。
ただ、コンシュマー向けのCPUだとAMDのThredripperを除いて128GBまでしか載りませんので、上限を載せています。
まぁメモリはそんな高くないですしね。
なおブロックチェーンは永遠に成長してどんどんディスクを食っていきますので、必ずいずれ足りなくなります。
将来的に拡張できるようにSATAポートが多いマザボを買うか、最初から多めに積んでおくことをおすすめします。
今回のケースでは8TBが4台のRAID5構成なので、8TB×3台=24TBの容量が使えます。
SSDの設定
まずはSSDを使えるように設定していきます。
フォーマット
GPTパーティションをgdisk
を使って作っていきます。
$ sudo gdisk /dev/sd[a-d]
RAID構築
$ sudo mdadm --create --raid-devices=4 --level=raid5 /dev/md1 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
これで/dev/md1に三台分の容量のブロックデバイスが出来上がります。
状態確認は
$ cat /proc/mdstat
でできます。
RAIDの構築におおむね半日〜一日程度くらいかかります。
RAIDの構築中にこれ以降の作業をしてもいいのですが、IOが発生しているとRAIDの同期がどんどん遅くなっていってしまいますので、素直に待ったほうがいいと思います。
LVM構築
先程作ったRAIDデバイスをそのままフォーマットして使ってもいいのですが、今後の拡張性のためにLVMを利用しました。
$ sudo pvcreate /dev/md1
$ sudo vgcreate ssd01 /dev/md1
$ sudo lvcreate --name dat01 --size 15T ssd01
ボリュームグループ名はssd01
、論理ボリューム名はssd01
としています。
FS作成
最後にファイルシステムを作っていきマウントします。
$ sudo mkfs -t ext4 /dev/mapper/ssd01-dat01
$ sudo mkdir /mnt/dat01
$ sudo mount /dev/mapper/ssd01-dat01 /mnt/dat01
$ sudo vi /etc/fstab
/dev/mapper/ssd01-dat01 /mnt/dat01 ext4 defaults,nofail 0 0
これでブロックチェーンデータ用の大容量SSDの作成は終わりです。
容量が足りなくなったらlvextend
で拡張しましょう。
Ethereum (geth)
インストール
公式のPPAリポジトリがありますのでこちらからインストールします。
$ sudo add-apt-repository -y ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install ethereum
起動
gethはデフォルトで$HOME/.ethereum
を使いますので、大容量SSDへのシンボリックリンクを張ります。
$ ln -s /mnt/dat01/ethereum $HOME/.ethereum
あとは普通に起動します。
$ geth
デフォルトでスナップショット同期が行われますが、同期が完全に終わるまでだいたい2〜3日くらい(もちろんCPUはネットワーク帯域にも依存しますが)かかります。
状態確認は
$ geth attach
> eth.syncing
> eth.blockNumber
でできます。
自動起動
さて、マシンを再起動するたびに手動で起動するのは非常に面倒です。
そこでsystemdデーモン化しましょう。
$ sudo vi /etc/systemd/system/geth.service
[Unit]
Description=Go Ethereum
After=syslog.target network.target
[Service]
User=visvirial
Group=visvirial
Type=simple
ExecStart=/usr/bin/geth --http --http.api debug,eth,net,rpc,txpool,web3 --http.addr 0.0.0.0 --http.vhosts '*' --http.corsdomain '*'
KillMode=process
KillSignal=SIGINT
TimeoutStopSec=600 // ⇦ 止めるときに10分くらいまで待たないとDBがぶっ壊れるので注意!
estart=on-failure
RestartSec=10s
[Install]
WantedBy=multi-user.target
一つ注意なのがTimeoutStopSec
に十分大きな値(10分とか)を指定することです。
デフォルトでは90秒だったと思いますが、この時間ではgethがオンメモリキャッシュをディスクにフラッシュするのが終わらず、強制終了になってしまい、最悪データベースが壊れて同期を一からやり直しになります。
実際、僕もこれもDBをぶっ壊して泣きながら同期し直しましたので気をつけてください。
Arbitrum
スナップショット
チェーンのジェネシスブロック(?)的なデータが必要なのでこれをダウンロードします。
執筆時点で350GiBくらいありました。
非常に巨大なので計画的にダウンロードしましょう。
ちなみにwgetやcurlなどを使うと、途中でネットワークが不安定になった場合にダウンロードがエラーとなってやり直しになってしまい非常に辛いです。
ですのでaria2cなどのダウンロードツールを使うことを強く推奨します。
Docker
公式でDockerイメージを配布しており、こちらを使うのが最も簡単です。
$ docker run --name arbitrum -itd --restart unless-stopped -v /mnt/dat01/arbitrum:/home/user/.arbitrum -p 0.0.0.0:8547:8547 -p 0.0.0.0:8548:8548 offchainlabs/nitro-node:v2.1.3-e815395 --parent-chain.connection.url http://172.17.0.1:8545 --chain.id=42161 --http.api=net,web3,eth,debug --http.corsdomain=* --http.addr=0.0.0.0 --http.vhosts=*
--restart unless-stopped
を指定するとマシンを再起動しても自動的に起動してくれますので便利です。
Optimism
インストール
op-geth
とop-node
の二つのプロセスが必要です。
ビルドの仕方は以下のサイトに詳しく載っていますので、こちらに従ってビルドしてください。
スナップショット
Arbitrumと同様、ジェネシスブロックのデータ的なもの (Bedrock) がありますので、こちらをダウンロードします。
300GBくらいありますので計画的にダウンロードしましょう。
共通鍵作成
op-geth
とop-node
をつなげるのにJWTファイルを作る必要があります。
$ cd op-geth
$ openssl rand -hex 32 > jwt.txt
$ cp jwt.txt ../optimism
起動
op-geth
#!/bin/bash
SEQUENCER_URL=https://mainnet-sequencer.optimism.io/
./build/bin/geth \
--datadir=./datadir \
--http \
--http.port=8549 \
--http.addr=0.0.0.0 \
--http.corsdomain '*' \
--authrpc.addr=localhost \
--authrpc.port=8552 \
--authrpc.jwtsecret=./jwt.txt \
--verbosity=3 \
--rollup.sequencerhttp=$SEQUENCER_URL \
--nodiscover \
--syncmode=full \
--maxpeers=0 \
--port=30304
こんな感じのスクリプトファイルを作って起動しましょう。
op-node
#!/bin/bash
L1URL=http://localhost:8545
L1KIND=debug_geth
NET=mainnet
./op-node/bin/op-node \
--l1=$L1URL \
--l1.rpckind=$L1KIND \
--l2=ws://localhost:8552 \
--l2.jwt-secret=./jwt.txt \
--network=$NET \
--rpc.addr=0.0.0.0 \
--rpc.port=8550
こちらも同様でこんな感じのスクリプトを作ります。
公式との違いは、L1KIND
にdebug_geth
を指定することです。
デフォルトのbasic
だと非常に遅く、同期が何週間もかかります。
debug_geth
を指定すれば一週間くらいで同期できます。
Binance Smart Chain
インストール
$ wget $(curl -s https://api.github.com/repos/bnb-chain/bsc/releases/latest |grep browser_ |grep geth_linux |cut -d\" -f4)
$ mv geth_linux geth
$ chmod -v u+x geth
genesis.json/config.tomlのダウンロード
$ wget $(curl -s https://api.github.com/repos/bnb-chain/bsc/releases/latest |grep browser_ |grep mainnet |cut -d\" -f4)
$ unzip mainnet.zip
スナップショットのダウンロード
公式のスナップショットもあるのですが、BNB48Clubという人たちが提供してくれているもののほうがpruningされているため、データ量が少ないです。
約400GBあります。
起動
$ ./geth --config ./config.toml --datadir ./node --cache 8000 --rpc.allow-unprotected-txs --txlookuplimit 0 --tries-verify-mode none --snapshot=false --syncmode full --http.port 8546
Avalanche
インストール
$ wget -nd -m https://raw.githubusercontent.com/ava-labs/avalanche-docs/master/scripts/avalanchego-installer.sh
$ chmod 755 avalanchego-installer.sh
$ ./avalanchego-installer.sh
これを実行すると$HOME/avalanche-node/avalanchego
という実行ファイルがダウンロードされます。
起動
$ $HOME/avalanche-node/avalanchego --config-file=/home/visvirial/.avalanchego/configs/node.json
Polygon
インストール
Heimdall
とbor
の二つが必要です。
Heimdall
$ curl -L https://raw.githubusercontent.com/maticnetwork/install/main/heimdall.sh | bash -s -- v1.0.3 mainnet heimdall
$ sed -i 's|^seeds =.*|seeds = "seed_details"|g' /var/lib/heimdall/config/config.toml
Bor
$ curl -L https://raw.githubusercontent.com/maticnetwork/install/main/heimdall.sh | bash -s -- v1.0.3 mainnet bor
sed -i 's|.*bootnodes =.*|bootnodes = "mainnet_bootnodes"|g' /var/lib/bor/config.toml
スナップショット
Heimdall
curl -L https://snapshot-download.polygon.technology/snapdown.sh | bash -s -- --network mainnet --client heimdall --validate-checksum true
だいたい400GBくらいあります。
aria2cを使って分割されたファイルをダウンロードしたあとに合体し、チェックサムの検証とアーカイブの展開までやってくれます。
Bor
curl -L https://snapshot-download.polygon.technology/snapdown.sh | bash -s -- --network mainnet --client bor --validate-checksum true
だいたい3TBくらい(!)あるので計画的にダウンロードしましょう。
100Mbpsの回線だと3日かかりますので、大変です。
起動
インストールスクリプトが/lib/systemd/system/(heimdalld|bor).service
を作ってくれますので、普通にsystemctl
コマンドで起動できます。
まずはHeimdallを起動して同期を完了させましょう。
Heimdallが同期できるまでBorの同期は開始できないようなので注意してください。
$ sudo systemctl start heimdalld
状態は
curl localhost:26657/status
で確認できます。
.result.sync_info.catching_up
がfalse
になれば同期完了です。
同期できたらBorを起動しましょう。
$ sudo systemctl start bor
同期に二週間くらいかかります。
まとめ
フルノードはTB級のデータを高速に捌かないといけないため、非常に運用が大変です。
スナップショットのダウンロードに時間がかかりますし、スナップショット時点から最新のブロックまで同期するまでも大量のIOが発生するため、SSDでも非常に時間がかかります。
さらっとやり方を書きましたが、全部やり終えるまで二ヶ月くらいかかりました。
それでもなんでフルノードを自前でも使って?
Don't trust, verify.
ですよ!!!
まぁ実務的にはRPCのホスティングサービスがどれも不安定で(ちゃんと課金しているにもかかわらず)よく通信に失敗するので、自前のサーバにつないでよしなにやるために必要で仕方なく運用しているというのが実情です。
おまけ
同期ダッシュボード
サーバにいちいちログインして一つ一つ同期状態を確認するのはなかなか大変です。
そのため同期状態が一発で分かるダッシュボードを作りました。
オープンソースなので、よろしければ改造して使ってください。
(※RPCは全世界に公開していますが、基本的に自分用なので勝手に繋がないでください)
NATを越えろ!
自宅サーバで運用しているため、外部からアクセスできるようにするためにはNAT超えをする必要があります。
僕の場合にはWireGuardでVPNとしてつないで、nginxでリバースプロキシしています。
ローカルでしか使わないのであれば必要ないと思います。
最後に
フルノード建てるの楽しいよ!みんなもやってみてね!!!