- Message → ユーザーがやりたかったこと(署名済みの提案)
- Meta → 実際に起きたこと(実行結果)
<Buffer 00 bf a0 e8...>のような形式)で提供されます。
このガイドは、そのバイナリデータを人間が読みやすい形式にデコードし、意味のある情報を抽出し、提案から実行までの完全なトランザクションストーリーを理解する方法を示します。
ライブストリーム、デコードなし
以下の最小クライアントを実行します。フィルターフラグは投票および失敗したトランザクションをドロップし、accountInclude配列はJupiterプログラムIDに触れる活動の結果を制限します。
filters, createdAt)と、2つの子を隠すtransactionブランチが表示されます。
transaction.transaction.transaction→ 署名済みのメッセージtransaction.transaction.meta→ 実行メタ
Uint8Arrayのように見えるものは、その時点では不透明なままです。
デコード関数を使ってスクリプトを実行すると、読みやすいアドレスを持つ実際のネスト構造が見られます。
バイナリデータのデコード
デコードの理由: 生のLaserstreamデータには、署名、アカウントキー、ハッシュがバイナリUint8Arrayオブジェクトとして含まれており、読み取りができません。これらをbase58文字列に変換する必要があります。
解決策: Laserstreamは、Yellowstone gRPCを使用しており、組み込みのデコードユーティリティを提供しています。各フィールドタイプのデコーダーを書く代わりに、再帰関数を使ってすべてのバイナリデータを人間が読みやすい形式に変換します。
トランザクション構造の理解
デコードされたデータが見えるようになったので、Laserstreamトランザクションアップデートの主な2つの部分を探ります。最初の例から、各トランザクションには2つのキーオブジェクトが含まれていることを思い出してください。- Message (Proposal) →
transaction.transaction.transaction→ 署名されたメッセージ(ユーザーの提案) - Meta (Execution) →
transaction.transaction.meta→ 実行メタデータ(バリデーターの応答)
提案: メッセージ内部のすべて
ユーザーは何を、誰が、そしていつまでを指定するメッセージを作成します。以下に各部分をデコードする方法を示します。トランザクションヘッダー
numRequiredSignaturesは、バリデーターにどれだけの署名を確認するかを伝え、2つのnumReadonly*の値は、ランタイムが読み取り専用として扱えるアカウントをラベル付けし、並列実行を可能にします。
アカウントキー辞書
accountKeysは公開鍵の単純なリストで、検索テーブルとして機能します。トランザクション内の後の整数(programIdIndexや命令のaccounts配列内の各要素)がこのリストにインデックスを使用して戻ります。これによりメッセージあたり1キロバイト以上を節約できます。
リプレイ防止
recentBlockhashは、最後の150のブロックハッシュをスクロールすると期限切れになります。メインネットで約90秒です。
命令: 実際のコマンド
- Program ID (
programIdIndex):accountKeys配列内のアドレスにポイントします(例: インデックス10 =ComputeBudget111111111111111111111111111111) - Accounts (
accounts): この命令がどのアカウントインデックスに触れるのかを表すbase58エンコードされた文字列 - Data (
data): base58でエンコードされた実際の命令データ
convertBuffers関数により、アカウントはbase58として表示されますが、実際にはアカウントインデックスを含んでいます(例: "3vtmrQMafzDoG2CBz1iqgXPTnC"はインデックス[21, 19, 12, 17, 2, 6, 1, 22]にデコードされます)
この設計により、フルの32バイトのアドレスを繰り返す代わりに、各命令はルックアップテーブル内の位置を参照するだけで済みます。
署名: 認証の証明
signaturesには必要なアカウントがこのトランザクションを承認したことを証明する暗号署名が含まれています。署名の数はheader.numRequiredSignaturesと一致する必要があります。
アドレスタブルックアップ
versionedがtrueの場合、addressTableLookupsはオンチェーンテーブルと2つのインデックスリストと共に表示されます。ルックアップテーブルにより、パケットを1,232バイトのMTU以下に保ちながら、アドレスカウントのハードキャップを数十に引き上げます。
トランザクション v1: ヘッダー内の計算予算
トランザクション v1 (SIMD-0385, Agave 4.2) はメッセージにもう一つのフィールドを追加します:transactionConfig。
instructions 配列には ComputeBudget111111111111111111111111111111 エントリが含まれることはありません。priorityFee はトランザクション全体の手数料を lamports で表し、計算単位当たりのマイクロ-lamports ではありません。null フィールドは、送信者が設定していないことを意味します。レガシーおよび v0 メッセージには transactionConfig がないため、その存在が v1 トランザクションを識別します。
デコーダーで確認すべき2つのこと:
- 優先手数料の抽出。
transactionConfig.priorityFeeが存在する場合に読み取ります。レガシーおよび v0 トランザクションの場合のみ ComputeBudget 命令をスキャンします。命令のみをスキャンするコードは、すべての v1 トランザクションを優先手数料ゼロとして読み取ります。 - プロトバージョン。
yellowstone-grpc-proto12.6.0 は v1 フィールドを含む最初のリリースであり、helius-laserstream0.8.4 (JavaScript)、0.6.3 (Rust)、0.2.0 (Go) はそれを基に構築された最初の SDK リリースです。古いバージョンではtransactionConfigを静かに破棄します。
すべての接続: フロー
基本原理から見た流れは次のとおりです:- ルックアップテーブルを構築する:
accountKeysはこのトランザクションが触れるすべてのアドレスを列挙します - ルールを設定する:
headerは必要な署名の数と読み取り専用のアカウントを指定します - コマンドを作成する: 各
instructionは以下を指します:- プログラム(
programIdIndex→accountKeys[index]経由) - 必要なアカウント(
accounts→ 複数のaccountKeys[index]位置を通して) - 命令データ(
dataにエンコード)
- プログラム(
- 承認を追加する:
signaturesは必要なアカウントがこのトランザクションを承認したことを証明します - 有効期限を設定する:
recentBlockhashはこのトランザクションが後で再実行されないようにします
実行: meta 内のすべて
メッセージはユーザーが実行したかったことを示し、meta はバリデーターがトランザクションを実行したときに実際に起こったことを示します。基本的な実行情報
成功/失敗err: null= 成功err: {...}= エラーディテール付きの失敗fee= このトランザクションで課金された lamports
accountKeys 配列に対応します:
- アカウント 0: 15000 lamports 減少(手数料支払い)
- アカウント 1: 1461600 lamports 増加(新しいアカウント作成)
- アカウント 3: 2001231920 lamports 増加(プログラムアカウント)
高度な実行詳細
内部命令実用的なデコードパターン
デコードされたトランザクションから有用な情報を抽出するための一般的なパターンは次のとおりです:完全な例: Jupiter スワップデコーダー
Jupiter スワップトランザクションをデコードし、意味のある情報を抽出する完全な例は次のとおりです:主なポイント
- 二部構成: すべてのトランザクションは、メッセージ(要求された内容)と meta(実際に起こった内容)を持ちます。
- バイナリデコード: バイナリフィールドを読みやすい base58 文字列に変換するために
bs58.encode()を使用します。 - アカウントキーのルックアップ: 命令は
accountKeys配列のインデックスでアカウントを参照します。 - 残高追跡:
preBalancesとpostBalancesを比較して何が変わったかを確認します。 - トランザクション v1:
transactionConfigが存在する場合に計算予算と優先手数料を読み込みます。v1 トランザクションには ComputeBudget 命令はありません。