Validium ノードで見るL1とL2の世界
この記事は、以下の Astar zkEVM ドキュメントを元にしています。
「Setup Local Validium Node(ローカル Validium ノード セットアップガイド)」(日本語訳もあります)
ローカルマシン上に Validium ノードの設定をし、実際に手元で稼働させ、この Validium ノードを使いL1とL2の関係性をトークンの転送を実際に行いながら確認します。
Validium ノード
Astar zkEVM は、Polygon CDK と AggLayer を搭載したイーサリアムレイヤー2 に Validium として展開されています。
Validium とは、レイヤー2のスケーリングに関連する概念です。Validium は、 ZK-rollupsのような有効性証明を使用してトランザクションの完全性を強化するスケーリングソリューションですが、トランザクションのデータ(DA = Data Availability = データ可用性)はイーサリアムメインネットに保存されません。これにより、トランザクションデータの完全性を保ちながら、イーサリアムネットワークのスケーラビリティへの課題を解決し、ガス料金を削減する役割を果たします。
オリジナルのドキュメントでは Astar zkEVM のバックエンド処理の主要な以下のコンポーネントが稼働します。この記事もそれにならい1台でこれらすべてが稼働する手順となっています。
zkEVM データベース:データノード、イベント、エクスプローラーL1およびL2、プール、状態、ブリッジサービス
zkEVM ノードコンポーネント:アグリゲーター、アプルーブサービス、シーケンサーとシーケンスセンダー、シンクロナイザー
L1 ネットワーク (mock)
プローバー
エクスプローラー L1, L2
JSON RPC エクスプローラー
L2 ガスプライサー
DAC:データ可用性サービス、DACセットアップ委員会
zkEVMブリッジサービスとUI
前提条件
マシンスペック
Linux ベース OS OS (e.g., Ubuntu Server 22.04 LTS)
少なくとも 16GB RAM と 4 コア CPU
AMD64 アーキテクチャシステム
上記の条件をもとに、今回構築したローカルマシンスペックは以下です。
Ubuntu Server 22.04.3 LTS
Intel Alder Lake - N100 4Core
16GB SODIMM DDR4 3200
M.2 NVMe SSD 500GB
ソフトウェア要件
この手順では、go, docker, docker compose (v2) , makeが必要です。
go はGoogleが開発したプログラミング言語です。これをインストールしておく必要があります。
参考: https://go.dev/doc/install
docker、docker compose はDocker社(かつてのdotCloud)が開発した、コンテナ型の仮想環境を作成、配布、実行するためのプラットフォームです。これをインストールし、エンジンプロセスを稼働させておく必要があります。
参考: https://docs.docker.com/engine/install/ubuntu/
make はソフトウェアのビルドプロセスを自動化するツールです。基本的には以下のエッセンシャルツールキットで一緒にインストールされるのでその方がよいでしょう。
$ sudo apt-get -y install build-essential
Validium ノード構築
実は、準備さえ整っていたら構築自体は一瞬です。クイックスタートできるように必要なコンテナイメージが用意されているからです。
リポジトリのクローン
$ git clone https://github.com/Snapchain/zkValidium-quickstart.git
$ cd zkValidium-quickstart
.env.sample ファイルをコピーします
$ cp .env.example .env
必要な Docker イメージをプルします。
$ sudo docker compose pull
インターネットの回線速度も影響しますが、これには完了まで数分時間かかる場合があります。
ローカルで Validium を起動
ローカルのCDK validiumを起動します。
$ sudo make run
make run-db
make[1]: Entering directory '/home/tk/test_validium/zkValidium-quickstart'
docker compose -f docker-compose.yml up -d zkevm-state-db
[+] Building 0.0s (0/0) docker:default
[+] Running 12/12
✔ Network zkevm Created 0.1s
✔ Volume "zkvalidium-quickstart_zkevm_bridge_db_data" Created 0.0s
✔ Volume "zkvalidium-quickstart_zkevm_mock_l1_geth_data" Created 0.0s
✔ Volume "zkvalidium-quickstart_zkevm_pool_db_data" Created 0.0s
✔ Volume "zkvalidium-quickstart_zkevm_state_db_data" Created 0.0s
✔ Volume "zkvalidium-quickstart_explorer_l1_backend_db_data" Created 0.0s
✔ Volume "zkvalidium-quickstart_explorer_l2_stats_db_data" Created 0.0s
✔ Volume "zkvalidium-quickstart_explorer_l1_stats_db_data" Created 0.0s
✔ Volume "zkvalidium-quickstart_zkevm_dac_node_db_data" Created 0.0s
✔ Volume "zkvalidium-quickstart_explorer_l2_backend_db_data" Created 0.0s
✔ Volume "zkvalidium-quickstart_zkevm_event_db_data" Created 0.0s
✔ Container zkevm-state-db Started 0.0s
docker compose -f docker-compose.yml up -d zkevm-pool-db
[+] Building 0.0s (0/0) docker:default
[+] Running 1/1
✔ Container zkevm-pool-db Started 0.0s
docker compose -f docker-compose.yml up -d zkevm-event-db
[+] Building 0.0s (0/0) docker:default
[+] Running 1/1
✔ Container zkevm-event-db Started 0.1s
make[1]: Leaving directory '/home/tk/test_validium/zkValidium-quickstart'
docker compose -f docker-compose.yml up -d zkevm-mock-l1-network
[+] Running 1/1
✔ zkevm-mock-l1-network Pulled 1.8s
[+] Building 0.0s (0/0) docker:default
[+] Running 1/1
✔ Container zkevm-mock-l1-network Started 0.0s
sleep 2
docker compose -f docker-compose.yml up -d zkevm-prover
[+] Building 0.0s (0/0) docker:default
[+] Running 1/1
✔ Container zkevm-prover Started 0.0s
docker compose -f docker-compose.yml up -d zkevm-approve
[+] Building 0.0s (0/0) docker:default
[+] Running 1/1
✔ Container zkevm-approve Started
(中略)
docker compose -f docker-compose.yml up -d zkevm-metrics
[+] Building 0.0s (0/0) docker:default
[+] Running 1/1
✔ Container zkevm-metrics Started 0.0s
make[1]: Leaving directory '/home/tk/test_validium/zkValidium-quickstart'
$
エラーなく完了した後、コンテナのステータスを確認します。
35のコンテナが起動していることがわかります。
$ sudo docker ps --format "table {{.Names}}\t{{.Command}}\t{{.Status}}\t{{.Ports}}"
NAMES COMMAND STATUS PORTS
zkevm-metrics "/bin/prometheus --c…" Up 2 minutes 0.0.0.0:9090->9090/tcp, :::9090->9090/tcp
explorer-sig-provider "./sig-provider-serv…" Up 2 minutes 0.0.0.0:8151->8050/tcp, :::8151->8050/tcp
visualizer-proxy "/docker-entrypoint.…" Up 2 minutes 80/tcp, 0.0.0.0:8083->8081/tcp, :::8083->8081/tcp
explorer-visualizer "./visualizer-server" Up 2 minutes 0.0.0.0:8152->8050/tcp, :::8152->8050/tcp
explorer-smart-contract-verifier "./smart-contract-ve…" Up 2 minutes 0.0.0.0:8150->8050/tcp, :::8150->8050/tcp
explorer-proxy-l2 "/docker-entrypoint.…" Up 2 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:8084->8080/tcp, :::8084->8080/tcp
explorer-stats-l2 "./stats-server" Up 2 minutes 0.0.0.0:8154->8050/tcp, :::8154->8050/tcp
explorer-stats-db-l2 "docker-entrypoint.s…" Up 2 minutes 0.0.0.0:7434->5432/tcp, :::7434->5432/tcp
explorer-frontend-l2 "./entrypoint.sh nod…" Up 2 minutes 0.0.0.0:3001->3000/tcp, :::3001->3000/tcp
explorer-backend-l2 "sh -c 'bin/blocksco…" Up 2 minutes 0.0.0.0:4001->4000/tcp, :::4001->4000/tcp
zkevm-explorer-json-rpc "/bin/sh -c '/app/zk…" Up 2 minutes 0.0.0.0:8124->8124/tcp, :::8124->8124/tcp, 8123/tcp, 0.0.0.0:8134->8134/tcp, :::8134->8134/tcp
explorer-backend-l2-db "docker-entrypoint.s…" Up 2 minutes 0.0.0.0:5437->5432/tcp, :::5437->5432/tcp
explorer-proxy-l1 "/docker-entrypoint.…" Up 2 minutes 0.0.0.0:81->80/tcp, :::81->80/tcp, 0.0.0.0:8082->8080/tcp, :::8082->8080/tcp
explorer-stats-l1 "./stats-server" Up 2 minutes 0.0.0.0:8153->8050/tcp, :::8153->8050/tcp
explorer-stats-db-l1 "docker-entrypoint.s…" Up 2 minutes 0.0.0.0:7433->5432/tcp, :::7433->5432/tcp
explorer-frontend-l1 "./entrypoint.sh nod…" Up 2 minutes 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp
explorer-backend-l1 "sh -c 'bin/blocksco…" Up 2 minutes 0.0.0.0:4000->4000/tcp, :::4000->4000/tcp
explorer-backend-l1-db "docker-entrypoint.s…" Up 2 minutes 0.0.0.0:5436->5432/tcp, :::5436->5432/tcp
zkevm-bridge-ui "/bin/sh /app/script…" Up 2 minutes 0.0.0.0:8088->80/tcp, :::8088->80/tcp
zkevm-bridge-service "/bin/sh -c '/app/zk…" Up 2 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:9080->9090/tcp, :::9080->9090/tcp
zkevm-bridge-db "docker-entrypoint.s…" Up 2 minutes 5438/tcp, 0.0.0.0:5438->5432/tcp, :::5438->5432/tcp
zkevm-data-availability "/bin/sh -c '/app/cd…" Up 2 minutes 0.0.0.0:8444->8444/tcp, :::8444->8444/tcp
zkevm-data-node-db "docker-entrypoint.s…" Up 2 minutes (healthy) 0.0.0.0:5444->5432/tcp, :::5444->5432/tcp
zkevm-json-rpc "/bin/sh -c '/app/zk…" Up 2 minutes 0.0.0.0:8123->8123/tcp, :::8123->8123/tcp, 0.0.0.0:8133->8133/tcp, :::8133->8133/tcp, 0.0.0.0:9091->9091/tcp, :::9091->9091/tcp
zkevm-aggregator "/bin/sh -c '/app/zk…" Up 2 minutes 8123/tcp, 0.0.0.0:50081->50081/tcp, :::50081->50081/tcp, 0.0.0.0:9093->9091/tcp, :::9093->9091/tcp
zkevm-l2gaspricer "/bin/sh -c '/app/zk…" Up 2 minutes 8123/tcp
zkevm-sequence-sender "/bin/sh -c '/app/zk…" Up 2 minutes 8123/tcp
zkevm-sequencer "/bin/sh -c '/app/zk…" Up 2 minutes 0.0.0.0:6060->6060/tcp, :::6060->6060/tcp, 0.0.0.0:6900->6900/tcp, :::6900->6900/tcp, 8123/tcp, 0.0.0.0:9092->9091/tcp, :::9092->9091/tcp
zkevm-eth-tx-manager "/bin/sh -c '/app/zk…" Up 2 minutes 8123/tcp, 0.0.0.0:9094->9091/tcp, :::9094->9091/tcp
zkevm-sync "/bin/sh -c '/app/zk…" Up 2 minutes 8123/tcp, 0.0.0.0:9095->9091/tcp, :::9095->9091/tcp
zkevm-prover "zkProver -c /usr/sr…" Up 3 minutes 0.0.0.0:50061->50061/tcp, :::50061->50061/tcp, 0.0.0.0:50071->50071/tcp, :::50071->50071/tcp
zkevm-mock-l1-network "/usr/local/bin/entr…" Up 3 minutes 9545/tcp, 0.0.0.0:8545-8546->8545-8546/tcp, :::8545-8546->8545-8546/tcp, 30303/tcp, 30303/udp
zkevm-event-db "docker-entrypoint.s…" Up 3 minutes 0.0.0.0:5435->5432/tcp, :::5435->5432/tcp
zkevm-pool-db "docker-entrypoint.s…" Up 3 minutes 0.0.0.0:5433->5432/tcp, :::5433->5432/tcp
zkevm-state-db "docker-entrypoint.s…" Up 3 minutes 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp
zkEVM エクスプローラにアクセス
ローカルノード上で作業していればブラウザで「localhost」にアクセスします。リモートマシンから作業している場合は、Validium ノードをセットアップしているIPアドレスで接続します(以降その場合は "localhost" を読み替えてください)。
MetaMask の設定と準備
モックとしてのL2ネットワークを追加します。
チェーンID: 1001
通貨記号: POL(実際なんでもよい)
RPCノード: http://localhost:8123
ブロックエクスプローラ: http://localhost:4001
テスト資金(トークン)が入っているアカウントが利用可能となっているので、そのプライベートキー「0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80」を使ってアカウントをインポートします。
すると、残高が 100000 POL と表示されます。
POL の送信確認
100 POL を別のアカウント(Account 8)に送ります。
※送信のオペレーションは割愛
送った後の POL の残高を確認します。
送信先のアカウント(Account 8)の状態を確認し、残高が 100 POL となっていることを確認します。
zkEVM エクスプローラでこのトランザクションを確認できます。
ブリッジの動作確認
CDK にはネイティブブリッジとUIが搭載されており、これをつかってL1とL2間で資金移動をすることができます。
ここからの操作は、アカウント1つ(Account 7)で行います。
L1 から L2
つまり、イーサリアム(ここではモックネットワーク)ネットワークから、Astar zkEVM です。
MetaMaskに L1 のイーサリアムモックネットワークの設定を追加します。
チェーンID: 1337
通貨記号: POL(実際なんでもよい)
RPCノード: http://localhost:8545
ブロックエクスプローラ: http://localhost:4000
※この追加したモックネットワークは、MetaMask でテストネットワークとして認識されている場合があるため、表示についてはそちらを確認してください。
L1ネットワークに切り替えると、いくらか POL(以下の例だとおよそ 100000 POL)を持っていることがわかります。
http://localhost:8088 ブリッジに移動して、UIを確認します。
以下の表示(Conect a wallet)は最初にアクセスしたときのみ表示されます。「Connect a wallet」をクリックし、前にインポートしたアカウントを選択します。
接続が完了すると、以下のようなページが表示されます。
ここでは、10 ETH をL2に送ってみます。金額を入力し「Continue」を押します。
以下のようなポップアップがでるため、「I understand」と入力して、「Continue」を押します。
確認画面になりますので「Bridge」を押し、MetaMask のポップアップでトランザクションの承認をします。
ブリッジが完了すると、Activity ページが表示されます。
L1のエクスプローラー(localhost:4000)上からもトランザクションを確認できます。
MetaMask のネットワークを L2(My Local Testnet)に切り替えると、10 POL 送られている事がわかります。
L2 から L1
MetaMask のネットワークをL2、つまり「My Local Testnet」のチェーンに切り替えます。
ブラウザでブリッジ(localhost:8088)にアクセスします。
更新された、L1とL2の残高が表示されます。
先ほど「10」トークンをL2に送信したので、今度はそのうちの「5」トークンをL1に戻してみます。
確認画面が出るので、「Bridge」を押し、MetaMask のポップアップでトランザクションの承認をします。
トランザクションは実行され、プロセスが進みます。
ブリッジUIの Activity ページは下記のようにステータスが進みます。
プロセスが進み、以下のような「On Hold(保留中)」状態となったら「Finalise」を押します。MetaMask のポップアップでL1に切り替えるよう促されるので、切り替えた後トランザクションを承認します。
トランザクションが実行されたあと、処理が進み、Activity ページではステータスの完了が表示されたら、L2からL1へのブリッジは完了です。
L1からL2へのトークンの移動は直観的で、1アクションで速やかに転送できますが、一方、L2からL1へのトークン移動はステップが大きく2つあり、セキュリティをしっかり確保するためにトークンを移動させる前にトランザクションを確定させるプロセスが必要であり、そのために時間を要します。
以上、クイックスタートガイドをもとにしてローカルマシン上に Validium ノードを構築し、L1とL2の関係性を実際のトークンの転送をしながら確認しました。