Rand Protocol
ドキュメント
基本概念

トランザクションとアクション

ワイヤ上のトランザクション、その id、台帳が認識するすべての Action、チェーン 20 が受け付ける Action、そしてノードが送信内容を検査する順序について説明します。

このページは、トランザクションの構築・送信・デコードに使います。rand_sendTransaction が受け取るワイヤ形式、ID の計算方法、バンドルと手数料のルールを含むアクションの全一覧、そしてどのエラーが先に返るかを決めるアドミッション順序を扱います。

トランザクション

Transaction { chain_id: u64, bundle: Option<Bundle>, action: Action }

Bundle {                                        // the hidden-asset bundle (since chain 14)
  anchor: Word8, nullifiers: [Word8; 4], commitments: [Word8; 4],
  fee: u64, burn_a: u64, burn_r: u64, burn_asset: u32, time: u32,
  envelopes: [Envelope; 4], proof: Vec<u8>,     // postcard(Proof) of the hidden-asset guest
  auth_commit: Word8, auth_proof: Vec<u8>,      // since chain 17: split authorisation's c and its auth proof
}
Envelope { kem_ct: Vec<u8>, to_receiver: Vec<u8>, to_sender: Vec<u8>, body: Vec<u8> }

Word8 は 8 個のリトルエンディアン u32 ワードで、小文字 16 進 64 文字として表記されます。ワイヤ形式は bincode のデフォルト設定(固定幅整数、8 バイトの長さプレフィックス、u32 の enum タグ)による bincode(Transaction) で、rand_sendTransaction はこれを 16 進文字列として受け取ります。トランザクションへの署名も送信者フィールドもありません。バンドルは自身の証明(バンドル証明と、chain 17 以降はそれと並ぶ認可証明)によって自らを認可し、署名付きのアクションは署名をアクション自身の内部に持ちます。リプレイ保護は、バンドルについてはナリファイア集合、署名付きのステーキングアクションについてはレジスタ内のバリデータごとのナンスが担います。TokenMint と SetAuthority にはトークンごとの mint_nonce が、ブリッジのガバナンスアクションにはブリッジの pause_nonce と list_nonce が使われます。

トランザクションが持つバンドルは多くても 1 つで、バンドルを伴わないアクション以外のすべてのアクションは、ちょうど 1 つを持ちます。バンドルのスロット 0〜1 はプライベート資産を、スロット 2〜3 は RAND を扱うため、1 つの証明でトークンを移動し、その RAND 手数料も支払えます。以前の設計にあった 2 バンドルのブリッジバーンはなくなり、バーンは 1 つのバンドルで行います(ノート)。

rand ウォレットは、これらすべてを randprotocol_client::wallet::{send, submit} を通じて構築します。入力の選択、アンカーの取得、ウォレット自身が持つツリーのコピーからのウィットネスの計算、出力の構築と 4 つのエンベロープすべての封印、トランザクションのバインディングの取得、バンドル証明と認可証明の生成、バンドル証明が公開するダイジェストの検証、そして送信という順序です。

トランザクションバインディング

トランザクションには署名がなく、バンドルの証明が確定させるのはバンドル自身のダイジェスト(アンカー、ナリファイア、コミットメント、手数料、バーンのフィールド、time)だけです。chain 13 までは、証明済みのバンドルを、それと一緒に送られるアクションやそのエンベロープに結びつけるものが何もありませんでした。そのため、トランザクションを目にした誰もがすべての証明バイトを保ったまま、それ以外を書き換えることができました。BridgeBurn の宛先、Bond のバリデータ、エンベロープなどです。chain 14 以降、すべてのバンドル証明は、トランザクションのバインディングに対して生成され、検証されます。

binding(tx) = blake3("rand-tx-bind-1" || bincode(chain_id, bundle', action'))            chains 14 to 19
binding(tx) = blake3("rand-tx-bind-2" || bincode(genesis_hash, chain_id, bundle', action'))  chain 20
                                                                                  as 8 LE u32 words

ここで ' は、すべてのバンドル証明のバイト列を空ベクタに置き換えることを意味します。対象は bundle.proof、chain 17 以降は bundle.auth_proof、そして Aggregate の proof です。それ以外はすべて含まれます。auth_commit、4 つのエンベロープすべて、バーンのすべてのフィールド、宛先、バリデータ、受取人、署名、ガーディアンの証明とその Dilithium2 共同署名、そして Call 自身の証明です。8 つのワードは証明の公開入力セグメントに載せられ、そのダイジェスト H_PUB は回路がすでにバインドしているため、この修正にゲストプログラムや回路の変更は不要でした。ノードは Machine::verify_public(hc_bundle, binding, proof) を実行し、トランザクションバインディング以外の公開高を宣言するバンドル証明を拒否します(public height not the transaction binding's)。Transaction::binding は、ウォレットが証明前に、台帳が検証前に呼び出す唯一の関数です。chain 17 以降、認可証明も同じ 8 つのワードに対して生成・検証されるため、別のトランザクションに移し替えることもできません。

chain 20 はジェネシスハッシュをバインドします。 chain 19 までは、バインディングとバンドルを伴わないアクションの署名メッセージはチェーン ID だけを対象としていたため、チェーン ID を共有する 2 つのチェーン(再カット版や非公開コピー)は、互いの証明や署名を受け入れてしまいました。chain 20 のジェネシスは binding_domain: 1 を設定します(v0.6.8、監査 v6 BIND-1。crates/randprotocol-core/src/types/binding.rs)。すると、ジェネシスハッシュがすべてのプリイメージの先頭に置かれ、タグはバージョンが 1 つ上がります。2 つのバインディングは rand-tx-bind-2 と rand-call-bind-2、ファウセットのミントは rand-mint-3、Unbond と Withdraw は rand-unbond-2 と rand-withdraw-2、RPL のミントと権限のメッセージは rand-rpl-mint-2 と rand-rpl-authority-2 になり、アグリゲータのアクションとブリッジのガバナンスメッセージも同様です。このようなチェーンでのバリデータ登録は、常に v2 のメッセージ(ジェネシス、チェーン、アドレス、ペイアウト)です。あるチェーンのために証明または署名されたものは、チェーン ID が何であれ、別のチェーンでは検証されません。バインディングのワードは公開入力なので、ゲストプログラムも検証鍵も変わっていません。v0.6.8 より古いウォレットはいまもチェーン ID 形式に対して証明するため、chain 20 では拒否されます。rand_getLimits と rand_status は binding_domain を返します(chain 20 では 1、このフィールドがない場合は 0)。

ジェネシスの hardening_v6(chain 16〜20)の下では、Call 自身の証明も、同じ構成の 2 つ目のダイジェストによって、独自のドメインのもとでバインドされます。このとき、バンドルの証明だけでなく Call の証明も空にします。

call_binding(tx) = blake3("rand-call-bind-1" || bincode(chain_id, bundle', action''))   as 8 LE u32 words

chain 20 ではタグは rand-call-bind-2 で、上記のとおりジェネシスハッシュがプリイメージの先頭に置かれます。Invoke の証明も同じ方法でバインドされ、宣言された遷移がプリイメージに保たれるため、証明はトランザクションが運ぶ状態変更、ペイアウト、受取人そのものにコミットします。

Call の証明は、プログラムにデプロイ時の公開入力がある場合はその後ろに、これらのワードを公開入力セグメントに載せます。そのため、別の手数料バンドルに付け替えたコピーは検証を通りません。2 つのバインディングは入れ子になっています。ウォレットは手数料バンドルのノートを選び、証明を空にしたままトランザクションを構築し、Call のバインディングに対して Call を証明してその証明を差し込み、その後にはじめてトランザクションのバインディングを取得してバンドルを証明します。

クライアントにとっての帰結は次のとおりです。出力、エンベロープ、アクションを含むトランザクション全体を、証明する前に構築してください。フォーク前に作られたウォレットは空の公開セグメントに対して証明するため、拒否されます。バンドルを伴わないアクションにはバインドすべき証明がなく、自身の署名に基づきます。バインディングはトランザクション ID ではなく、トランザクション ID は変わりません。

トランザクション ID

txid = blake3("rand-txid-3" || bincode(view))

ここで view は、バンドルの proof バイトを blake3(proof)(proof_hash)に、auth_proof バイトを blake3(auth_proof)(auth_proof_hash。そのまま入る auth_commit の後ろに置かれます)に置き換え、それ以外のフィールドはそのままにしたトランザクションです。ドメインは chain 16 まで、2 つの認可フィールドを持たない rand-txid-2 でした。chain 17 で、すべてのトランザクション ID が変わりました。証明をダイジェストでハッシュすることで、プルーニングされたバンドル(ブロック集約。chain 20 では無効)も、生の形式と同じ ID を保てます。プルーニングされたバンドルは認可証明を保持します。バンドルを伴わないトランザクションは、そのバイト列をそのままハッシュします。同じ ID が、メモリプール、レシート、およびすべての RPC 検索のキーになります。

すべてのアクション

Action は bincode の enum で、タグは宣言順です。

tagactionfieldsbundlefee floor
0None—必須BUNDLE_BASE = 0.001 RAND
1Mintcm, pk, time, r, envelope, amount, minter: PublicKey, signature不可0(validator が署名。faucet チェーンのみ、amount ≤ 100 RAND)
2Deploybase_pc: u32, words: Vec<u32>, public: Vec<u32>必須base + プログラムのワードと公開ワード 1 つにつき 100,000 単位
3Callprogram, proof, input_envelope: Option<CallEnvelope>必須chain 20 では、base + gas_price × proof が宣言する GAS_LIMIT + proof と入力 envelope の 1 KiB ごとに byte_price。gas セクションのないチェーンでは base + call_fee(tier)
4Bondvalidator, amount, registration: Option<Registration>必須。かつ burn_r == amountbase
5Unbondvalidator, amount, nonce, signature不可0
6Withdrawvalidator, amount, nonce, time, r, envelope, signature不可ワイヤ上は 0。base は amount から差し引かれる
7BridgeAttestattestation, recipient: ShieldedAddress, r, time, asset, envelope, pq_signatures: Vec<PqSignature>必須base
8BridgeBurnasset, amount, relayer_fee, to_chain: u16, token: [u8; 32], to: [u8; 32]必須。burn_asset == asset かつ burn_a == amountBRIDGE_BURN_FEE = 0.01 RAND
9RegisterAggregatorregistration必須。burn_r = bondbase
10UnbondAggregatoraggregator, nonce, signature不可0
11WithdrawAggregatoraggregator, nonce, time, r, envelope, signature不可0
12SlashAggregator署名付きの aggregate header 2 つ不可0
13Aggregatecovers, proof, aggregator, nonce, time, r, envelope, signature不可0
14RegisterTokenname, symbol, decimals: u8, authority: MintAuthority, initial: Option<InitialMint>, salt: [u8; 32], index: u32必須base + レジストリの registration_fee(chain 20 では 1 RAND、burn される)
15TokenMintasset, amount, recipient: ShieldedAddress, r, time, envelope, nonce, signature必須base
16SetAuthorityasset, new: Option<PublicKey>, nonce, signature必須base
17TokenBurnasset, amount必須。burn_asset == asset かつ burn_a == amountbase
18PauseMintsnonce, signature不可0
19UnpauseMintsnonce, pq_signatures不可0
20RegisterBridgedTokenname, symbol, salt, chain: u16, token: [u8; 32], decimals: u8, nonce, pq_signatures必須base + registration_fee
21ListBackingtoken_index, chain: u16, token: [u8; 32], decimals: u8, nonce, pq_signatures必須base
22RotatePqGuardiansnew_pq_guardians: Vec<PublicKey>, nonce, pq_signatures不可0
23RotatePauseKeynew_pause_key: PublicKey, nonce, pq_signatures不可0
24ClaimVestedentry: [u8; 32], amount, nonce, to: ShieldedAddress, time, r, envelope, signature不可ワイヤ上は 0。base は amount から差し引かれる
25RevokeVestingentry: [u8; 32], unvested, nonce, to: ShieldedAddress, time, r, envelope, signatures(v0.6.8 以降は、エントリの revoker のしきい値数の署名で、そのエントリのジェネシスが指定する treasury に支払う。それ以前は signature 1 つ)不可ワイヤ上は 0。base は unvested から差し引かれる
26BondVestedentry: [u8; 32], validator, amount, registration: Option<Registration>, nonce, signature不可0
27UnbondVestedentry: [u8; 32], amount, nonce, signature不可0
28AdmitValidatorcandidate: PublicKey, signatures: Vec<(PublicKey, Signature)>不可0
29SlashEquivocationfirst, second: 1 人のリーダーが 1 つの view に対して署名した 2 つのブロックヘッダ不可0
30RotatePqGuardiansV2new_pq_guardians: Vec<PublicKey>, possession: Vec<Vec<u8>>, nonce, pq_signatures不可0
31RotatePauseKeyV2new_pause_key: PublicKey, possession: Vec<u8>, nonce, pq_signatures不可0
32CancelRotationkind: u8, nonce, signature不可0
33Invokeprogram, proof, input_envelope: Option<CallEnvelope>, transition: Transition必須。burn_r と、burn_asset の burn_a が、プログラムに入るものCall の floor + 作成されるセル 1 つにつき cell_fee
MintAuthority = None | Key(PublicKey) | Bridge { backings: Vec<Backing> } | Program(Hash)
InitialMint   { amount: u64, recipient: ShieldedAddress, r: Word8, time: u32, envelope: Envelope }
PqSignature   { index: u8, signature: Vec<u8> }   // one guardian's Dilithium2 co-signature, by set index

chain 20 では、tag 0〜8、14〜21、28、30〜33 が使えます。そのジェネシスには、rules_v2 を持つ bridge セクション、tokens セクション、staking.admission_by_vote(tag 28)、bridge.rotation(tag 30〜32)、program_state(tag 33)があります。tag 22 と 23 はここでは拒否されます。bridge.rotation.needs_possession のもとでは、ローテーションは新しい各鍵自身の署名を含む …V2 形式でなければならないためです。これらのセクションを一つも持たなかった chain 19 では、tag 0〜8 と 14〜23 が使えました(rules_v2 を持たない chain 14 は 22 と 23 を拒否しました)。SlashEquivocation には staking.slashing セクションが必要ですが、chain 20 のそれは null です。5 つのアグリゲーション用アクションには aggregation セクションが必要ですが、chain 20 にはありません(アグリゲーションが再計測されるまで、それを含むジェネシスではビルドが起動を拒否します)。ノードはこれらすべてを他のどの検査よりも前のゲートで拒否しますが、bincode の tag は引き続き占有されているため、tag 番号をハードコードするエンコーダはこれらも数えに入れる必要があります。アグリゲーションは Proofs で今後の機能として説明されています。4 つのジェネシス・ベスティング用アクション(tag 24〜27、v0.5.11 以降のビルドに含まれる)には vesting セクションが必要ですが、chain 20 を含め、どのチェーンにもそれはなく、このセクションなしでは受け付け時に拒否されます。tag 28〜33 は v0.6.8 で新たに追加され、末尾に付け足されているため、それ以前のどのチェーンの履歴も引き続きデコードできます。

4 つの RPL アクション(tag 14〜17)は、トークンの登録、Key 認可のトークンの追加 mint、mint 権限の引き渡しまたは放棄、保有分の burn を行います。Bridge または Program の権限を指定した RegisterToken は拒否されます。トークン転送のアクションはありません。トークンの転送は None であり、RAND の支払いと区別がつきません。RPL tokens を参照してください。4 つのブリッジガバナンス用アクション(tag 18〜21)は、mint の一時停止、その解除、そしてジェネシス後のブリッジトークンの上場または追加のバッキングの上場です。PauseMints はジェネシスの pause key で署名され、この鍵は一時停止しかできません。残る 3 つには Dilithium2(PQ)guardian の定足数が必要です。BridgeAttest も、ECDSA の定足数に加えて、同様の定足数を持ちます。bridge の rules_v2 のもとでの tag 22 と 23 は、PQ guardian のセットまたは pause key を置き換えるもので、いずれも現行セットの PQ 定足数と bridge の rotation_nonce のもとで行われます。tag 30 と 31 は bridge.rotation のもとで同じことを行い、さらに新しい各鍵自身の Dilithium2 署名(ローテーションメッセージに対するもので、その鍵が保持されていることの証明)を含みます。chain 20 では、ローテーションは保留として記録され、delay_secs(86,400 s)の後に有効になります。CancelRotation(tag 32)は現行の pause key で署名され、保留中のローテーションが有効になる前に取り消します。Bridge を参照してください。

AdmitValidator(tag 28)は、新しい鍵を受け入れるための validator セットによる投票です。ステークの 3 分の 2 を超える分を保有する validator の署名を、アドレスの昇順に並べたものです。staking.admission_by_vote(chain 20)のもとでは、新しい validator を登録する Bond は、そのアドレスがこの方法で承認されていない限り拒否されます(Staking)。Invoke(tag 33、RPL-2)は、proof がプログラムの宣言された 1 つの状態 transition を保証する call です。つまり、読み書きされるセル、バンドルの burn フィールドがプログラムの vault に持ち込むもの、そして vault が支払う、またはプログラムが mint する note です。台帳は、宣言された読み取りがすべて現在も成立し、2 つの proof が検証されれば、その transition を適用します(Programs)。

Deploy と Call は通常のシールド取引であり、そのバンドルはゼロの自己転送です。これは、floor を呼び出し元自身の note から支払うために存在するため、チェーンはそれが誰のものだったかを知ることがありません。RAND がプールを出るのは burn_r を通じてのみです。Bond のステーク、RegisterAggregator の bond、Invoke による program vault への預け入れがそれにあたります。トークンが出るのは、そのトークンを指定した burn_asset を伴う burn_a を通じてのみで、TokenBurn、BridgeBurn、Invoke で行われます。それ以外のアクションは何も burn せず、burn_asset = 0 で burn_a が 0 以外のバンドルは、どこでも拒否されます。

受け付けの順序

Ledger::validate_inner は、コストの低い検査をコストの高い検査より先に、次の順序で行います。mempool もゴシップの前に同じ検査を実行するため、不正な取引はエッジで 1 度だけ拒否されます。

  1. サイズ上限 — トランザクション全体は、チェーンの max_block_bytes 以下です。バンドルの 4 つのエンベロープのそれぞれ、およびアクションが持つノートのエンベロープは、ジェネシスの envelope_bytes とちょうど同じサイズでなければなりません(chain 20 では 1,860、このフィールドのないチェーンでは最大 2,048 バイト)。バンドル証明、認可証明、呼び出し証明はそれぞれ max_proof_bytes 以下です(デフォルトは 2 MiB、chain 20 のジェネシスでは 4 MiB、chain 13〜16 では 8 MiB でした)。プログラムはチェーンのプログラム上限以下です(デフォルトは 4,096 ワード、chain 20 のジェネシスでは 65,535)。呼び出しエンベロープは max_call_envelope_bytes 以下です(デフォルトは 18,432 バイト、chain 20 では 65,536)。アテステーションは 16 KiB 以下です。シール形式(プルーニング済みマーカー形式)のバンドル証明は、シール形式の同期以外ではここで拒否され(PrunedFormOutsideSync)、証明に関する処理は一切行われません。
  2. チェーン ID が一致していること。
  3. 形式と手数料の下限 — バンドルを持たないアクションはバンドルを含まず、それ以外のアクションはちょうど 1 つ含まなければなりません。check_burn_shape は、アクションが設定できる 3 つのバーンフィールドのうちどれかを定めます。TokenBurn または BridgeBurn は、burn_asset と burn_a を通じて自身の asset と amount をバーンします。Bond または RegisterAggregator は、burn_r を通じて自身の amount をバーンします。それ以外のアクションは何もバーンしません。そして fee ≥ fee_floor(action) でなければなりません。gas セクションを持つチェーン(chain 20)では、この段階での Call または Invoke の下限は、宣言上限を 1 としたときのガスの規則、すなわち証明と入力エンベロープに対する BUNDLE_BASE + gas_price + byte_price × ⌈bytes / 1024⌉ です。これらは検証の前に分かっています。
  4. アンカー — chain 20 では直近 1,024 個のブロック終端ルートのいずれかです(chain 20 のジェネシスは proof_window_blocks: 1024 を設定、v0.6.8)。このフィールドのないチェーンでは、chain 19 までと同様に直近 256 個のいずれかです。
  5. 時刻 — chain 20 では [height − 1024, height] の範囲内、このフィールドがない場合は [height − 256, height] の範囲内です。ジェネシスの 1 つの値が両方のウィンドウを決めます。
  6. ナリファイアとコミットメント — 4 つのナリファイアはすべて異なり、いずれも使用済みではありません。4 つのコミットメントもすべて異なり、いずれもすでにリーフになっていません。
  7. アクションの検査 — faucet が有効であること、ミントが上限未満でバリデータによる署名があること、chain 20 ではさらに、ジェネシスの staking.faucet_recipients 許可リストにある受取人を指定していること、エポックの faucet_budget_per_epoch に収まること、ジェネシスの staking.faucet_minters リストにあるバリデータが署名していること(chain 16 以降は有効性ルール)。2⁶³ 以上のミントまたはデポジットはすべてのチェーンで拒否されます。プログラムがデコードできること、プログラムが存在すること、ステーキングの規則(バリデータが未知の場合にのみ登録が存在すること、nonce、署名、十分なステーク)、BridgeAttest と BridgeBurn およびポーズとリスティングのアクションに対するブリッジ固有の規則、RPL の 4 つのアクションに対する RPL の規則(登録手数料を含む)。chain 20 では、承認投票の定足数、そして Invoke については、遷移の形式、保存されたセルに対して宣言された読み取り、すべての支払いに対するヴォルトの担保、セル手数料も検査されます。これらはすべてバンドルの証明より前に実行されるため、適用できないトランザクションは STARK 検証のコストを発生させません。hardening_v6(chain 16〜20)では、さらに 2 つの拒否がここに置かれます。どの呼び出しも保持できないプログラムの Deploy(ProgramUncallable)と、正直な証明者なら書かないフィールドをヘッダまたはトランスクリプトに持つバンドル証明または呼び出し証明(non-canonical proof: …)で、いずれもどちらの証明も検証される前に拒否されます。v0.6.8 以降は、最も高いテーブルの上限を超える次数をヘッダで宣言する証明は、同じ判定のもとで最初に拒否されます(audit v6 ZKV-4)。この検査が証明を走査する前に行われます。
  8. バンドルダイジェスト — 認可分離型のチェーン(chain 17 以降のすべてのチェーン)では、まず認可フィールドが検査されます。認可証明のないバンドルは拒否され、認可証明が公開する c(読み取るだけで、まだ検証されていません)は auth_commit と等しくなければならず、chain 20 では認可証明が宣言する GAS_LIMIT がちょうど 1,279 でなければなりません。その後、台帳は auth_commit を含むバンドルの公開フィールドのダイジェストを再計算し、それが証明の公開したものと等しくなければなりません。chain 20 では、バンドル証明が宣言する GAS_LIMIT も、ジェネシスの bundle_gas_limit(20,479)とちょうど等しくなければなりません。
  9. バンドル証明 — ジェネシスで固定された hc_bundle とトランザクションのバインディングに対する Machine::verify_public です。認可分離型のチェーンでは、次にジェネシスで固定された hc_auth と同じバインディングに対して認可証明が検証されます。
  10. 呼び出し証明とそのティア手数料 — Call または Invoke では、まず証明のヘッダが固定されます(ティアは最大 14、keccak テーブルは最大 2¹²、sha256 テーブルは最大 2¹³、デプロイされたプログラムの高さ(hardening_v6 では下限 2⁷ 行)、chain 20 ではヘッダの上限 gas_max を超えない宣言済みの GAS_LIMIT)。続いて、プログラムの code_hash に対して、また hardening_v6 ではトランザクションの呼び出しバインディングに対して、呼び出しの STARK が検証されます。手数料は最後に検査されます。証明がデコードされて初めて分かるためです。chain 20 では、適用中の価格で fee ≥ BUNDLE_BASE + gas_price × GAS_LIMIT + byte_price × ⌈bytes / 1024⌉ であり、Invoke では作成されるセルごとに cell_fee が加わります(手数料)。gas セクションのないチェーンでは fee ≥ BUNDLE_BASE + call_fee(tier) です。

エラーは、コード -32000 と理由を付けて rand_sendTransaction から返されます。nullifier already spent、anchor is not one of the last 1024 roots(proof_window_blocks のないチェーンでは 256)、time 12 is outside [476, 1500]、fee 1000000 below minimum 2000000、the bundle's digest is not what its proof published、invalid bundle proof: …、unknown program …、already in mempool、conflicts with a pending transaction over <nullifier>、faucet is disabled on this chain、chain 14 以降の the bundle burns asset 2 on an action that burns no token、a burn of 5 is not allowed on this action、the bundle burns 399, not the 400 the action declares、wrong mint nonce: expected 1, got 0、wrong token index: expected 3, got 2、chain 17 以降の this chain requires an auth proof on every bundle (genesis hc_auth) と the auth proof publishes a different commitment than the bundle's auth_commit、そして chain 20 の envelope is 1348 bytes, this chain requires exactly 1860 と bundle proof declares gas limit …, this chain requires exactly 20479 です。受理はコミットではありません。rand_getTransaction がブロックを返すまでポーリングしてください。

無効なトランザクションを 1 つでも含むブロックは無効です。mempool は保留中のすべてのナリファイアとコミットメントをインデックス化し、競合を即座に拒否するため、同じノートを使う 2 つのバンドルが同じブロックに入ることはありません。

サイズ

部位バイト数
Word832
Envelope 1 つエンコード後 1,892(暗号文 1,860)(chain 18 以降)、1,380(1,348)(chain 17 まで)
2 つの証明を除く Bundle7,936(ナリファイア 4 つ、コミットメント 4 つ、エンベロープ 4 つ、auth_commit)
2 つの証明を除く転送トランザクション7,949
2 つの証明を除くデプロイトランザクション(100 ワードのプログラム、公開入力なし)8,369
3 つの証明を除く呼び出しトランザクション(入力エンベロープなし)7,990
ミントトランザクション(バンドルなし)5,761(1,312 バイトの Dilithium2 鍵と 2,420 バイトの署名)
バンドル証明、ティア 14、本番プロファイルchain 18 で読み取った 1,497,544 と 1,504,260(高さ 97,821 のデプロイと 98,335 の呼び出し、2026-09-30)、chain 14 で計測した 1,422,116 と 1,423,170(zUSD の登録とバッキングのリスティング、2026-09-20)
認可証明、ティア 10、本番プロファイル同じ chain 18 の 2 つのトランザクションで 1,370,827 と 1,367,303

最初の 6 行は chain 18 以降のエンコーディングです。メモフィールドによってすべてのエンベロープが 512 バイト増え、認可分離によって認可証明自体のバイトの前にバンドルが 40 バイト増えました。したがって、ワイヤ上のシールド転送は chain 18 以降(chain 20 を含む)で約 2.88 MB であり、どのアセットを移動する場合でも、そのほぼすべてが証明です。内訳は、バンドル証明が約 1.5 MB、認可証明が約 1.37 MB です。chain 15 までは証明が 1 つで、約 1.43 MB でした。ブロックは 2,000 トランザクション(MAX_BLOCK_TXS)と、チェーンの max_block_bytes 分のトランザクションバイトに上限があり、どちらもコンセンサスルールです。デフォルトは 4 MiB(MAX_BLOCK_BYTES)で、このような転送を1 つしか収容できません。chain 20 のジェネシスでは 20 MiB で、7 つ収容できます。hc_auth を持つジェネシスは、max_block_bytes を max_proof_bytes の 3 倍に 1 MiB を加えた値以上に設定しなければなりません。1 つのトランザクションが 3 つの証明(バンドル、認可、呼び出し)を持ち得るためで、そのため 4 MiB のデフォルトはそこでは拒否されます。ブロックレベルの集約が予定されている対策です。証明を参照してください。

読み戻す

rand_getTransaction(hash) は、トランザクションがコミットされるまで null を返し、コミット後はそのブロック位置と公開フィールドのみを返します。

{
  "height": 192, "index": 0, "block_hash": "63f6…08",
  "tx": {
    "hash": "4f2c…e7", "chain_id": 20,
    "bundle": {
      "anchor": "6b1d…c4",
      "nullifiers": ["8c04…d1", "5e77…20", "03aa…6f", "e19b…42"],
      "commitments": ["2a9f…07", "b310…88", "77c1…0e", "5d20…b3"],
      "fee": "1000000", "burn_a": "0", "burn_r": "0", "burn_asset": 0, "time": 5,
      "proof_len": 1497544, "envelope_len": [1860, 1860, 1860, 1860],
      "auth_commit": "0bab…e8a1", "auth_proof_bytes": 1370827
    },
    "action": { "kind": "none" }
  }
}

転送(transfer)には from、to、nonce、金額、asset のいずれのフィールドもなく、保存されたブロックにもありません。ノードには、これ以上秘匿すべき情報がないということです。auth_commit と auth_proof_bytes(認証証明の長さ)は chain 17 から含まれています。バンドルには常にダミーを含めて 4 つのスロットがあり、RAND の転送も任意の RPL トークンの転送も、どちらも "kind": "none" です。chain 14 以降、すべての u64 の金額は 10 進数の文字列です(fee、burn_a、burn_r、アクションの amount)。インデックス、nonce、高さ、長さは JSON の数値のままです。その他のアクション種別は公開フィールドを表示します。対象は mint、deploy、call、bond、unbond、withdraw、bridge_attest、bridge_burn、register_token、token_mint、set_authority、token_burn、pause_mints、unpause_mints、register_bridged_token、list_backing、rotate_pq_guardians、rotate_pause_key、ベスティングの 4 種類 claim_vested、revoke_vesting、bond_vested、unbond_vested、そして v0.6.8 以降の admit_validator、slash_equivocation、rotate_pq_guardians_v2、rotate_pause_key_v2、cancel_rotation、invoke で、JSON-RPC リファレンスに一覧があります。

fullnode のコミット c0878c3f(チェーン 21)に対して 2026-10-12 に最終確認しました。 コードとこのページが食い違う場合は、コードが正です。お知らせください。