FlowのAccess Nodeを構築してみた(校正前)

Takashi Tahara (田原 崇)
25 min readSep 15, 2023

--

※※※※※Advertisement|広告※※※※※

書籍、SvelteとGraphQLでブロックチェーンゲームを作る!が好評発売中です。(URLは以下)

※※※※最新フレームワークでBlockchainアプリ開発ならこの一冊!※※※

前回の記事で、Nodeのセットアップまで行いました。

そこで1日以上経過したので試しにBillingページを見てみました。

AWS EC2 m6i.xlarge インスタンスが32時間使用で7.94 USDでした。1ヶ月(=30日)使用すると日本円で25,891円(1$=145¥で計算)かかります。

これはインスタンスだけなのでEBS750GBの費用が別にかかります。だいたい750GBで1万円かかりますので、Access Nodeの運営は一月3万5千円~4万円かかる、と見ていいでしょう。

前回の記事の中でNode IDを登録する為に100FLOWをステークしました。1週間にこのNode IDは5つAccess Nodeに選出されます。(これもスマートコントラクトのようです。Eventが飛びますので)今はFlow人気が熱い時期ではないので1週間に5つのスロットでも選出されそうですが、次第に難しくなっていきそう。その間EC2の費用が飛んでいきます。。

Flow BlockchainにはObserver Nodeというのがあり、任意のAccess Nodeに対し、トランザクションの発行を依頼することが出来ます。このObserver Nodeって必要なの? と思うかも知れませんが、Access Nodeを運営している側にとっては、わざわざAPIを実装する必要がなくなる(Observer Nodeに実装がされている)のでAPI販売が楽になります(その為にObserver Nodeが作られたのだと思います)。(ノード運営者はそのノードのAPIを販売して生業をします)

先日、EthereumのStakeした6000ETHがノードの運営者によってexploited(搾取)された事件(ビデオの4:35頃~)がありましたので、フルノード(FlowではAccess Node)を国内に置くようにライセンス取得希望者に指示する金融庁の判断は正しかったのだと思います。

1週間後の木曜日が来ました! 果たして、Node IDはアクセスノードとして受け付けられたのでしょうか?

Staked Amountのところに100FLOWと表示されてますね!やりました!1週間でAccess Node登録をすることが出来ました!

分かりにくいですが、1週間前の時点では以下のように表示されていました。

Staked AmountがPending

では、Nodeを走らせてみましょう。

と、その前にEBSストレージを追加しましょう。750GBが理想と公式では書かれています。

EBSボリュームを追加します。

WebコンソールのEC2の画面の左メニューでEBSのVolumeを選択し、右上のCreate Volumeを押します。

Access Nodeに必要とされるストレージ容量は750GBなので740GBを追加します。

Create Volumeを押します。

Availability Zoneはインスタンスと同じ場所である必要があります

Volume stateがAvailableに変わったら、作成したボリュームを選択して右上のActionsからAttach Volumeを選択します。

インスタンスを選択してAttach Volumeを押します。

Volume stateがIn-useに変わりますので、次にインスタンスにsshで繋ぎます。

df -hコマンドを実行します。(現在のボリュームのサイズを表示します)

740GBのボリュームはこの時点で表示されません

最初に作った10GBのボリュームしか表示されませんので、次に

lsblkコマンドを実行します。(Linuxの全てのblock deviceを表示します)

740GBのボリュームが表示されます。

ここにblock deviceの名前が表示されますので

file -s /dev/[device名] コマンドを実行します。

dataと表示されます。

ここがdataと表示されるというのはボリュームにパーティションが切られていない為、このblock deviceに対してfile systemをセットアップする必要があることを意味しますので、

mkfs -t xfs /dev/[device名] コマンドを実行します。

xfsファイルシステムをsetup

再度、file -s /dev/[device名] コマンドを実行します。

740GBのボリュームにfile systemを持たせました

次に一つのディレクトリにこのボリュームをマウントするのですがそのディレクトリは空でないといけません。

現在、作業フォルダ(/home/ec2-user)の下にはdataフォルダがあります。ここに740GBのボリュームをマウントしたいのですが、このフォルダ内にファイルがあるため、一度このフォルダをリネームし、新しくdataフォルダを作成します。

以下コマンドを実行します。

mv ./data ./data_copy
mkdir ./data

740GBのボリュームを/home/ec2-user/dataディレクトリにマウントします。

mount /dev/[device名] /home/ec2-user/data コマンドを実行します。

df -hコマンドを実行すると740GBのボリュームが表示されました!これでEBSボリュームの追加処理は完了です!

最後に元々/home/ec2-user/dataの中にあったファイルをこのディレクトリ内に戻します。

mv ./data_copy/* ./data コマンドを実行します。

ここの部分はこちらのWebページを参考にさせて頂きました。

Access Nodeを起動します

以下のコマンドを実行します。

sudo docker run --rm \
-v $PWD/bootstrap:/bootstrap:ro \
-v $PWD/data:/data:rw \
--name flow-go \
--network host \
gcr.io/flow-container-registry/access:v0.29.8 \
--nodeid=[Access Nodeとして登録しておいたNode ID] \
--bootstrapdir=/bootstrap \
--datadir=/data/protocol \
--secretsdir=/data/secrets \
--rpc-addr=0.0.0.0:9000 \
--http-addr=0.0.0.0:8000 \
--rest-addr=0.0.0.0:80 \
--rpc-metrics-enabled=true \
--bind 0.0.0.0:3569 \
--dynamic-startup-access-address=secure.mainnet.nodes.onflow.org:9001 \
--dynamic-startup-access-publickey=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae \
--dynamic-startup-epoch-phase=EpochPhaseStaking \
--loglevel=error

起動しました! が、数10秒でエラーが出ました….

Troubleshooting

  1. 到達不能エラー
{
"level":"fatal",
"node_role":"access",
"node_id":"75f84c62148ccb4f11bb540d72cd85a5927dbf74f70831b275f2f82cacd6c9c6",
"error":"failed to validate flag --dynamic-start-epoch: failed to get
snapshot: failed to get latest finalized protocol state snapshot during
pre-initialization: client: rpc error: code = Unavailable desc = connection
error: desc = \"transport: Error while dialing dial tcp 35.202.246.32:9001:
i/o timeout\"",
"time":"2023-09-14T03:17:41.518105867Z”
}

descとはdescriptionの省略ですね。(降順の意味ではなく)

Error while dialing dial tcp 35.202.246.32:9001: i/o timeout

この35.202.246.32とはFlowネットワークのAccess Node Bootstrap用のノードのIPアドレスのことです。どこで見かけたのか忘れてしまいましたが、Troubleshooting中にそう記載のあるページを見みつけました。

Access Nodeの立ち上げのためにFlowのBootstrap用のノードにアクセスしようとしたがタイムアウトになったとありますので、サブネットのAccess Control Listの内容をチェックしてInboundポートとOutboundポートを全て解放(1–65535をAllowに変更)します。するとこのエラーは消えました。AWSのSecurity Groupは前回の記事での設定から変更しなくて大丈夫です。

2. key not found エラー

{
"level":"fatal",
"node_role":"access",
"node_id":"75f84c62148ccb4f11bb540d72cd85a5927dbf74f70831b275f2f82cacd6c9c6",
"error":"could not bootstrap protocol state: bootstrapping failed: could not
bootstrap sealing chain segment blocks: could not insert root block: could not
store payload: invalid payload referencing unknown execution result
20a8bdca9189578566cb4dfaa358d3d8e1638d92f866a66dcd732ab771d330ef, err: could
not retrieve resource: key not found",
"time":"2023-09-14T09:42:10.401181253Z”
}

これは結論から言いますと、まだノードがネットワークに入っていない為のエラーです。(すみません、後で説明しますが、これはdataフォルダ内に古い情報があるためです。記事を書きながら実行しているので少し不正確な部分があります

昨日、先週Node IDをNodeステーキングで登録した結果を確認したら、Staked Amountに100FLOWが表示されたので、早速Accessノードを立ち上げようと思ったのですが、実際にノードがFlowネットワークに入るのはトランジション期間中であり、それは水曜日(日本時間では水曜深夜)であり、それまではネットワークに入っていないのでエラーになるのだとのことでした。

1週間にPermissionless Access Nodeとして登録されるのは5つだけですので、やった!選ばれた! (Node IDが選ばれた時はtokensCommitted bucketからtokensStaked Bucketというところに100FLOWが移動します。選ばれていない場合はtokensCommitted bucketからtokensUnstaked Bucketに100FLOWが移動します。)と思って勇んで起動しようとしても、もう1週間待つ必要があるようです。

ネットワークに入ったかを確認するためにFlow CLIをインストールします。(以下コマンドをCrowdShell上で実行します。)

sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)"

Make sure /home/ec2-user/.local/bin is in your $PATH environment variable.

と表示されますが、私の環境では既に$PATHに/home/ec2-user/.local/binが入っていました。(echo $PATHで確認出来ます)

1コマンドです。便利ですね。

最初にFLOWがステーキングされているか確認します。(FlowPortでステーキングされているのは確認しましたが念の為)

flow accounts staking-info 0x99765333ee05a931 -n mainnet

コマンドを実行します。0x99765333ee05a931というのは私がFlowPortでFLOWをステーキングするためにサインインしたBloctoのアカウントです。(私もなぜBloctoのアカウント?と思いましたが、サインインできるのがBloctoしかなかったので私のemailアドレスに紐づいたBloctoアカウントに持たせた100FLOWでEC2上のAccess Node Node IDを登録しています。)

ここで、❌ Command Error: error getting staking info: missing configuration と表示されますので、flow.jsonファイルを作成する為に以下のコマンドを実行します。

flow setup (プロジェクト名) --scaffold

General Scaffoldsで大丈夫ですので1を選びました。その後、cd(プロジェクト名)でflow.jsonファイルのある場所に移動します。

flow accounts staking-info 0x99765333ee05a931 -n mainnetコマンドを実行すると以下のように表示されます。

ちゃんとステーキングされてますね! Account has no delegationとあるので、このNodeを経由してFlowをステーキングすることもできそうです。delegationされたFLOWの数が増えるとノードオペレーターにも報酬があるそうですが、それはAccess Nodeにも払われるかは不明です。Access Nodeのオペレーターはノーリスクな(止まっても損害を負わない)ので他の4ノードと同じ報酬率が得られると不公平だと思います。

公式ドキュメントには以下の記載があります。

Tokens Stakedが100となっているそのノードはAccess Nodeに選ばれている。

その下に

Step 4 — Start your node

If your node was selected as part of Step 3, you can now start your node.

の表記がありますが、残念ながらこれは不正確ですね。(すみません、ここも後に説明しますが、これはdataフォルダ内に古い情報があるため実行時出来なかっただけでした。記事を書きながら実行している為少し不正確な記述をしている部分があります)そこで、

ネットワークに入ったかを確認するためのコマンドを実行

するのですが、実はこのコマンドをFlowのノード開発責任者であるVishal Changrani氏に行ってもらいました。

Vishal氏のメールアドレスを知っていたので、key not found エラーが起きた時にメールで聞いていました。(何て贅沢な!!)すると代わりに調べてくれました。(本来はDiscordで聞くべきですが、FlowハッカソンSeason2後、Discordを開くのが抵抗あったのでメールで問い合わせました。)

$ flow scripts execute ./transactions/idTableStaking/scripts/get_node_info.cdc --args-json  '[{ "type":"String", "value":"75f84c62148ccb4f11bb540d72cd85a5927dbf74f70831b275f2f82cacd6c9c6"}]' --host access.mainnet.nodes.onflow.org:9000  

Result: A.8624b52f9ddcd04a.FlowIDTableStaking.NodeInfo(id: "75f84c62148ccb4f11bb540d72cd85a5927dbf74f70831b275f2f82cacd6c9c6", role: 5, networkingAddress: "ec2-18-176-215-185.ap-northeast-1.compute.amazonaws.com:3569", networkingKey: "6015142e4f66fe0e63cfd08d31869e06c8fac65432e515872930146f0a2797c1205468e8da6d24bdcc44149fea165474cc431d860321fa06b4c0cf0f5da9ec23", stakingKey: "9376b00f32d874171db211cb389329bc7eaabd2d2cb3eaab0dcdcc45f3994864faac3d7a1888856d89e0a44939e5a26b1712730338c9c7a41159c165193735468baff381efbcc82207d1f506e906a17260480b3b150a3b99effc6f9f234a8a1f", tokensStaked: 100.00000000, tokensCommitted: 0.00000000, tokensUnstaking: 0.00000000, tokensUnstaked: 0.00000000, tokensRewarded: 0.00000000, delegators: [], delegatorIDCounter: 0, tokensRequestedToUnstake: 0.00000000, initial weight: 100)

このコマンドを実行するとネットワークに入ったか分かるそうです。

しかし、先ほど作ったばかりのFlowの設定では./cadence/transactionsの下は空であり、idTableStakingフォルダはありません。仕方ないのでAsk AIで聞いてみます。

flow-core-contractsというところにあると教えてくれます。

flow-core-contractsというリポジトリからPullしてくるみたいです。

gitをインストールします。

$ sudo dnf install git
$ git config --global user.name "Emma Paris"
$ git config --global user.email "eparis@atlassian.com"

flow-core-contractsリポジトリをgit cloneします。

git clone https://github.com/onflow/flow-core-contracts.git

Vishal氏に頂いたコードを私も実行してみます。

flow scripts execute ./flow-core-contracts/transactions/idTableStaking/scripts/get_node_info.cdc --args-json  '[{ "type":"String", "value":"75f84c62148ccb4f11bb540d72cd85a5927dbf74f70831b275f2f82cacd6c9c6"}]' --host access.mainnet.nodes.onflow.org:9000

すると以下のように表示されますのでこの0xIDENTITYTABLEADDRESSをviで0x8624b52f9ddcd04aに変更してもう一度実行します。

するとこのように出力されました。

Result: A.8624b52f9ddcd04a.FlowIDTableStaking.NodeInfo(
id: "75f84c62148ccb4f11bb540d72cd85a5927dbf74f70831b275f2f82cacd6c9c6",
role: 5, // 十中八九、Access Nodeのこと
networkingAddress: "ec2-18-176-215-185.ap-northeast-1.compute.amazonaws.com:3569",
networkingKey: "6015142e4f66fe0e63cfd08d31869e06c8fac65432e515872930146f0a2797c1205468e8da6d24bdcc44149fea165474cc431d860321fa06b4c0cf0f5da9ec23",
stakingKey: "9376b00f32d874171db211cb389329bc7eaabd2d2cb3eaab0dcdcc45f3994864faac3d7a1888856d89e0a44939e5a26b1712730338c9c7a41159c165193735468baff381efbcc82207d1f506e906a17260480b3b150a3b99effc6f9f234a8a1f",
tokensStaked: 100.00000000, // ←ここに100以上あるとAccess NodeのNodeIDとして選ばれている
tokensCommitted: 0.00000000,
tokensUnstaking: 0.00000000,
tokensUnstaked: 0.00000000,
tokensRewarded: 0.00000000,
delegators: [],
delegatorIDCounter: 0,
tokensRequestedToUnstake: 0.00000000,
initialWeight: 100
)

しっかり登録されていますね。あれっ…? おかしいな、Vishal氏のメールではまだネットワークに追加されていない、とあってその下に上記内容があったので、このコマンドでまだFlowネットワークに追加されていないことがわかると思ったのですが、どうやらNode IDが登録されていることを確認するためのコマンドだったようです。

ではその後のVishal氏のメールの文面を見ていきます。

The nodes get added on every epoch transition, which happens every Wednesday. So, this upcoming Wednesday is when you can expect the node to get added to the network. After that, you need to delete the data folder and start your node.

delete the data folderはおそらく最初からやり直して、という意味だと思います。boot-toolsの中にあるファイルからAccess Nodeが立ち上がるので。

このブログのEBS追加の中でdata_copyの中身をdataフォルダに戻しましたがあれは余計な行動だったみたいですね。もう一度dataフォルダの中を削除してdocker run で立ち上げてみます。

dataフォルダ内をrm -rf ./data/*コマンドで空にしました。

docker runコマンドを実行します。今度は-itdをつけます。

sudo docker run --rm \
-v $PWD/bootstrap:/bootstrap:ro \
-v $PWD/data:/data:rw \
--name flow-go \
--network host -itd \
gcr.io/flow-container-registry/access:v0.29.8 \
--nodeid=75f84c62148ccb4f11bb540d72cd85a5927dbf74f70831b275f2f82cacd6c9c6 \
--bootstrapdir=/bootstrap \
--datadir=/data/protocol \
--secretsdir=/data/secrets \
--rpc-addr=0.0.0.0:9000 \
--http-addr=0.0.0.0:8000 \
--rest-addr=0.0.0.0:80 \
--rpc-metrics-enabled=true \
--bind 0.0.0.0:3569 \
--dynamic-startup-access-address=secure.mainnet.nodes.onflow.org:9001 \
--dynamic-startup-access-publickey=28a0d9edd0de3f15866dfe4aea1560c4504fe313fc6ca3f63a63e4f98d0e295144692a58ebe7f7894349198613f65b2d960abf99ec2625e247b1c78ba5bf2eae \
--dynamic-startup-epoch-phase=EpochPhaseStaking \
--loglevel=error

-itdコマンドをつけましたので出力をsudo docker logs — tail 100 flow-goコマンドで確認します。

あっ、動いていますね。すみません、先週、試しにdocker runさせてその時に生成されたファイルをそのままにしてもう一回動かしてもダメだそうです。一度、dataフォルダ内を削除してからdocker runさせる必要がありそうです。

良かった、Vishal氏に聞いてなかったらずっとハマっていましたね。。

level: fatalはその場でdockerが停止してしまいますが、そうではなくてlevel: errorが吐き出され続けているのは気になりますが、動いているということは進展です。

と思ったら既にflow-go dockerが落ちていました。すみません、ぐだぐだで…

やはりVishal氏に言われた通り来週木曜日にもう一度dataフォルダ内を空にして再実行してみます。

--

--

Takashi Tahara (田原 崇)

Programmer, Blockchain engineer, AI Engineer, and Front-end Engineer ( I have several certifications of Cisco, IBM, AWS, Google Cloud, C++, Go, Rust and more.)