🐣

ブロックチェーン開発メモ ~Ethereum2.0 ネットワーク同期編~

2023/11/22に公開

やりたいこと

Ethereum + Solidityでスマートコントラクトを実装したい。
前回: ブロックチェーン開発メモ ~Ethereum2.0 環境構築編~

ネットワーク同期するには

Ethereum2.0では実行クライアントとコンセンサスクライアントの両方を実行する必要がある。(2023/11時点)

詳しくはノードとクライアント仮想通貨のPoSとは?仕組みからPoWとの違いやデメリットについて解説を熟読。

大切なところを引用すると以下。

実行クライアントは(EL クライアントや実行エンジンとも呼ばれ、過去の名称は Eth1 クライアント)、ネットワークでブロードキャストされた新たなトランザクションを受け取り、EVM(イーサリアム仮想マシン)でトランザクションを実行し、すべての現在のイーサリアムデータの最新の状態とデータベースを保持する。

コンセンサスクライアントは(ビーコンノードや CL クライアントとも呼ばれる、旧称は ETh2 クライアント)、プルーフ・オブ・ステークのコンセンサスアルゴリズムを実行し、実行クライアントからの検証されたデータに基づき、ネットワークの合意を形成する。

コンセンサスクライアントの起動

Ethereumに対応したビーコンノードとバリデータクライアントを構成するLoadstarを実行する。
https://lodestar.chainsafe.io/

JWTシークレットを生成する

実行クライアントとコンセンサスクライアント間の安全な接続を確立するために、JWTシークレットを生成する。

openssl rand -hex 32 | tr -d "\n" > "jwtsecret"

コマンドの注意点

  • --max-old-space-size: Node.jsはデフォルトのヒープメモリ容量が1400MBなので、2048MB以上を指定する
    • 今回は8192MBを指定する
  • --network: 接続するネットワーク名を指定する。今回はテストネットの holeskyを指定
  • --dataDir: 同期するブロックチェーン関連データの保存先を指定する
  • --jwtSecret: 生成したJWTシークレットのパスを指定する
  • --checkpointSyncUrl: 信頼できるプロバイダーからビーコンノードを同期する

全部書くとこんな感じ。

$ node --max-old-space-size=8192 \
  ./packages/cli/bin/lodestar.js beacon \
  --network holesky \
  --dataDir <データを保存するディレクトリのパス> \
  --jwtSecret <JWTシークレットのパス> \
  --checkpointSyncUrl https://beaconstate-holesky.chainsafe.io

コマンドの実行結果

こんな感じになればOK。
最後辺りに[eth1] error: Eth1Provider faced error state=OFFLINEと出力されるが、これは実行クライアントを起動していないから出るエラーなので今は問題ない。

XXX-XX XX:XX:XX.XXX[]                 info: Lodestar network=holesky, version=v1.12.0/stable/7000473, commit=<省略>
XXX-XX XX:XX:XX.XXX[]                 info: Connected to LevelDB database path=/home/vagrant/Desktop/projects/eth_holesky_net/chain-db
XXX-XX XX:XX:XX.XXX[]                 info: Initializing beacon from a valid db state slot=390048, epoch=12189, stateRoot=<省略>, isWithinWeakSubjectivityPeriod=true
XXX-XX XX:XX:XX.XXX[network]          info: running libp2p instance in worker thread
XXX-XX XX:XX:XX.XXX[network]          info: libp2p worker started peer=<省略>
XXX-XX XX:XX:XX.XXX[network]          info: PeerId <省略>, Multiaddrs /ip4/0.0.0.0/tcp/9000
XXX-XX XX:XX:XX.XXX[rest]             info: Started REST API server address=http://127.0.0.1:9596
XXX-XX XX:XX:XX.XXX[]                 warn: Low peer count peers=0
XXX-XX XX:XX:XX.XXX[]                 info: Searching peers - peers: 0 - slot: 395656 - head: 390048 0xd742…392a - exec-block: syncing(365116 0x4b00…) - finalized: 0x1c7a…a8eb:12187
XXX-XX XX:XX:XX.XXX[network]          info: discv5 worker started peerId=<省略>, initialENR=enr:-<省略>, bindAddr4=/ip4/0.0.0.0/udp/9000
XXX-XX XX:XX:XX.XXX[eth1]            error: Eth1Provider faced error state=OFFLINE, lastErrorAt=9:02:11 - Request to http://localhost:8551 failed, reason: connect ECONNREFUSED 127.0.0.1:8551
~~~
XXX-XX XX:XX:XX.XXX[]                 info: Syncing - ? left - 0.00 slots/s - slot: 395677 - head: 390048 0xd742…392a - exec-block: syncing(365116 0x4b00…) - finalized: 0x1c7a…a8eb:12187 - peers: 33
XXX-XX XX:XX:XX.XXX[]                 info: Syncing - ? left - 0.00 slots/s - slot: 395678 - head: 390048 0xd742…392a - exec-block: syncing(365116 0x4b00…) - finalized: 0x1c7a…a8eb:12187 - peers: 33
XXX-XX XX:XX:XX.XXX[]                 info: Syncing - ? left - 0.00 slots/s - slot: 395679 - head: 390048 0xd742…392a - exec-block: syncing(365116 0x4b00…) - finalized: 0x1c7a…a8eb:12187 - peers: 35
XXX-XX XX:XX:XX.XXX[]                 info: Syncing - ? left - 0.00 slots/s - slot: 395680 - head: 390048 0xd742…392a - exec-block: syncing(365116 0x4b00…) - finalized: 0x1c7a…a8eb:12187 - peers: 35

実行クライアントの起動

クライアントにも数種類あるが、今回はネット情報の多さや、書籍等でも使われがちな go-ethereumを実行する。
https://geth.ethereum.org/

2窓で起動する

コンセンサスクライアント(以降Loadstar)と実行クライアントは、同時に起動していないといけないので、既にLoadstarを起動しているコンソールとは別に、新しいコンソールウインドウを開く。

コマンドの注意点

  • --holesky: holeskyテストネットを使用する
  • --syncmode: 同期モードを選択する
    • 今回は snap(デフォルト)を指定
    • 詳しくは公式の Sync modes を参照
  • --cache: 内部キャッシュに割り当てるメモリを指定
    • 今回は2048MBを指定
  • --authrpc.addr: Loadstarとやりとりするためのアドレスを指定
    • 同じマシン内で起動するのでlocalhostを指定
  • --authrpc.port: Loadstarとやりとりするためのポートを指定
    • デフォルトである8551を指定
  • --authrpc.vhosts: 仮想ホストからの受信リクエストを受け入れる
    • 同じマシン内で起動するのでlocalhostを指定
  • --authrpc.jwtsecret: LoadstarとやりとりするためのJWTシークレットのパスを指定
  • --datadir: 同期するブロックチェーン関連データの保存先を指定する
  • --rpc.enabledeprecatedpersonal: v.1.11.0で廃止された personal名前空間を使用するため指定
    • これあると開発に便利(なはず)

全部書くとこんな感じ。

$ geth --holesky \
  --syncmode snap \
  --cache=2048 \
  --authrpc.addr localhost \
  --authrpc.port 8551 \
  --authrpc.vhosts localhost \
  --authrpc.jwtsecret <JWTシークレットのパス> \
  --datadir <データを保存するディレクトリのパス> \
  --rpc.enabledeprecatedpersonal

コマンドの実行結果

ログ早すぎてコピペ間に合わなかった、、
特にエラーが出なければ問題無し。

Loadstar側のログ

実行クライアントを起動したことで、以下のログが出るようになった。

XXX-XX XX:XX:XX.XXX[execution]        info: Execution client became online oldState=OFFLINE, newState=ONLINE
XXX-XX XX:XX:XX.XXX[execution]        info: Execution client is synced oldState=ONLINE, newState=SYNCED
XXX-XX XX:XX:XX.XXX[]                 info: Syncing - ? left - 0.00 slots/s - slot: 395809 - head: 390048 0xd742…392a - exec-block: valid(365116 0x4b00…) - finalized: 0x1c7a…a8eb:12187 - peers: 49
XXX-XX XX:XX:XX.XXX[]                 info: Syncing - 5.5 hours left - 0.286 slots/s - slot: 395810 - head: 390111 0xed40…935b - exec-block: valid(365177 0x7378…) - finalized: 0xd742…392a:12189 - peers: 49
XXX-XX XX:XX:XX.XXX[]                 info: Syncing - 2.4 hours left - 0.655 slots/s - slot: 395811 - head: 390143 0x58b6…e1a2 - exec-block: valid(365205 0x9679…) - finalized: 0x952b…4fbd:12190 - peers: 53
XXX-XX XX:XX:XX.XXX[]                 info: Syncing - 1.5 hours left - 1.07 slots/s - slot: 395812 - head: 390175 0x672b…4288 - exec-block: valid(365236 0x9082…) - finalized: 0x0031…ff5f:12191 - peers: 53
XXX-XX XX:XX:XX.XXX[]                 info: Syncing - 1 hours left - 1.51 slots/s - slot: 395813 - head: 390207 0xa4b7…9681 - exec-block: valid(365265 0x3cb9…) - finalized: 0xeac9…915a:12192 - peers: 53

実行クライアントにアクセスする

実行クライアント(以降Geth)を起動したので、諸々の作業をするためにGethのコンソールにアクセスする。

実は全部で3窓使う

LoadstarとGethを起動しているかつ、その上別コンソールから起動中のGethにアクセスするので、さらにもう一つコンソールウインドウを開く。

コマンドの注意点

  • 実行クライアントを起動すると--datadirで指定したパスにgeth.ipcが出力されるので、それをattachコマンドで指定する

コマンドは以下

$ geth attach <datadirパス>/geth.ipc

コマンドの実行結果

以下のような出力があればOK。

WARN [11-22|20:30:57.442] Enabling deprecated personal namespace 

Welcome to the Geth JavaScript console!

instance: Geth/v1.13.5-stable-916d6a44/linux-amd64/go1.21.4
at block: 366650 (Wed Nov 22 2023 06:31:12 GMT+0900 (JST))
 datadir: <--datadirのパス>
 modules: admin:1.0 debug:1.0 engine:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

To exit, press ctrl-d or type exit
> 

適当にGethコマンドを打ってみる

アカウント作成済み&テストネットでのEthereum取得済み
⇒ この辺のやり方はまたまとめる(かも)

> eth.accounts
["0x0000000000000000000000000000000000000000", "0x1111111111111111111111111111111111111111"]
> eth.getBalance(eth.accounts[0])
1899579999962762897
> personal.unlockAccount(eth.accounts[0],"パスワード")
true

以上

Discussion