Rand Protocol
文檔
指南

程式

保密程式模型:以 RISC-V 客戶程式在 zkVM 中證明,一次部署,以私密輸入調用;涵蓋建構、部署、呼叫、調用及收據指令,自 chain 20 起的 RPL-2 程式狀態,以及目前尚未可行事項的如實清單。

使用本頁可將程式部署上鏈並呼叫:程式是甚麼、如何構建、一次呼叫會公開甚麼又隱藏甚麼、如何讀回收據,以及你會遇到的限制。每個程式都是公開代碼;每次呼叫都是一個證明。Example programs 載有完整的應用,randprotocol/example-programs 載有部署於 chain 20 的程式源碼(chain 21 於 2026-10-12 切換,起始時沒有任何程式:程式不會跨越切換而保留,示例程式亦尚未重新部署於其上),其中包括 RPL-2 程式(見下文)。

程式是甚麼

程式是供 Rand zkVM 使用的 RV32IM 機器碼:{ base_pc: u32, words: Vec<u32> },字數至多為該鏈的程式上限(chain 21 為 65,535 個字,自 chain 13 起每條鏈皆然;未設 max_program_words 的創世區塊,例如 chain 12,則為 4,096),base_pc 為 4 的倍數,每個字均可解碼為指令(無法解碼的字會在部署時被拒絕,而非在運行時)。與 chain 19 和 chain 20 一樣,chain 21 亦拒絕部署任何無法被一次呼叫容納的程式:沒有公開段時多於 8,180 個字,有公開段時則更少(見下文)。程式按內容定址,且不可變更:

program_id = blake3("rand-program" || base_pc || words)       // the id, with no public input
program_id = blake3("rand-program-2", base_pc || u32_le(len(words)) || words || u32_le(len(public)) || public)   // deployed with --public
code_hash  = hc = Poseidon2 digest of (base_pc, len, words)    // what calls are verified against

一次呼叫是一個 STARK 證明,證明摘要為 hc 的程式在某些私有輸入上運行,所耗 gas 不超過所聲明的 gas 上限,並公開八個輸出字。節點驗證該證明、記錄收據,除此之外不會發生任何事:輸出是數據,而非效果。呼叫不能轉移 RAND;呼叫者在支付該次呼叫費用的捆綁交易中轉移價值,而程式的輸出具何含義,由程式與其呼叫者約定。自 chain 20 起,Invoke 是例外:其證明擔保一項已聲明的狀態轉換,帳本隨後會應用該轉換(程式狀態 (RPL-2))。

客戶端程式(guest)能做的事:

組別指令
高位 / 跳轉LUI AUIPC JAL JALR
分支BEQ BNE BLT BGE BLTU BGEU
載入 / 儲存LW SW LB LH LBU LHU SB SH
ALUADDI SLTI SLTIU XORI ORI ANDI SLLI SRLI SRAI ADD SUB SLL SLT SLTU XOR SRL SRA OR AND
RV32MMUL MULH MULHU MULHSU DIV DIVU REM REMU
系統ECALL;不支援 FENCE、CSR、EBREAK,亦不支援 A 或 C 擴展

系統呼叫,按 a7 中的編號:

#系統呼叫效果
0HALT結束運行
1WRITE_OUTPUT slot word固定公開輸出 slot < 8;每個槽位至多寫入一次,未寫入的槽位為零
2READ_INPUT idx返回私有輸入字 idx,並綁定於加鹽承諾 H_IN
3POSEIDON2 ptr n以 Poseidon2 海綿結構就地對 n ≤ 4096 個字進行雜湊
4KECCAK ptr就地執行一次 Keccak-f[1600] 置換;令證明攜帶 keccak 表
5SHA256 ptr就地執行一次 SHA-256 壓縮;令證明攜帶 sha256 表
6READ_PUBLIC idx返回公開段的字 idx;自 chain 20 起,公開段於部署時固定(rand program deploy --public);在未設 max_program_public_words 的創世區塊上,公開段為空,此呼叫不會讀到任何內容
7POSEIDON2_LEN ptr n將訊息長度綁定入海綿結構的 POSEIDON2,使 [a] 與 [a, 0] 的雜湊不同(約束集 7,chain 16 及之後)。電路版本 aeacf31 的 rand-guest check 仍會拒絕它(見下一節)

記憶體:32 個暫存器,其中 x0 恆為零;從零開始的 RAM;每個地址均低於 2³⁰;供編譯後客戶端程式使用的 64 KiB 堆疊。以 rand-guest 構建的程式,其唯讀數據與已初始化數據存於映像容器中,並由屬於程式一部分的載入器前導碼,在程式自身代碼運行之前寫入這些數據(RISC-V ISA)。Note 承諾、nullifier 與 Merkle 檢查並非系統呼叫,而是建於 POSEIDON2 之上的庫例程。

自 chain 18(約束集 8)起,每次運行均以 gas 計量。一般指令及系統呼叫 0、1、2 和 6 各耗 1 gas,對 n 個字的 POSEIDON2 耗 3 + 3 × ⌈n / 4⌉,一次 KECCAK 置換耗 192,一次 SHA256 壓縮耗 64。Example programs 載有該表,以及一次呼叫須聲明的內容。

構建程式

有三種方式,均產出 RV32IM 字:

內置彙編器。 錢包附帶五個手工彙編的客戶端程式,並將它們彙編為 { "base_pc", "words" } JSON 檔案:

rand program build --guest private_payment --arg 1000 --out pp.json   # prints the program id
rand program build --guest balance_check --arg 1000 --out bc.json
# guests: fib, memcpy, bubble_sort, balance_check, private_payment, public_echo, rpl2_counter (v0.6.8); --arg is repeatable

以 rand-guest 編譯的程式。 電路庫中的 rand-guest 可將 no_std Rust crate(riscv32im-unknown-none-elf,Rust 1.98.1)或 C 目錄(clang 23.1.1)構建為映像容器,按機器的解碼器檢查每個字,並印出 hc 與程式 id。構建具封閉性,因此同一源碼在任何機器上都得出相同的 hc。對於 chain 18 至 20,請在電路提交 aeacf31(分支 feat/v067-circuits)構建工具鏈,fullnode v0.6.7 與 v0.6.8 均固定使用該提交。在該提交上,rand-guest check 只列出系統呼叫 0 至 6,因此呼叫 guest_sdk::poseidon2_len(系統呼叫 7)的客戶端程式會在構建時被拒絕,儘管機器能運行它(zkp-circuits issue #1)。逐步說明見:Deploy a Rust program 與 Deploy a RISC-V program。

轉譯程式。 sbpf2rv 轉譯 Solana sBPF ELF,evm2rv 轉譯 EVM 運行時字節碼,所得程式的輸出與 Rand 的直譯器客戶端程式逐字相同:Solana 轉譯器 與 Ethereum 轉譯器。

錢包本身沒有編譯器。rand program deploy 接受 .json、由小端序字組成的原始 .bin,或 rand-guest 寫出的映像容器(fullnode v0.3 及之後)。

部署

rand program deploy pp.json          # a bundle pays the floor; waits for the commit; prints the id
rand program show <id>               # id, base_pc, words_len, code_hash, deployed_at, public_words_len, public_digest

testnet 為 chain 21(自 2026-10-12 起運行),在其上部署、呼叫或調用均需要 fullnode v0.8.0 的 rand 錢包。舊版錢包完全無法在該鏈發送交易:chain 21 運行約束集 9,更改了每一個驗證密鑰及證明編碼,因此 v0.6.8 或 v0.7.x 錢包的證明甚至無法解碼;並且與 chain 20 一樣,創世區塊設定 binding_domain: 1,因此每個證明綁定及每條簽署訊息均包含創世雜湊。chain 21 起始時沒有任何程式:部署於 chain 20 的程式不會跨越切換而保留,示例程式亦尚未重新部署於其上。公共端點 https://rpc.randprotocol.org 為錢包的同步、部署與呼叫提供服務(設定)。

錢包首先印出程式 id、字數及 hc,並以 rand_estimateFee 向節點查詢費用;該方法會在任何證明之前拒絕超出該鏈上限的程式。然後,它構建一個零價值的自我轉帳捆綁交易(每筆交易都攜帶的那個 4 入 4 出隱藏資產捆綁交易;費用從其 RAND 槽位中扣除),以自身的 note 支付 0.001 RAND + 100,000 units × words(公開段的字計入代碼字),附上 Action::Deploy { base_pc, words, public },按該交易的綁定對捆綁交易生成證明並提交。自 chain 17 起這是兩個證明,錢包會為每個證明印出一行:tier-10 花費授權(數秒,約 1.37 MB)與 tier-14 捆綁交易(在筆記本電腦上約兩分鐘,約 1.5 MB)。在 chain 17 之前只有捆綁交易證明,在 chain 15 上約 100 秒、約 1.42 MB。部署費用沒有 gas 或字節項:gas 只為呼叫定價。節點檢查每個字均可解碼,計算 hc,儲存記錄,並在後台開始構建驗證密鑰。代碼是公開的;誰支付了費用則不公開 — rand_getProgram 沒有 deployer 欄位。重複部署相同的字是冪等的。

→ {"method":"rand_getProgram","params":["675adeea…0065"]}
← { "id": "675adeea…0065", "base_pc": 0, "words_len": 42, "code_hash": "…", "deployed_at": 10,
    "public_words_len": 0, "public_digest": null }
→ {"method":"rand_getProgramCode","params":["675adeea…0065"]}
← { "base_pc": 0, "words": [ … ] }

呼叫

rand call <program id> --input 400 --input 250 --input 300 --input 75
rand receipt <tx hash>

錢包從節點取得代碼與公開段,並檢查它們的雜湊是否與 id 相符。它在模擬器中運行該次呼叫,並在生成任何證明之前印出 gas 與費用:

gas: 5636 (declaring 6144, tier 12)
fee 0.006191437 RAND (incl. two price steps of headroom)

然後,它封存輸入記錄(見下文),以該鏈的 FRI 配置在本地為該次呼叫生成證明,並以輸入作為私有向量;再為支付費用的捆綁交易生成證明、提交、等待,並印出收據。自 chain 20 起,呼叫證明綁定於其自身的交易(該綁定包含創世雜湊),而捆綁交易為兩個證明,因此一次呼叫共有三個證明:呼叫、tier-10 花費授權與 tier-14 捆綁交易。上面兩行輸出取自 2026-09-30 在 chain 18 上對匿名投票的呼叫(An anonymous vote)。

費用。 自 chain 20 起,費用下限為 BUNDLE_BASE + gas_price × declared gas limit + byte_price × ⌈bytes / 1024⌉,其中 BUNDLE_BASE 為 0.001 RAND,位元組數為調用證明加上輸入信封,而兩項價格起初分別為 100 與 800 個單位(一個單位為 10⁻⁹ RAND),並隨區塊飽和度浮動。Chain 20 與 21 將兩者的上限定為 10,000 與 80,000 個單位,且只有需支付位元組價格的位元組(調用的證明與信封)才計入其負載(byte_load: "paying");在 chain 18 與 19 上,價格沒有上限,每筆交易的位元組都會推動位元組價格。帳本按「0.001 RAND + call_fee(tier)」計算的固定費率表,即 chain 15 上的規則,在此並不適用。錢包須在證明生成之前確定費用,因此按該鏈的證明上限(chain 20 為 4 MiB,chain 21 為 6 MiB)為證明定價,並另加兩個價格階梯的餘裕。在 chain 21 上,整個費用下限均被銷毀(genesis fees.burn_floor):提議者只保留發送者在下限之外多付的部分,而 rand_getSupply.base_fees_burned 記錄已被銷毀的數額(費用)。在 chain 18 上實測的四次調用,每次費用為 0.0057 至 0.0075 RAND(計算方式)。rand fee call <tier> --gas <limit> --bytes <B> 會直接向節點查詢費用下限。private_payment 讀取四個私密餘額,若其總和不低於門檻,便公開盈餘:輸出為 [1, 0, 25, 0, 0, 0, 0, 0]。鏈上只會看到證明、層級與這八個字;餘額則絕不會被看到。

旗標:--tier T 強制指定層級;--gas-limit <N|max> 聲明確切的 gas 上限,或該層級的上限值,以取代預設值(預設為確切 gas 向上取整至 2^(tier − 2) 的倍數);--fee <RAND> 設定費用;--expect-public <FILE> 會在證明生成前拒絕執行,除非程式的公開段正是該檔案中的字;--auditor <rand1…> 同時為指定的審計方封存執行記錄;--print-call-key 列印每次調用的密鑰;--no-envelope 不發佈執行記錄;--cuda 選用 GPU 後端(尚未在硬件上測試,且與封存信封不相容)。Chain 20 對調用直接拒絕 --cuda:與其交易綁定的調用證明須在 CPU 後端生成。

收據

每次已提交的調用均會儲存一份收據,並在節點同步或驗證其鏈時重新計算:

→ {"method":"rand_getReceipt","params":["b082…09b0"]}
← { "tx": "b082…09b0", "program": "675adeea…0065", "tier": 14,
    "outputs": [1, 0, 25, 0, 0, 0, 0, 0], "height": 105, "index": 0, "h_in": "9c0e…7f", "h_pub": null }

h_in 是證明對私密輸入所作的加鹽承諾;單憑它不會披露任何內容。h_pub 是程式於部署時公開段的摘要,即程式的 public_digest;若程式部署時沒有公開段,則為 null。收據中沒有 effect 欄位,所聲明的 gas 上限亦不在收據之內。瀏覽器於 GET /transactions/:hash 上將同一物件顯示為 call 的 receipt,於 GET /programs/:id 列出程式的調用,並可透過 GET /transactions?kind=call&program=<id> 篩選。

輸入信封:事後披露調用

預設情況下,rand call 會把調用的 (salt, inputs) 執行記錄封存於調用輸入信封(call-input envelope)中發佈,以便日後無須再生成一次證明,即可展示輸入:

部分位元組說明
body12 + 16 + 4·n + 16以全新的每次調用密鑰 K_call 加密的 salt ‖ inputs
to_sender60以調用者的出站查看密鑰包裹的 K_call
kem_ct1,088 或 0向審計方作出的 ML-KEM-768 封裝;無審計方時為空
to_auditor60 或 0以該封裝之秘密包裹的 K_call

本體的關聯資料為 H_IN,因此被移植到另一次調用上的信封,無人能夠開啟。鏈只檢查大小(至多為 max_call_envelope_bytes:chain 20 與 21 為 65,536 位元組,沒有該欄位的 genesis 則為 18,432),並以 rand_getCallEnvelope(tx) 原樣提供。三把密鑰可開啟信封,除此以外別無他者:調用者的查看密鑰(該錢包所作的每一次調用)、每次調用的密鑰(僅該次調用)、審計方的查看密鑰(僅該次調用)。

rand open-call <txhash>                    # as the caller
rand open-call <txhash> --as-auditor       # as the auditor
rand open-call <txhash> --call-key <hex>   # with the per-call key alone

open-call 會開啟執行記錄,檢查 input_digest(salt, inputs) == H_IN,透過模擬器以還原的輸入重新運行程式,並將輸出與收據中的輸出比對;任何一項檢查失敗,即以非零狀態退出,令腳本不會把警告誤當作通過。--no-envelope 不可逆轉:鹽一旦遺失,包括調用者在內,任何人均無法開啟該次調用。

自 v0.6.8 起,重新運行所採用的公開段,與生成證明時的公開段一致:即程式於部署時的公開字,以及在 hardening_v6 下緊隨其後的八字調用綁定(fullnode issue #116)。在 v0.6.7 中,open-call 只適用於部署時沒有公開段的程式;對於有公開段的程式,它會先列印輸入,然後以 re-running the program on these inputs failed: PublicIndex(0) 中止,在未執行任何一項檢查的情況下以非零狀態退出。

程式狀態(RPL-2)

Chain 20 是首條具備 RPL-2 的鏈,由其 genesis 的 program_state 區段啟用,而 chain 21 沿用該區段及相同數值。程式因而獲得三項原本沒有的能力(fullnode docs/program-state.md,v0.6.8 的 crates/randprotocol-core/src/ledger/program_state.rs):

儲存格每個程式一張由 8 字鍵至 8 字值的映射。不存在的儲存格讀取時為八個零;寫入八個零即移除該儲存格。已納入狀態根
金庫每種資產一個公開餘額(0 為 RAND)。價值經由 invoke 的 bundle 進入,並以鏈所計算的 note 形式流出
專屬代幣以 rand token create --program <id> 登記的代幣(鑄造權限為 Program(id),無初始供應量),只能由該程式的 invoke 鑄造與銷毀

儲存格與金庫餘額與代幣的供應量一樣,均屬公開。其中沒有任何 note。

Invoke(Action 33)是一種同時聲明狀態轉換(transition)的調用,其調用證明顯示程式接受的正是該轉換:

Invoke     { program, proof, input_envelope, transition }
Transition { reads:  [{ key, value }]     // cells read, with the values read; keys strictly ascending
             writes: [{ key, value }]     // cells written; keys strictly ascending
             inflow: none | deposit | burn
             pays:   [{ asset, amount, recipient, r, envelope }]   // notes out of the vault
             mints:  [{ asset, amount, recipient, r, envelope }] } // new units of the program's own token

流入的,是 bundle 所銷毀的部分:burn_r 為存入金庫的 RAND;burn_a 個 burn_asset 為存入(inflow 為 deposit)或被銷毀(inflow 為 burn,僅限程式自身的代幣)的代幣。流出的,是每筆支付對應一枚由鏈計算的 note,先支付後鑄造,其數額與接收方的 pk 均為公開,與鑄造的情況相同。只有在程式存在、結構合法、reads 中的每個儲存格仍持有所聲明的值、金庫(計入本交易自身的存入後)足以支付每一筆支付、每一筆鑄造均屬程式自身的代幣,且證明通過驗證時,帳本才會套用該轉換。讀取值不再相符者,會以 StaleRead 拒絕;錢包會重新讀取並重新生成證明。

invoke 與 call 有何不同。

Call(RPL-1)Invoke(RPL-2)
證明所依據的公開段public ‖ call_bindingpublic ‖ call_binding ‖ context,即以字表示的轉換
成功時鏈的操作儲存收據;輸出屬於資料儲存收據並套用轉換:寫入儲存格、移動金庫、附加支付 note
價值僅限 bundle 本身的轉賬經由 bundle 的銷毀存入金庫;支付與鑄造則從金庫流出
是否依賴狀態否證明不依賴(公開段由交易構建),但讀取檢查依賴,於准入時及在交易池中均會進行
費用調用費用下限調用費用下限,另加每建立一個儲存格的 cell_fee

程式以 READ_PUBLIC(public_len + 8 + i) 讀取第 i 個 context 字。第 0 字為版本(1),第 1 至 4 字為讀取、寫入、支付與鑄造的數目,接著是 burn_r、inflow 種類、burn_asset 與 burn_a,然後是每項讀取與寫入的鍵與值(各 8 字),最後是每筆支付的資產與數額。接收方不在 context 之內:程式決定數額,綁定則確定誰獲得支付。程式必須約束其所見的每一個 context 字,且不得存在任何會 panic 的路徑,因為 guest-sdk 的 panic 處理器會令執行停止,而已停止的執行是可以被證明的。

Chain 21 的限制(rand_getLimits.program_state,與 chain 20 相同):

限制chain 21
cell_fee每建立一個儲存格 10,000,000 個單位,即 0.01 RAND(即在原先沒有儲存內容之處寫入非零值的儲存格);改寫或刪除儲存格則免費
max_reads8 個儲存格
max_writes8 個儲存格
max_payouts4 枚 note,支付與鑄造合計

公開段的規則通常更為嚴格:整個公開段必須容納於對同一程式作調用時所依據的公開表之內,對於沒有公開輸入的程式為 127 個字。這樣便剩下 119 個 context 字,例如三項讀取、三項寫入與四筆支付。

命令與 RPC(錢包 v0.6.8 及其後版本):

rand program build --guest rpl2_counter --out counter.json   # one cell, incremented by one per invoke
rand program invoke <id> --transition step.json [--input N | --inputs-file F.json]
rand program state <id> [--cell <64 hex>]                   # rand_getProgramCell / rand_getProgramCells
rand program vault <id>                                      # rand_getProgramVault

program invoke 會在證明前,對照鏈上即時的 cell 檢查每一個 reads 項目;若讀取已過期,無論是在證明前還是在納入區塊時,都會以 3 結束,因此腳本須重新讀取並重試。rand_estimateFee 配合 "kind": "invoke" 可報出費用。轉換檔案的格式載於 fullnode 的 docs/cli.md。部署於 chain 20 的完整 RPL-2 程式(amm、stableswap、orderbook、stablecoin、lending、perp、crowdfund、stoploss),以及 RPL-1 程式(sealed-auction、ballot、eligibility、private-join、credit-score),均收錄於 randprotocol/example-programs。

Chain 21 亦載有 RPL-3 永續期貨,以創世 perps 區段的形式存在,而非已部署的程式:僅一個市場,即以 zUSD 結算的 BTC-PERP,其撮合引擎為固定的 guest(engine_hc f286a611…1573,由交易場所自身的 prover 在鏈下以 tier 18 證明),其狀態另有自己的創世根。它有六個專屬操作(標籤 34 至 39)及四個讀取方法:rand_getPerps、rand_getPerpAccount、rand_getPerpAccounts 和 rand_getPerpInputs(Transactions、JSON-RPC)。自行部署的程式無法呼叫它。

公開與隱藏的內容

公開隱藏
程式 id 及其程式碼;tier;宣告的 gas 上限;八個輸出;H_IN;bundle 的費用及公開欄位;信封的大小;呼叫使用的是 Keccak 還是 SHA-256,以及大致使用的次數(證明標頭會宣告各雜湊表的高度)私有輸入;暫存器、記憶體、分支;實際週期數及確切 gas;H_IN 的 salt;呼叫者是誰,以及以甚麼支付

同一次執行的兩個證明,位元組並不相同。這在 chain 15 及更早的鏈上並不足夠:私有字少於或等於 31 個的呼叫,所證明的表小得無法隱藏,其輸入可從證明中還原。自 v0.6 起,prover 已將這些表的下限定為 128 列,而約束集 7(chain 16 及其後)則遮蔽了仍會洩漏的各表總數。hc 具綁定性但不具隱藏性:任何能列舉候選程式的人,都可確認所部署的是哪一個。

目前尚無法做到的事

以下依 fullnode 的表述:

  • 不支援跨程式呼叫,亦無 RPL-2 以外的狀態。 一次 Call 是對一次執行的一個證明;除呼叫者回饋輸入的內容外,沒有任何東西會在呼叫之間延續。自 chain 20 起,Invoke 可讀寫程式自身的 cell 及 vault(見上文);chain 20 之前的鏈均無程式狀態,而 invoke 亦無法觸及其他程式的 cell。
  • vault 以外不支援由程式驅動的轉帳。 效果類型 1,即由程式向帳戶支付的轉帳,已隨帳戶一併刪除,而 Call 的輸出只是陳述。自 chain 20 起,Invoke 從程式自身的 vault 付款,最多四個 note,金額與收款人均為公開。
  • 錢包內沒有編譯器。 程式為內建組裝的 guest,或以電路儲存庫中的 rand-guest 建構的映像。
  • 公開輸入在部署時固定,而非每次呼叫時指定。 約束集 6 新增了 READ_PUBLIC 與 H_PUB。自 chain 20 起,一次部署最多可攜帶 32,768 個公開字,程式 id 會綁定這些字,而每次呼叫的證明均對照其摘要檢驗。沒有每次呼叫的公開字。
  • 雜湊系統呼叫會產生龐大的證明。 載有 keccak 的證明約 3.2 MB,直接超出預設 2 MiB 的證明上限;載有 sha256 的證明則多出約 400 KB。Chain 21 的上限為 6,291,456 位元組(6 MiB,於該鏈創建時為私密多重簽名授權證明而調高;chain 17 至 20 為 4 MiB,chain 13 至 16 為 8 MiB),兩者均可容納:在 chain 18 上,帶 Keccak 表的 tier-12 呼叫實測為 3.35 MB,帶 SHA-256 表的 tier-14 呼叫為 1.91 MB(Example programs)。一次呼叫亦限於 128 次 Keccak-f 置換及 128 次 SHA-256 壓縮(見下文),而證明的每 KiB 均按位元組價格收費。
  • EVM 與 Solana 程式無法在 chain 21 上部署,其呼叫亦超出呼叫 tier 上限。 直譯器 guest(evm.bin,18,009 字;sbpf.bin,8,317 字)及轉譯後的映像(ERC-20,11,686 字;SPL Token,65,096 字)均超出預設 4,096 字的上限,而低於 chain 13 所設、其後各鏈沿用的 65,535 字。兩個轉譯映像均於 2026-09-19 部署在 chain 13 上,其中 SPL Token 以其 ELF 作為公開輸入。Chain 14 與 15 為全新創建,兩者均未重新部署任何一個映像。Chain 21 與 chain 19 及 20 一樣,拒絕部署這四者中的任何一個:依其 hardening_v6 規則,凡沒有任何 tier-14 呼叫能容納的程式(無公開段者超過 8,180 字,有公開段者則更少),在部署時即被拒絕(ProgramUncallable),以免為無人能呼叫的程式支付部署費。ERC-20 呼叫以 tier 16 或 18 證明:tier-16 的 approve 曾於 2026-09-19 在 chain 13 上以 3,412,405 位元組的正式環境證明呼叫(Ethereum transpiler),而 chain 21 拒絕任何高於 tier 14 的呼叫(見下一項),因此目前在該鏈上不可能納入任何 ERC-20 呼叫。SPL Token 的呼叫為 tier 20,約需 330 GB;目前並無 SPL 呼叫證明存在(證明記憶體)。EVM 的區塊上下文操作碼會觸發陷阱,鏈上亦無 EVM 狀態。
  • 呼叫須以 tier 14 或以下證明。 自 fullnode v0.5.6(2026-09-25)起,高於 tier 14 的呼叫證明會被拒絕(CallTierTooHigh),Keccak-f 置換多於 128 次或 SHA-256 壓縮多於 128 次者亦然。Chain 13 的 tier-16 ERC-20 approve 在 chain 21 上會被拒絕,一如在 chain 15 及 chain 18 至 20 上那樣,而每一個 tier-18 的 ERC-20 或 tier-20 的 SPL Token 呼叫亦然;這些呼叫仍可在鏈下證明(預算)。
  • GPU 證明從未在硬件上運行過。 --cuda 需要 --features cuda 建構及已提交的 PTX;在 chain 20 創建時(2026-10-01),車隊上兩者均不存在。車隊上的呼叫證明由 CPU 後端生成;自 v0.7.1 起,--features cuda 建構在偵測到 GPU 時會預設選用 GPU,而 --cpu 則強制使用 CPU。
  • hc 不具隱藏性,如上所述,而且見證請求仍會讓節點得知錢包所花費的是哪一片 leaf。

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