Flow コミュニティ・アーカイブ・ノードのオープンベータ版を開始しました

Ara
Flow Japan
Published in
13 min readDec 8, 2022

私たちは、Flow コミュニティ・アーカイブ・ノードのオープンベータを発表することに興奮しています。アーカイブ・ノードは、Flow プロトコルの実行ステートの履歴にアクセスするための、スケーラブルで効率的な方法を提供します。これは、gRPC の Access API を使って、現在のスポークの開始から最新のシールされたブロックまでのあいだの任意のブロックで、アカウントの詳細を照会し、スクリプトを実行するために使用できます。

※本記事はこちらの投稿を日本語に翻訳したものです

アーカイブ・ノードとは何ですか?

Flow のマルチノード・アーキテクチャは、コンセンサスと実行を分離して、トランザクション実行のために少数のハイスペックな実行ノードを用意することで、将来性のあるスケーリングを提供します。これらの実行ノードは、実行ステート(Flow アカウント、スマートコントラクト、リソースなどの状態)をメモリに保持し、高速にアクセスできるように設計されています。しかし、ステートが無限に増え続けることを考慮して、過去 100 ブロックまでの最新ステートのみを保持するよう設計されています。そのため、過去のステートを照会したいアプリケーションに対して、100 ブロック前よりも古い実行ステートを提供する効率的なソリューションが必要とされています。アーカイブ・ノードは、そのようなソリューションを提供し、アーカイブのデータを提供することを目的としています。

アーカイブ・ノードは、チェーンをたどるノードで、プロトコル・ステートと実行ステートの両方を保存し、インデックスを付けます。これは実行ステートのレジスタ値を必要とする、スクリプト実行のような読み取り専用のクエリを可能にします。例えば「ブロック番号 X の Flow アカウントの残高はどうなっていたか」(X は過去 数千ブロック)など、過去のデータからあらゆるクエリに応答するために使えます。

アーカイブ・ノードはどのように動作しますか?

オブザーバ・ノードと同様に、アーカイブ・ノードもステーク不要のノードであり、上流のアクセスノードと通信します。オブザーバ・ノードはプロトコル・ステート(ブロック、コレクション、トランザクションなど)のみを受け取り、アーカイブ・ノードはプロトコル・ステートと実行ステートの両方を受け取ります。

アーカイブ・ノードは誰が使うべきですか?

  • 過去のデータにアクセスする必要がある dApps、例えば、過去のブロックにおけるユーザーアカウントの残高を考慮する CAST など
  • 過去のデータにアクセスする必要があるチェーン分析および監査ツール

アーカイブ・ノード vs アクセス・ノード vs オブザーバ・ノード

アーカイブ・ノード、アクセス・ノード、オブザーバ・ノードの違いを説明する前に、まず、Flow の 2 種類のステートについて説明しましょう。Flow は単一のバリデータ・ノードではなく、さまざまな種類のノードを持つため、すべてのノードの種類がすべてのデータを持つわけではありません。Flow のステートは「プロトコル・ステート」と「実行ステート」に分けられます。

プロトコル・ステートとは、ID テーブルや Flow ネットワーク内のノードが生成するリソース(ブロック、コレクション、レシート、承認、シールなど)を含む、Flow ネットワークプロトコルの動作に関するステートです。

実行ステートとは、Flow のアカウント、スマートコントラクト、リソースなどのステートです。このステートは、実行ノードにだけ完全に保存されます。

アクセス・ノードは、すべてのプロトコル・ステートのデータを受信してインデックスを作成し、Access API を提供するステークしたノードです。GetBlock、GetAccount、GetCollection など、プロトコル・ステートに関連するすべての Access API 呼び出しに対して、ローカルのデータベースを照会して応答できます。しかし、GetAccount や ExecuteScriptAtXXX などの実行ステートに関連する呼び出しについては、実行ノードに上流呼び出しを行って実行ステートのデータを取得します。

今年初め、アクセス・ノードに代わる、ステークなしで誰でも実行できるノードとして、オブザーバ・ノードを発表しました。アクセスノード同様にオブザーバ・ノードも Access API を提供します。ただ、オブザーバ・ノードは、最新のブロックデータを受信してインデックスを作成するだけで、ブロックデータ以外の Access API 呼び出しはすべて上流のアクセスノードに委ねます。

現在、アクセス・ノードやオブザーバ・ノードに対して、最新ブロックのアカウント残高を問い合わせたり、最新ブロックのスクリプトを実行することは簡単にできますが、過去の任意のブロックのアカウント残高を問い合わせたりスクリプトを実行したりすることはできません。実行ノードは過去 100 ブロック以上の実行ステートを保持しないため、以下のようなエラーが発生します。

rpc error: code = Internal desc = failed to get account: failed to get account at block (xxx): state commitment not found (yyy). this error usually happens if the reference block for this script is not set to a recent block.

ここでアーカイブ・ノードの出番です。

アクセス・ノードやオブザーバ・ノードとは異なり、アーカイブ・ノードはプロトコル・ステートだけでなく実行ステートも保存し、インデックスを作成します。そして、GetAccount などの実行ステートにアクセスする API 呼び出しに対して、ローカルのデータベースから応答できます。

アクセス・ノード

  • Flow Network の一部(他のステーク・ノードと会話する): はい
  • 対応 API: すべての Access API
  • 誰でもノードを実行できるか: はい(2023 Q1 に向けてリクエスト可)
  • コミュニティ運営ノードのレート制限ここを参照

オブザーバ・ノード

  • Flow Network の一部(他のステーク・ノードと会話する): いいえ
  • 対応 API: すべての Access API(gRPC エンドポイントのみ)
  • 誰でもノードを実行できるか: はい
  • コミュニティ運営ノードのレート制限:アクセス・ノードと同じ

アーカイブ・ノード

  • Flow Network の一部(他のステーク・ノードと会話する): いいえ
  • 対応 API: 一部の Access API(gRPC エンドポイントのみ)
  • 誰でもノードを実行できるか: はい(2023 年のローンチ後)
  • コミュニティ運営ノードのレート制限ここを参照
  • ノードを運営したくない場合は、Flow コミュニティ・アクセス・ノードをご利用ください
  • シングル・テナントが望ましい、または、Access API のレート制限を受けたくない場合は、独自のアクセス・ノードの実行を検討してください
  • 最新のブロックデータを提供する、ローカルで動作するノードが必要な場合は、オブザーバ・ノードを実行してください
  • 過去の実行ステートにアクセスしたい場合は、コミュニティ・アーカイブ・ノードをご利用ください

API

アーカイブ・ノードでは、gRPC の Access APIの簡易バージョンとして以下 3 つの API を提供します。

  1. ExecuteScriptAtBlockID
  2. ExecuteScriptAtBlockHeight
  3. GetAccountAtBlockHeight

これ以外の Access API 呼び出しに対しては、HTTP エラー 501 Not implemented を返します。

gRPC API のエンドポイントは、 archive.mainnet.nodes.onflow.org:9000 です。

使用例

1.現在のスポーク開始時点のアカウント残高を取得するには、アーカイブ・ノードの GetAccountAtBlockHeight を呼び出すとよいでしょう。

サンプル・コード:

package main

import (
"context"
"fmt"
"github.com/onflow/flow-go-sdk/access/grpc"

"github.com/onflow/flow-go-sdk"
)

func main() {
// the Flow community archive API endpoint
archiveNodeAddress := "archive.mainnet.nodes.onflow.org:9000"

// create a gRPC client for the Archive node
archiveNodeClient, err := grpc.NewClient(archiveNodeAddress)
if err != nil {
fmt.Println("err:", err.Error())
panic(err)
}

ctx := context.Background()

addr := flow.HexToAddress("e467b9dd11fa00df") // any Flow account address

// get Account balance at the start height of the current spork
// <https://developers.flow.com/nodes/node-operation/past-sporks#mainnet-20>
account, err := archiveNodeClient.GetAccountAtBlockHeight(ctx, addr, 40171634)
if err != nil {
fmt.Println("err:", err.Error())
panic(err)
}

fmt.Println(account.Balance)
}

2.過去のあるブロックでスクリプトを実行するには、アーカイブ・ノードの ExecuteScriptAtBlockHeight または ExecuteScriptAtBlockID を呼び出せばよいでしょう。

サンプル・コード:

package main

import (
"context"
"fmt"
"github.com/onflow/cadence"
"github.com/onflow/flow-go-sdk/access/grpc"
)

func main() {
// the Flow mainnet community Access node API endpoint
accessNodeAddress := "access.mainnet.nodes.onflow.org:9000"

// the Flow community archive API endpoint
archiveNodeAddress := "archive.mainnet.nodes.onflow.org:9000"

// create a gRPC client for the Access node
accessNodeClient, err := grpc.NewClient(accessNodeAddress)
if err != nil {
fmt.Println("err:", err.Error())
panic(err)
}

ctx := context.Background()

// get the height of the latest sealed block from the Flow mainnet community access node
latestBlockHeader, err := accessNodeClient.GetLatestBlockHeader(ctx, true)
if err != nil {
fmt.Println("err:", err.Error())
panic(err)
}

// set height to 500 blocks in the past
height := latestBlockHeader.Height - 500

// create a gRPC client for the Archive node
archiveNodeClient, err := grpc.NewClient(archiveNodeAddress)
if err != nil {
fmt.Println("err:", err.Error())
panic(err)
}

script := []byte(`
pub fun main(a: Int): Int {
return a + 10
}
`)
args := []cadence.Value{cadence.NewInt(5)}

// execute script on the archive node at a block height which is 500 blocks in the past
value, err := archiveNodeClient.ExecuteScriptAtBlockHeight(ctx, height, script, args)
if err != nil {
fmt.Println("err:", err.Error())
panic(err)
}

fmt.Printf("\\nValue: %s", value)
}

制限

  • gRPC API のレート制限
  • Access REST API と gRPC-web エンドポイントには現状は未対応です
  • アーカイブ・ノードは、現状はセルフホスティングができません
  • アーカイブ・ノードは、現在のスポーク開始時点までしか遡れません

ノードの稼働ステータス

アーカイブ・ノードの稼働ステータスは、Flow ステータス・ページの “Flow mainnet archive node components” から確認できます。

次のステップは何?🚀

これはオープン・ベータ版であり、来年初めの正式版ローンチに向けてアーカイブ・ノードを準備するためのものです。

コミュニティ・アーカイブ・ノードは常に利用可能で、来年初めには、パーミッションレス・ノード運用へのロードマップの一部として、誰でも実行できるアーカイブ・ノードのセルフ・ホスティング・バージョンが用意される予定です。今回のベータ版公開は、そのための足がかりとなるものです。

フィードバック❤️

私たちは、皆様からのフィードバックを大切にしています。アーカイブ・ノードの利用中に見つけた問題は、こちらで報告してください: https://github.com/onflow/flow-archive/issues

--

--

Ara
Flow Japan

ソフトウェアエンジニア。生物学、民俗学、仏教、神道、メディアアート、博物学、フォント、ブロックチェーンなどに興味あり。