Rand Protocol
文檔
指南

證明

錢包如何生成 bundle 證明、其時間與位元組成本、節點如何驗證、何謂約束集及為何更改約束集屬硬分叉,以及區塊聚合(即證明如何進入區塊的即將推出的改動)。

使用本頁以估算證明機器的規格,了解為何一次轉帳需時逾一分鐘,以及為何吞吐量的上限在於區塊空間而非運算,並知悉當證明系統變更時有哪些部分會失效。驗證者(validator)所接納的一切,均有其自行驗證過的證明作為支持。

證明陳述什麼

對鏈上運行的每個程式,只有一個關係:

此 RV32IM 程式自 base_pc 起動,在由 H_IN 承諾的私有輸入向量與由 H_PUB 承諾的公開輸入段上運行,於 2ᵗ − 1 個週期內停機,耗用的 gas 不超過 GAS_LIMIT,並公布了這八個輸出字。

程式由其電路內摘要 hc 識別;驗證者從不看到任何指令字。一次屏蔽轉帳,就是將該關係套用於隱藏資產捆綁 guest,這是一個手工組譯的 4 入 4 出程式,其 hc 在創世檔案中固定為 hc_bundle。Chain 20 固定使用 guest v3(guests::bundle_hidden_v3,60af094a…6e3fce,自 chain 17 起)。Chain 14 與 15 固定使用 v1(83d3a370…cd0ef8),chain 16 則固定使用無分支的 v2(651043e2…839b)。自 chain 17 起,每個捆綁還附帶第二個證明,即授權 guest(guests::auth,創世 hc_auth,1e4e347f…5639c1)的證明:捆綁證明取用查看密鑰,而授權證明則顯示發送者持有其背後的花費密鑰。這就是分拆授權,也讓只持有查看密鑰的配對證明者(prover)得以製作捆綁證明。隱藏資產 guest 取代了 chain 13 及之前所用的 2 入 2 出 bundle guest;後者在 fullnode 中僅為測試而保留,沒有任何鏈固定使用它。機密呼叫則是將同一關係套用於已部署的程式(Programs)。

錢包如何證明一個捆綁

rand send <rand1…> <amount> 在本機完成私密工作,只有證明、承諾、作廢符(nullifier)與密封信封會送達鏈上:

  1. 掃描樹並以查看密鑰挑選輸入:最多兩張涵蓋金額加手續費的 RAND 票據(note),置於槽位 2–3;如屬代幣轉帳或銷毀,則最多兩張該代幣的票據置於槽位 0–1,而 RAND 票據只負責涵蓋手續費。未使用的輸入槽位為虛設(dummy):金額為 0,由錢包持有,其成員資格失敗在電路內被遮蔽,作廢符仍會公布。自 guest v2 起,guest 為無分支:虛設票據的路徑與真實票據一樣,逐一經過全部 32 層雜湊。
  2. 取得頭部錨點(rand_getAnchor)及每張真實輸入的 32 層 Merkle 見證(rand_getWitness(index)),並對照錨點檢查所返回的根。
  3. 建構四個輸出:在轉移價值的那一組中,包含收款人的票據與找零票據(即使為零亦然),其餘則為零金額的虛設票據,密封至一個即棄密鑰。
  4. 密封每個輸出於信封中(以 ML-KEM-768 密封予收款人,另加以錢包的 ovk 包裹的交易密鑰),連同其動作組裝整筆交易,並取得其綁定(binding):blake3("rand-tx-bind-1" || …),對象為將證明清空後的交易,共八個字(Transactions)。在創世設定 binding_domain: 1 的 chain 20 上,則為 blake3("rand-tx-bind-2" || …),先帶創世雜湊,再帶鏈 id,因此為某一條鏈製作的證明在其他任何鏈上都無法通過驗證,即使該鏈的鏈 id 相同亦然。早於 v0.6.8 的錢包採用舊綁定,chain 20 會拒絕其證明。
  5. 授權:抽取一個全新的 256 位元鹽值(salt),並對授權 guest 的 16 字私有輸入(花費密鑰與鹽值)進行證明,以綁定作為公開輸入段,於 tier 10 進行。它由花費密鑰推導出 nk,並公布 c = H(AUTH, nk ‖ salt),捆綁將其作為 auth_commit 攜帶。
  6. 證明捆綁 guest 的 1,212 字私有輸入(查看密鑰 nk、附帶路徑的四個輸入槽位、錨點、四個輸出、fee、burn_a、burn_r、私有資產 A、time、鹽值),以同一綁定作為公開輸入段,於 tier 14 進行。該證明顯示擁有權、成員資格、每個真實輸入均帶有其槽位的資產、四個作廢符、同一個 c,以及兩項平衡:in₀ + in₁ = out₀ + out₁ + burn_a 與 in₂ + in₃ = out₂ + out₃ + fee + burn_r。這是配對證明者可代錢包製作的證明;授權證明則在錢包自己的機器上製作。
  7. 核對證明所公布的摘要與由明文計算所得者是否一致,然後提交 Transaction { chain_id, bundle, action: None }。

自 chain 14 起,次序至關重要:信封與動作先於證明存在,因為證明承諾於它們。就呼叫而言,呼叫證明最先製作,並同樣置於綁定之內。在 hardening_v6 鏈上,呼叫證明本身是針對呼叫綁定而製作的,該綁定為兩個證明均被清空後的交易(chain 16 至 19 為 rand-call-bind-1,chain 20 為帶創世雜湊的 rand-call-bind-2),涵蓋費用捆綁的作廢符,因此不能被複製到另一個捆綁之下。

proving bundle (tier 14; about a minute on a laptop)…
proved in 98.3s: tier 14, 1423170 bytes
submitted transfer 4f2c…  1.5 RAND out, 98.499 RAND change, fee 0.001 RAND, anchored at height 192

此記錄是 chain 14 時 fullnode 指南中錢包的輸出格式;所示位元組數為 chain 14 上提交的生產配置捆綁證明之位元組數。自 chain 17 起的錢包(包括 chain 20 上的 v0.6.8)會在這些行之前多印出兩行:proving the spend authorisation on this machine (tier 10; seconds)… 與 authorisation proved in …: tier 10, … bytes,並將捆綁一行改寫為 proving the bundle (tier 14; about a minute and a half on a laptop)…。

同一機制為每項動作付費,且一律只帶一個捆綁:部署、呼叫、代幣註冊或代幣鑄造,均附於一筆 RAND 的零值自我轉帳之上;質押(bond)附於一個透過 burn_r 銷毀質押額的捆綁之上;代幣銷毀或橋接銷毀則附於一個從槽位 0–1 銷毀資產(burn_a、burn_asset)並由槽位 2–3 支付 RAND 手續費的捆綁之上。轉帳所移動的資產是一個見證字,不在任何公開欄位之中。

成本

在開發用筆記型電腦(Apple Silicon,release 構建)上量度,以下為 fullnode 自身文件所記錄的數字:

guest字數週期tier證明證明大小(生產配置,80 次查詢)
bundle guest v3(chain 17 至 20)—4,024 個週期,以及 tier-14 預算中尚餘 273 次 Poseidon2 置換的餘裕14≈ 100 秒,峰值 5.7 GB;chain 18 上量度為 102.5 至 134.0 秒(2026-09-30)≈ 1.50 MB;chain 18 上量度為 1,494,151 至 1,504,260 位元組(2026-09-30)
auth guest(chain 17 至 20)—25010≈ 7 秒;chain 18 上量度為 6.6 至 19.9 秒(2026-09-30)≈ 1.37 MB;chain 18 上量度為 1,364,940 至 1,375,371 位元組(2026-09-30)
隱藏資產 bundle v1,4 入 4 出(chain 14 與 15)—低於 tier-14 預算,尚餘約 2,071 個週期(13%)14≈ 98–100 秒,峰值 5.7 GB≈ 1.43 MB;chain 14 上量度為 1,422,116 與 1,423,170 位元組
bundle,2 入 2 出(已淘汰;chain 13 及之前)3,811≈ 9,16014≈ 100 秒(單獨運行 94.6–97.9 秒;兩個同時運行則各 114 秒)chain 8 上量度為 1,321,773 位元組
private_payment(一次呼叫)少量< 1,00010≈ 7 秒≈ 1.37 MB(tier 10 的 fib:約束集 7 下為 1,367,688 位元組;約束集 6 下為 1,298,729 位元組)
無雜湊表的呼叫(off-chain ledger,chain 18)773—14114.8 秒1,498,589 位元組
帶 SHA-256 表的呼叫(proof of liabilities,chain 18)994—14122.9 秒1,911,152 位元組
帶 Keccak 表的呼叫(anonymous vote,chain 18)——1229.2 秒3,346,865 位元組

驗證是共識成本,由每個節點承擔:驗證者密鑰已預熱時約 16 毫秒,為某一形狀首次建立密鑰時約 230 毫秒。驗證者密鑰不取決於程式內容,而是以 (tier, program_log_height, input_log_height, keccak_log_height, sha256_log_height, public_log_height) 為索引,因此節點為每種形狀建立一份並重複使用;對於已部署的程式,密鑰會在部署時於背景計算一次(筆記型電腦上約 2 秒,2 vCPU 伺服器上 7 秒)。chain 13 及之前的 2 入 2 出捆綁所宣告的形狀為 program 12, input 10, keccak 0, sha256 0, public 2, mem 16;chain-14 的捆綁證明宣告 public 4,即八個綁定字的高度,不帶任何雜湊表,若宣告了其他 tier、任一雜湊表或其他公開高度,則會在建立任何驗證者密鑰之前被拒絕。自約束集 7 起,每個已宣告的表至少有 2⁷ 行,因此 chain-20 的捆綁證明宣告 public 7。

因此,chain 20 上的一筆轉賬約帶有 2.87 MB 的證明,即 bundle 證明與 auth 證明;一次調用則另加第三份證明。每份證明都必須符合創世的 max_proof_bytes,即 chain 20 上的 4,194,304(4 MiB),與 chain 17 至 19 相同,較 chain 13 至 16 的 8 MiB 為低。

隱藏資產 guest 之所以能夠放進 tier 14,只因為它以迴圈讀取私有輸入,並把 Merkle 檢查中的兄弟節點讀取合併處理;若以較早期的展開式寫法,同一關係會落在 tier 16,約需 400 秒及 21–22 GB,這會把 16 GB 的錢包排除在外。

證明受 CPU 限制,而錢包目前在所有平台上均使用 CPU 後端。在大型 tier 的運行中,證明者只用單線程:一部 16 vCPU 的 droplet 僅佔滿一個核心的 99%,而決定證明能否完成的是記憶體而非核心數(證明記憶體)。send、bond、call、deploy、bridge-mint 及 bridge-burn 上的 --cuda 標誌會選用 NVIDIA 後端,這需要以 --features cuda 構建。其內核於 2026-09-28 首次在真實硬件 NVIDIA H100 上運行,結果與 CPU 參考實現一致;但發行版所引用的 circuits checkout 中並未提交 PTX,因此在內核編譯完成之前,構建會以 no PTX for the GPU kernels 失敗。目前尚未在任何機群 GPU 節點上量度過生產環境的證明。系統刻意不設回退至 CPU 的機制。CUDA 調用亦無法封存輸入信封,因為鹽值不會離開證明者。tier 14 隱藏資產 bundle 證明的峰值記憶體約為 5.7 GB(Production FRI,CPU);較大的記憶體級別則涉及下文的解譯器及遞迴證明(≥ 64 GB 及以上)。

節點如何驗證

准入先進行低成本檢查(Transactions),然後:

  • 根據已公開的明文(anchor、四個 nullifier、四個承諾、fee、burn_a、burn_r、burn_asset、time、該 bundle 的 auth_commit,以及固定為零的 taint 字)重新計算 bundle digest,並要求其等於證明所公開的值——若證明的 witness 破壞了該關係,所公開的 digest 即帶有污染,與任何明文都不吻合。另有一些檢查屬結構性的(guest 自行提供輸出的發送者、資產及時間,故證明者無從選擇),而私有資產並不在 digest 之內;
  • 解碼證明,並按 tier 檢查其聲明的高度(check_declared_heights),使鏈對證明形狀的約束由驗證者負責。在檢查任何簽名或證明之前,每筆提交或經 gossip 傳入的交易都會先經過規範證明篩查(在 hardening_v6 下,區塊驗證亦然);自 fullnode v0.6.8(audit v6,ZKV-4)起,該篩查首先把每個聲明的 degree 限制在 25 位(MAX_HONEST_DEGREE_BITS,即記憶體表上限加一),因此帶有巨大 degree 的標頭,不會再在節點為其重新推導誠實折疊排程時拖住節點,而篩查內部的 panic 只會拒絕該筆交易,不會令節點停止運行;
  • 計算交易的綁定,並運行 Machine::verify_public(hc_bundle, &binding, proof)——即批量驗證器,加上檢查 H_PUB 是這八個字的 digest,因此把證明複製到帶有另一項操作、另一個信封或另一個 chain id 的交易上,或在 chain 20 上複製到另一條鏈的創世之上,均無法通過驗證(直至 chain 13,該段為空,沒有任何東西把證明綁定到其交易);
  • 對照 hc_auth 及同一綁定驗證 auth 證明,並要求其公開的 c 等於 auth_commit。沒有 auth 證明的 bundle 會被拒絕(AuthMissing),c 不一致者亦然(AuthMismatch);
  • 要求 bundle 證明的 GAS_LIMIT 等於創世的 bundle_gas_limit,即 20,479,而 auth 證明的則須等於 1,279,兩者均為兩個 guest 的標頭上限(BundleGasLimit、AuthGasLimit);
  • 若為調用,則針對程序已存儲的 code_hash 作同樣的檢查,並以程序的公開字後接調用綁定作為該段(RPL-2 的 Invoke 會把其狀態轉換附加為上下文字,Programs),然後按證明所聲明的 gas 上限及其位元組數檢查費用(Fees)。

經 RPC 或 gossip 提交的交易,會在四個 worker 之一上驗證,其前設有 64 深的隊列,並在共識迴圈之外運行,驗證通過後才會繼續 gossip 轉發;每個對等節點設有令牌桶(突發 16,每秒補充 4)以限制其可令節點驗證的數量,另有 8,192 個條目的緩存,可免費應對對已被永久拒絕的交易的重複提交。已提議區塊內證明的驗證,仍會在區塊被應用時於共識迴圈上運行。同步中的節點會在接受每個區塊之前,重新驗證其每份證書及每份證明;沒有任何東西會僅因法定人數已簽署而被信任。

Tier

tier週期預算(2ᵗ − 1)cpu 行數用於
101,0232¹⁰auth guest;private_payment、fib
124,0952¹²
1416,3832¹⁴隱藏資產 bundle guest(及已退役的 bundle guest);最大的調用
1665,5352¹⁶測試套件中的 EVM 調用證明;經翻譯的 ERC-20 approve(於 chain 13 上調用)
18262,1432¹⁸ERC-20 transfer 及 transferFrom,不論經翻譯或解譯
201,048,5752²⁰SPL Token,不論經翻譯或在 sBPF 解譯器 guest 上

自 fullnode v0.5.6(2026-09-25)起,高於 tier 14 的調用證明會在建立驗證器密鑰之前被拒絕(CallTierTooHigh),載有此類證明的區塊即屬無效;一次調用亦最多只可帶有 128 次 Keccak-f 置換及 128 次 SHA-256 壓縮。tier 16 至 20 仍可證明,但僅限鏈下:以上各行均無法在 chain 20 上調用,而 chain 20 會拒絕部署對任何 tier-14 調用而言過大的程序,即在沒有公開輸入的情況下超過 8,180 個字(ProgramUncallable)(預算)。

證明者會選取其預算足以涵蓋週期數,加上程序及輸入 digest 行數的最小 tier;不適配的運行會在證明之前失敗。只有 tier 是公開的。每上升一級,證明時間約增至四倍,證明大小則略為增加。在 chain 20 上,調用的費用取決於其證明所聲明的 gas 上限及其位元組大小,而非 tier(Fees)。

約束集與硬分叉

約束集是驗證器所檢查的表、列、匯流排、公開值及 FRI 參數的確切集合。在某一集合下生成的證明,在另一集合下無法通過驗證,雙向皆然;而節點啟動時的重放會重新驗證其鏈上的每份證明——因此以不同集合構建的節點,會在第一份證明處失敗並被截斷。這就是為何對該集合的每項更改,都會以新的 chain id 發佈,且所有節點須使用同一構建;亦是為何 rand_status 會報告 hc_bundle 及 hc_auth,而構建與創世不一致的節點會拒絕啟動。

集合日期更改內容
22026-09-10首次審查後的五項安全性修復
32026-09-11Poseidon2 chip、電路內的 hc、作為 witness 的程序表、子字記憶體、RV32M、FRI 重新調校為 27 次查詢
42026-09-11帶鹽的輸入承諾 H_IN 及其專屬表;平面二進位加載器
52026-09-12可選的 keccak 表;由證明聲明的記憶體高度;zk 審計中的兩項嚴重修復;FRI 回復為 80 次查詢;MAX_PROOF_BYTES 調整為 2 MiB
62026-09-14強制的 public 表及 H_PUB;可選的 sha256 表;以庫形式提供的 EVM 及 sBPF 解譯器 guest;34 個公開值。chain 12 至 15 所運行的集合。
72026-09-28每個 LogUp 終端均經 BLIND 匯流排致盲;每個已聲明的表下限為 2⁷ 行;對輸入、公開及鹽值字作 32 位範圍檢查;POSEIDON2_LEN 系統調用(7);JALR 清除其目標的第 0 位,並要求 funct3 = 0;驗證器密鑰由 key_derivation_v2 加鹽。chain 16 及 17 所運行的集合。
82026-09-29gas 計量:cpu 表中的 GAS 列及公開值 GAS_LIMIT;35 個公開值。chain 18 至 20 所運行的集合。

chain 14 及 15 沒有更改任何約束。chain 15 的節點以字面表持有 Poseidon2 的 86 個輪常數,取代以種子抽取的方式(audit ZKV-2)——數值相同,因此沒有任何哈希、digest 或證明發生變動。chain 14:隱藏資產 bundle 是新的 guest(即新的 hc_bundle),而交易綁定使用集合 6 已在電路內綁定的公開段。它仍然屬於硬分叉——bundle 的線路格式、已固定的 guest 及每個交易 id 均已改變,載有 bundle 的 chain-13 交易會被新構建拒絕,而在分叉前構建的錢包所生成的空段證明,亦會被鏈拒絕。

第 16 條鏈、第 17 條鏈和第 18 條鏈各自改變了證明的內涵。第 16 條鏈(fullnode v0.6.1,2026-09-28)轉用約束集 7,固定採用無分支捆綁包客體程式 v2 並設定 hardening_v6,原因是 2026-09-27 的審查發現過短的表和未加盲化的 LogUp 終端值會洩漏私密資料(zkVM 如何運作)。所有驗證密鑰均已更換。第 17 條鏈(v0.6.3,2026-09-29)沿用約束集 7,並加入拆分授權:捆綁包客體程式 v3、授權客體程式、捆綁包線上格式的兩個新欄位,以及交易 id 域 rand-txid-3。第 18 條鏈(v0.6.7-rc1,2026-09-29)為 Gas 計量改用約束集 8,實測證明大小增幅不足 1%。第 19 條鏈(2026-10-01)是第 18 條鏈在同一 v0.6.7 版本上的重新創世,證明方面沒有任何改動。第 20 條鏈(fullnode v0.6.8,2026-10-01)沿用約束集 8 以及相同的客體程式和驗證密鑰,改動的是證明所綁定的對象:交易綁定和調用綁定帶有創世雜湊(binding_domain: 1),這是由錢包和帳本計算的公開輸入,因此沒有任何電路變動。儘管如此,它仍是一次硬分叉,因為 v0.6.7 錢包的證明在該鏈上無法通過驗證。每個版本都會按創世雜湊拒絕此前的各條鏈。

代碼中載有兩項值得留意的審計備註:TIER 公開值由驗證者對照證明標頭和批次的次數位元進行檢查,但電路本身並不對其施加約束(審計 ZL1,已標記留待下一個約束集處理而未修復,因為移除它會改變公開值的佈局);而 H_IN 是客體程式可見的承諾,驗證者不會將其與調用方提供的值比對,此為有意的設計。

即將推出:區塊聚合

在第 14 條鏈和第 15 條鏈上,每個隱藏資產捆綁包證明約為 1.43 MB,一個 4 MiB 區塊(預設值,也是第 12 條鏈的設定)只能容納兩筆屏蔽轉賬;在 2 入 2 出捆綁包約 1.3 MB 的情況下則可容納三筆。第 13、14 和 15 條鏈將區塊上限提高至 20 MiB(max_block_bytes),可容納十四筆。第 20 條鏈維持 20 MiB,其上每筆轉賬帶有約 2.87 MB 的證明,因此一個區塊約容納七筆。fullnode 在 2026-09-12 選定的方案,勝過修剪歷史,也勝過擴大區塊,那就是區塊級聚合:每個封存視窗產生一個遞迴證明,用以驗證 N 個捆綁包證明,使歷史自始至終保持帶證明的狀態,而原始證明則可以丟棄。它已建成並已合併,但尚未啟用,而且自第 14 條鏈起,必須重新測量方可啟用:其獲准的捆綁包形態是以空的公開段(public 2)測量的,而綁定交易的捆綁包聲明為 public 4,因此第 14 條鏈上證明的捆綁包沒有一個與之吻合。約束集 7 和 8 再次改變了形態:捆綁包證明現在聲明 public 7 並發佈 35 個值,因此聚合的介面是每個證明 35 個字。節點版本會拒絕在任何帶有 aggregation 區段的創世上啟動,而第 14 至 20 條鏈均是在沒有該區段的情況下創建的。帶有動態 Gas 價格的創世(例如第 20 條鏈的創世)同樣不能與 aggregation 區段並存。自 fullnode v0.5.8 起,聚合證明亦綁定其聚合者(審計 AGG-2:程式吸收 aggregate_binding(chain_id, aggregator, nonce)),因此獲准形態的程式摘要必須在包含此改動的版本上測量。啟用前還有兩項待辦:針對已修復的遞迴驗證器進行端到端的偽造聚合演練,該演練尚未進行;以及就授權證明作出決定:聚合程式只驗證捆綁包證明,因此在採用拆分授權的鏈上,封存一個視窗會將一筆轉賬由約 2.87 MB 縮減至約 1.37 MB,而不是縮減為零。

已建成的部分:

  • 第二台以 Goldilocks 為原生的機器(遞迴 VM,randprotocol-rvm),其驗證者程式在層級 21 以約 197 萬行檢查一個 RV32 證明(約束集 7 下為 2,044,506 行),另有針對一個捆綁包證明視窗的通用 N 聚合程式;
  • 兩種角色:驗證節點維持較低的 CPU 成本,每個封存區塊只驗證一個聚合;聚合者(無需許可、須繳付保證金的註冊制,附有屏蔽收款地址)在 GPU 級機器上證明聚合,並獲得所涵蓋捆綁包的證明份額,外加按減半時間表發放的新 RAND 區塊補貼;
  • 五項操作(RegisterAggregator、UnbondAggregator、WithdrawAggregator、SlashAggregator、Aggregate;SlashAggregator 保留在線上格式中但會被拒絕,因為重試的聚合會以相同的 nonce 重新簽署,不屬於雙重簽署)、九步准入、封存並將所涵蓋的捆綁包修剪至每個僅約 3 KB 的公開欄位、讓新節點每個視窗只需一次遞迴驗證的封存格式同步、RPC 方法 rand_getAggregate、rand_getAggregators、rand_getUnsealed、rand_getRawTransaction,以及 rand-node aggregate --watch 守護程式。

在測試 FRI 設定檔上的測量結果:一個 N=1 的聚合在負載較高的手提電腦上約用 26 分鐘完成證明(327,035 位元組);一個新節點在不足一秒內套用了七個區塊的封存批次,只進行了一次遞迴驗證。機器等級按最初設定的上限為:N=1 需要 ≥ 64 GB 主機記憶體,N=2 需要 ≥ 128 GB,N=3 需要 ≥ 160 GB;生產環境 N ≥ 2 屬於 CUDA 後端,而它需要一個尚不存在的 GPU 節點。在約束集 7 下於 256 GB 機器上的測量結果(2026-09-28 和 29):N=2 聚合佔用 133 GB,N=3 佔用 221 GB,而生產退出證明(針對一個內層證明的驗證者程式)超過 256 GB。以上均未在約束集 8 下重新測量。在聚合啟用之前,第 20 條鏈上沒有任何聚合可取代證明:其兩個存檔節點保留所有原始證明,而其驗證節點則修剪 24 小時之前的歷史。

最後一次對照 fullnode 提交 c0878c3f(chain 21)核實的日期為 2026-10-12。 如代碼與本頁內容有出入,以代碼為準;請告知我們。