Gunakan halaman ini untuk menempatkan sebuah program di chain dan memanggilnya: apa itu program, cara membangunnya, apa yang dipublikasikan dan apa yang disembunyikan oleh sebuah panggilan, cara membaca kembali sebuah kuitansi, dan batas-batas yang akan Anda temui. Setiap program adalah kode publik; setiap panggilan adalah sebuah bukti. Program contoh memuat aplikasi lengkap, dan randprotocol/example-programs memuat kode sumber program yang di-deploy di chain 20, termasuk program RPL-2 (di bawah).
Apa itu program
Program adalah kode mesin RV32IM untuk Rand zkVM: { base_pc: u32, words: Vec<u32> }, paling banyak sebesar batas program chain (65.535 word di chain 20, seperti di setiap chain sejak chain 13; 4.096 pada genesis tanpa max_program_words, seperti chain 12), dengan base_pc kelipatan 4, dan setiap word dapat didekode sebagai instruksi (word yang tidak dapat didekode ditolak saat deploy, tidak pernah saat dijalankan). Chain 20, seperti chain 19, juga menolak men-deploy program yang tidak dapat ditampung oleh panggilan mana pun: lebih dari 8.180 word tanpa segmen publik, atau lebih sedikit jika ada segmen publik (di bawah). Program ini beralamat konten dan tidak dapat diubah:
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
Sebuah panggilan adalah bukti STARK bahwa program dengan digest hc dijalankan pada beberapa input privat, tidak menghabiskan gas melebihi batas gas yang dinyatakan, dan mempublikasikan delapan word keluaran. Node memverifikasi bukti, mencatat sebuah kuitansi, dan tidak ada hal lain yang terjadi: keluaran adalah data, bukan efek. Sebuah panggilan tidak dapat memindahkan RAND; pemanggil memindahkan nilai dalam bundle yang membayar panggilan tersebut, dan keluaran sebuah program bermakna sebagaimana yang disepakati oleh program dan pemanggilnya. Di chain 20, Invoke merupakan pengecualian: buktinya menjamin sebuah transisi state yang dinyatakan, yang kemudian diterapkan oleh ledger (Program state (RPL-2)).
Apa yang dapat dilakukan guest:
| kelompok | instruksi |
|---|---|
| upper / jump | LUI AUIPC JAL JALR |
| cabang | BEQ BNE BLT BGE BLTU BGEU |
| load / store | LW SW LB LH LBU LHU SB SH |
| ALU | ADDI SLTI SLTIU XORI ORI ANDI SLLI SRLI SRAI ADD SUB SLL SLT SLTU XOR SRL SRA OR AND |
| RV32M | MUL MULH MULHU MULHSU DIV DIVU REM REMU |
| sistem | ECALL; tidak pernah FENCE, CSR, EBREAK, ekstensi A atau C |
Syscall, menurut nomor di a7:
| # | syscall | efek |
|---|---|---|
| 0 | HALT | mengakhiri eksekusi |
| 1 | WRITE_OUTPUT slot word | menetapkan keluaran publik slot < 8; setiap slot paling banyak sekali, slot yang tidak ditulis bernilai nol |
| 2 | READ_INPUT idx | mengembalikan word input privat idx, terikat pada komitmen bergaram H_IN |
| 3 | POSEIDON2 ptr n | meng-hash n ≤ 4096 word di tempat dengan sponge Poseidon2 |
| 4 | KECCAK ptr | satu permutasi Keccak-f[1600] di tempat; membuat bukti memuat tabel keccak |
| 5 | SHA256 ptr | satu kompresi SHA-256 di tempat; membuat bukti memuat tabel sha256 |
| 6 | READ_PUBLIC idx | mengembalikan word segmen publik idx; di chain 20 segmen publik ditetapkan saat deploy (rand program deploy --public); pada genesis tanpa max_program_public_words segmen ini kosong dan syscall ini tidak membaca apa pun |
| 7 | POSEIDON2_LEN ptr n | POSEIDON2 dengan panjang pesan terikat ke dalam sponge, sehingga [a] dan [a, 0] menghasilkan hash yang berbeda (constraint set 7, chain 16 dan seterusnya). rand-guest check pada circuits aeacf31 masih menolaknya (bagian berikutnya) |
Memori: 32 register dengan x0 bernilai nol; RAM yang dimulai dari nol; setiap alamat di bawah 2³⁰; stack 64 KiB untuk guest yang dikompilasi. Program yang dibangun dengan rand-guest membawa data read-only dan data terinisialisasinya dalam image container, dan sebuah prolog loader yang menjadi bagian dari program menulis data tersebut sebelum kode program itu sendiri berjalan (ISA RISC-V). Komitmen note, nullifier, dan pemeriksaan Merkle bukanlah syscall, melainkan rutin pustaka di atas POSEIDON2.
Sejak chain 18 (constraint set 8) setiap eksekusi diukur dalam gas. Instruksi biasa serta syscall 0, 1, 2, dan 6 masing-masing berbiaya 1 gas, POSEIDON2 atas n word berbiaya 3 + 3 × ⌈n / 4⌉, satu permutasi KECCAK berbiaya 192, dan satu kompresi SHA256 berbiaya 64. Program contoh memuat tabelnya dan apa yang dinyatakan oleh sebuah panggilan.
Membangun program
Tiga cara, semuanya menghasilkan word RV32IM:
Assembler bawaan. Wallet menyertakan lima guest yang di-assemble secara manual dan meng-assemble-nya menjadi berkas JSON { "base_pc", "words" }:
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
Program yang dikompilasi, dengan rand-guest. rand-guest dari repositori circuits membangun crate Rust no_std (riscv32im-unknown-none-elf, Rust 1.98.1) atau direktori C (clang 23.1.1) menjadi image container, memeriksa setiap word terhadap decoder mesin, dan mencetak hc serta id program. Build-nya hermetik, sehingga kode sumber yang sama menghasilkan hc yang sama di mesin mana pun. Untuk chain 18 hingga 20, bangun toolchain pada commit circuits aeacf31 (branch feat/v067-circuits), commit yang di-pin oleh fullnode v0.6.7 dan v0.6.8. Pada commit tersebut rand-guest check hanya mencantumkan syscall 0 hingga 6, sehingga guest yang memanggil guest_sdk::poseidon2_len (syscall 7) ditolak saat build meskipun mesin menjalankannya (zkp-circuits issue #1). Langkah demi langkah: Men-deploy program Rust dan Men-deploy program RISC-V.
Program hasil terjemahan. sbpf2rv menerjemahkan ELF sBPF Solana, dan evm2rv menerjemahkan bytecode runtime EVM, menjadi program yang keluarannya sama dengan guest interpreter Rand word demi word: Transpiler Solana dan Transpiler Ethereum.
Wallet itu sendiri tidak memiliki compiler. rand program deploy menerima berkas .json, berkas .bin mentah berisi word little-endian, atau image container yang ditulis oleh rand-guest (fullnode v0.3 dan seterusnya).
Men-deploy
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 adalah chain 20, dan untuk men-deploy, memanggil, atau meng-invoke di sana diperlukan wallet rand dari fullnode v0.6.8 atau yang lebih baru. Wallet yang lebih lama sama sekali tidak dapat mengirim ke sana: genesis chain 20 menetapkan binding_domain: 1, sehingga setiap binding bukti dan setiap pesan bertanda tangan menyertakan hash genesis, sedangkan binding wallet v0.6.7 hanya membawa id chain. Endpoint publik https://rpc.randprotocol.org melayani sinkronisasi, deploy, dan panggilan wallet (penyiapan).
Wallet terlebih dahulu mencetak id program, jumlah word, dan hc, lalu meminta biaya kepada node dengan rand_estimateFee, yang menolak program yang melebihi batas chain sebelum proving apa pun. Kemudian wallet membangun bundle self-transfer bernilai nol (satu bundle aset tersembunyi 4-in-4-out yang dibawa setiap transaksi; biayanya diambil dari slot RAND-nya) yang membayar 0.001 RAND + 100,000 units × words dari note miliknya sendiri (word segmen publik dihitung sebagai word kode), melampirkan Action::Deploy { base_pc, words, public }, membuktikan bundle terhadap binding transaksi, lalu mengirimkannya. Sejak chain 17 itu berarti dua bukti, dan wallet mencetak satu baris untuk masing-masing: otorisasi pembelanjaan tier-10 (beberapa detik, sekitar 1,37 MB) dan bundle tier-14 (sekitar dua menit pada laptop, sekitar 1,5 MB). Sebelum chain 17 hanya ada bukti bundle, sekitar 100 s dan sekitar 1,42 MB pada chain 15. Biaya deploy tidak memiliki komponen gas atau byte: gas hanya menentukan harga panggilan. Node memeriksa bahwa setiap word dapat didekode, menghitung hc, menyimpan catatannya, dan mulai membangun verifier key di latar belakang. Kodenya publik; siapa yang membayarnya tidak — rand_getProgram tidak memiliki field deployer. Men-deploy word yang sama dua kali bersifat idempoten.
→ {"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": [ … ] }
Memanggil
rand call <program id> --input 400 --input 250 --input 300 --input 75
rand receipt <tx hash>
Wallet mengambil kode dan segmen publik dari node dan memeriksa bahwa keduanya menghasilkan hash yang sama dengan id. Wallet menjalankan panggilan di emulator dan mencetak gas serta biaya sebelum membuktikan apa pun:
gas: 5636 (declaring 6144, tier 12)
fee 0.006191437 RAND (incl. two price steps of headroom)
Wallet kemudian menyegel transkrip input (di bawah), membuktikan panggilan secara lokal di bawah profil FRI chain dengan input sebagai vektor privat, membuktikan bundle yang membayar biaya, mengirimkan, menunggu, dan mencetak kuitansi. Di chain 20 bukti panggilan terikat pada transaksinya sendiri (binding yang menyertakan hash genesis) dan bundle terdiri dari dua bukti, sehingga sebuah panggilan menghasilkan tiga: panggilan, otorisasi pembelanjaan tier-10, dan bundle tier-14. Kedua baris di atas berasal dari panggilan pemungutan suara anonim di chain 18 pada 2026-09-30 (Pemungutan suara anonim).
Biaya. Pada chain 20, batas bawahnya adalah BUNDLE_BASE + gas_price × declared gas limit + byte_price × ⌈bytes / 1024⌉, dengan BUNDLE_BASE sebesar 0,001 RAND, byte yang dihitung adalah bukti panggilan ditambah envelope input, dan harga awalnya 100 dan 800 unit (satu unit adalah 10⁻⁹ RAND) yang bergerak mengikuti tingkat keterisian blok. Chain 20 membatasinya pada 10.000 dan 80.000 unit, dan hanya byte yang membayar harga byte (bukti dan envelope panggilan) yang dihitung dalam bebannya (byte_load: "paying"); pada chain 18 dan 19 harga tidak memiliki batas atas dan byte setiap transaksi menggerakkan harga byte. Skema datar buku besar 0.001 RAND + call_fee(tier), aturan pada chain 15, tidak berlaku di sana. Dompet menetapkan biaya sebelum bukti ada, sehingga ia menghitung harga bukti pada batas 4 MiB milik chain dan menambahkan ruang cadangan sebesar dua langkah harga. Empat panggilan terukur pada chain 18 masing-masing berbiaya 0,0057 hingga 0,0075 RAND (perhitungannya). rand fee call <tier> --gas <limit> --bytes <B> menanyakan batas bawah itu langsung kepada node. private_payment membaca empat saldo privat dan, jika jumlahnya mencapai ambang batasnya, mempublikasikan selisih lebihnya: keluaran [1, 0, 25, 0, 0, 0, 0, 0]. Chain melihat bukti, tier, dan kedelapan kata itu; chain tidak pernah melihat saldonya.
Flag: --tier T memaksakan suatu tier; --gas-limit <N|max> menyatakan batas gas yang tepat atau batas atas tier sebagai pengganti nilai bawaan, yaitu gas yang tepat dibulatkan ke atas ke kelipatan 2^(tier − 2); --fee <RAND> menetapkan biaya; --expect-public <FILE> menolak sebelum pembuktian kecuali segmen publik program adalah kata-kata dari berkas tersebut; --auditor <rand1…> menyegel transkrip bagi auditor yang disebutkan juga; --print-call-key mencetak kunci per panggilan; --no-envelope tidak mempublikasikan transkrip; --cuda memilih backend GPU (belum diuji pada perangkat keras, dan tidak kompatibel dengan penyegelan envelope). Chain 20 menolak --cuda pada panggilan sama sekali: bukti panggilan yang terikat pada transaksinya dibuat pada backend CPU.
Tanda terima
Satu tanda terima disimpan untuk setiap panggilan yang telah di-commit dan dihitung ulang ketika sebuah node melakukan sinkronisasi atau memverifikasi chain-nya:
→ {"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 adalah komitmen bergaram dari bukti terhadap input privat; dengan sendirinya ia tidak mengungkapkan apa pun. h_pub adalah digest dari segmen publik program saat deploy, yaitu public_digest program, atau null untuk program yang di-deploy tanpa segmen tersebut. Tidak ada kolom effect, dan batas gas yang dinyatakan tidak tercantum dalam tanda terima. Penjelajah menampilkan objek yang sama sebagai receipt pada GET /transactions/:hash untuk sebuah call, mendaftarkan panggilan suatu program pada GET /programs/:id, dan menyaring GET /transactions?kind=call&program=<id>.
Envelope input: mengungkapkan panggilan di kemudian hari
Secara bawaan rand call mempublikasikan transkrip (salt, inputs) dari panggilan itu, disegel dalam sebuah envelope input panggilan, sehingga input dapat ditunjukkan kemudian tanpa bukti kedua:
| bagian | byte | keterangan |
|---|---|---|
body | 12 + 16 + 4·n + 16 | salt ‖ inputs di bawah kunci baru per panggilan K_call |
to_sender | 60 | K_call yang dibungkus dengan kunci pandang keluar milik pemanggil |
kem_ct | 1.088 atau 0 | enkapsulasi ML-KEM-768 untuk auditor, kosong jika tanpa auditor |
to_auditor | 60 atau 0 | K_call yang dibungkus di bawah rahasia enkapsulasi tersebut |
Data terasosiasi dari body adalah H_IN, sehingga envelope yang dipindahkan ke panggilan lain tidak dapat dibuka oleh siapa pun. Chain hanya memeriksa ukurannya (paling banyak max_call_envelope_bytes: 65.536 byte pada chain 20, 18.432 pada genesis tanpa kolom tersebut) dan menyajikannya apa adanya melalui rand_getCallEnvelope(tx). Tiga kunci membukanya, tidak lebih: kunci pandang pemanggil (setiap panggilan yang dibuat dompet itu), kunci per panggilan (satu panggilan itu), kunci pandang auditor (satu panggilan itu).
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 membuka transkrip, memeriksa bahwa input_digest(salt, inputs) == H_IN, menjalankan ulang program pada input yang dipulihkan melalui emulator, membandingkan keluarannya dengan keluaran pada tanda terima — dan keluar dengan kode bukan nol jika salah satu pemeriksaan gagal, sehingga skrip tidak dapat keliru menganggap peringatan sebagai jawaban ya. --no-envelope tidak dapat dibatalkan: begitu salt hilang, tidak seorang pun, termasuk pemanggil, dapat membuka panggilan tersebut.
Sejak v0.6.8, penjalanan ulang dilakukan atas segmen publik yang menjadi dasar pembuatan bukti: kata-kata publik program saat deploy dan, di bawah hardening_v6, pengikatan panggilan sepanjang delapan kata setelahnya (isu fullnode #116). Pada v0.6.7 open-call hanya berfungsi untuk program yang di-deploy tanpa segmen publik; untuk program yang memilikinya, ia mencetak input lalu berhenti dengan re-running the program on these inputs failed: PublicIndex(0), keluar dengan kode bukan nol tanpa menjalankan kedua pemeriksaan itu.
Status program (RPL-2)
Chain 20 adalah chain pertama dengan RPL-2, yang diaktifkan oleh bagian program_state pada genesis-nya. Sebuah program memperoleh tiga hal yang sebelumnya tidak dimilikinya (fullnode docs/program-state.md, crates/randprotocol-core/src/ledger/program_state.rs pada v0.6.8):
| sel | pemetaan dari kunci 8 kata ke nilai 8 kata, per program. Sel yang tidak ada terbaca sebagai delapan nol; menulis delapan nol menghapusnya. Di-commit dalam akar status |
| brankas | saldo publik per aset (0 adalah RAND). Nilai masuk melalui bundle sebuah invoke dan keluar sebagai catatan yang dihitung oleh chain |
| token miliknya sendiri | token yang didaftarkan dengan rand token create --program <id> (otoritas pencetakan Program(id), tanpa pasokan awal) dicetak dan dibakar hanya oleh invoke program tersebut |
Sel dan saldo brankas bersifat publik, seperti pasokan sebuah token. Tidak ada satu pun di dalamnya yang berupa catatan.
Invoke (Action 33) adalah panggilan yang juga menyatakan sebuah transisi, dan bukti panggilannya menunjukkan bahwa program menerima tepat transisi itu:
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
Yang masuk adalah yang dibakar oleh bundle: burn_r adalah RAND yang disetor ke brankas; burn_a dari burn_asset adalah token yang disetor (inflow deposit) atau dimusnahkan (inflow burn, hanya token milik program itu sendiri). Yang keluar adalah satu catatan yang dihitung chain untuk setiap pembayaran keluar, pays lalu mints, dengan jumlah dan pk penerima bersifat publik, seperti pada pencetakan. Buku besar menerapkan transisi hanya jika program ada, bentuknya sah, setiap sel dalam reads masih memuat nilai yang dinyatakan, brankas (setelah setoran transaksi ini sendiri) mencukupi setiap pay, setiap mint adalah token milik program itu sendiri, dan bukti-buktinya terverifikasi. Pembacaan yang tidak lagi cocok ditolak sebagai StaleRead; dompet membaca ulang dan membuktikan ulang.
Perbedaan invoke dengan call.
Call (RPL-1) | Invoke (RPL-2) | |
|---|---|---|
| segmen publik yang menjadi dasar pembuatan bukti | public ‖ call_binding | public ‖ call_binding ‖ context, transisi sebagai kata-kata |
| yang dilakukan chain jika berhasil | menyimpan tanda terima; keluaran berupa data | menyimpan tanda terima dan menerapkan transisi: menulis sel, memindahkan brankas, menambahkan catatan pembayaran keluar |
| nilai | hanya transfer milik bundle itu sendiri | setoran ke brankas melalui pembakaran bundle; pembayaran keluar dan pencetakan dari brankas |
| bergantung pada status | tidak | buktinya tidak (segmen dibangun dari transaksi), tetapi pemeriksaan pembacaan bergantung, pada saat penerimaan dan di dalam pool |
| biaya | batas bawah panggilan | batas bawah panggilan ditambah cell_fee per sel yang dibuat |
Sebuah program membaca kata konteks i dengan READ_PUBLIC(public_len + 8 + i). Kata 0 adalah versi (1), kata 1 sampai 4 adalah jumlah reads, writes, pays, dan mints, kemudian burn_r, jenis inflow, burn_asset, dan burn_a, lalu setiap read dan write sebagai kunci dan nilai (masing-masing 8 kata), lalu setiap pembayaran keluar sebagai aset dan jumlah. Penerima tidak ada dalam konteks: program menentukan jumlahnya, sedangkan pengikatan menetapkan siapa yang dibayar. Sebuah program harus membatasi setiap kata konteks yang ditampilkan kepadanya, dan tidak boleh memiliki jalur yang menyebabkan panic, karena panic handler milik guest-sdk menghentikan eksekusi dan eksekusi yang terhenti adalah eksekusi yang dapat dibuktikan.
Batas-batas chain 20 (rand_getLimits.program_state):
| batas | chain 20 |
|---|---|
cell_fee | 10.000.000 unit, 0,01 RAND, per sel yang dibuat (sel yang ditulis dengan nilai bukan nol padahal sebelumnya tidak ada yang tersimpan); menulis ulang atau menghapus sel tidak dikenai biaya |
max_reads | 8 sel |
max_writes | 8 sel |
max_payouts | 4 catatan, pays dan mints digabungkan |
Aturan segmen biasanya lebih ketat: seluruh segmen harus muat dalam tabel publik yang menjadi dasar pembuatan bukti panggilan ke program yang sama, yaitu 127 kata untuk program tanpa input publik. Itu menyisakan 119 kata konteks, misalnya tiga reads, tiga writes, dan empat pembayaran keluar.
Perintah dan RPC (dompet 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 memeriksa setiap entri reads terhadap sel yang aktif sebelum membuktikan, dan keluar dengan kode 3 pada pembacaan yang usang, baik sebelum pembuktian maupun saat inklusi, sehingga skrip membaca ulang dan mencoba lagi. rand_estimateFee dengan "kind": "invoke" menawarkan kuotasi biaya. Format berkas transisi dijelaskan dalam docs/cli.md milik fullnode. Program RPL-2 lengkap yang di-deploy pada chain 20 (amm, stableswap, orderbook, stablecoin, lending, perp, crowdfund, stoploss), dan program RPL-1 (sealed-auction, ballot, eligibility, private-join, credit-score), tersedia di randprotocol/example-programs.
Apa yang publik dan apa yang tersembunyi
| publik | tersembunyi |
|---|---|
id program dan kodenya; tier; batas gas yang dideklarasikan; kedelapan output; H_IN; biaya dan field publik milik bundel; ukuran envelope; apakah panggilan menggunakan Keccak atau SHA-256, dan kira-kira seberapa sering (header bukti mendeklarasikan tinggi setiap tabel hash) | input privat; register, memori, cabang; jumlah siklus sebenarnya dan gas yang tepat; salt H_IN; siapa yang memanggil dan dengan apa mereka membayar |
Dua bukti dari eksekusi yang sama menghasilkan byte yang berbeda. Hal itu belum cukup pada chain 15 dan sebelumnya: panggilan dengan 31 kata privat atau kurang membuktikan tabel yang terlalu kecil untuk menyembunyikan isinya, sehingga inputnya dapat dipulihkan dari bukti. Sejak v0.6, prover memberi batas bawah 128 baris pada tabel-tabel tersebut, dan constraint set 7 (chain 16 dan seterusnya) menyamarkan total per tabel yang masih bocor. hc bersifat binding tetapi tidak hiding: siapa pun yang dapat menyebutkan satu per satu program kandidat dapat memastikan program mana yang telah di-deploy.
Apa yang belum dimungkinkan
Sebagaimana dinyatakan oleh fullnode:
- Tidak ada panggilan antarprogram, dan tidak ada state di luar RPL-2. Sebuah
Calladalah satu bukti atas satu eksekusi; tidak ada yang terbawa dari satu panggilan ke panggilan berikutnya kecuali yang dimasukkan kembali oleh pemanggil. Pada chain 20, sebuahInvokemembaca dan menulis cell serta vault milik program itu sendiri (di atas); tidak ada chain sebelum chain 20 yang memiliki state program, dan sebuah invoke tidak dapat menyentuh cell milik program lain. - Tidak ada transfer yang digerakkan program di luar vault. Efek jenis 1, yaitu transfer yang dibayar program ke sebuah akun, telah dihapus bersama akun-akun tersebut, dan output sebuah
Callhanyalah pernyataan. Pada chain 20, sebuahInvokemembayar dari vault milik program itu sendiri, paling banyak empat note, dengan jumlah dan penerima yang bersifat publik. - Tidak ada compiler di dalam wallet. Program berupa guest bawaan yang sudah dirakit, atau image yang dibangun dengan
rand-guestdi repositori circuits. - Input publik ditetapkan saat deploy, bukan per panggilan. Constraint set 6 menambahkan
READ_PUBLICdanH_PUB. Pada chain 20, sebuah deploy dapat membawa hingga 32.768 kata publik, id program mengikatnya, dan bukti setiap panggilan diperiksa terhadap digest-nya. Tidak ada kata publik per panggilan. - Syscall hash menghasilkan bukti yang besar. Bukti yang memuat keccak berukuran sekitar 3,2 MB, jelas melampaui batas bukti bawaan sebesar 2 MiB; bukti yang memuat sha256 menambah sekitar 400 KB. Batas pada chain 20 adalah 4.194.304 byte (4 MiB, seperti pada chain 17 sampai 19; pada chain 13 sampai 16 batasnya 8 MiB), yang menampung keduanya: pada chain 18, panggilan tier-12 dengan tabel Keccak berukuran 3,35 MB dan panggilan tier-14 dengan tabel SHA-256 berukuran 1,91 MB (Example programs). Sebuah panggilan juga dibatasi pada 128 permutasi Keccak-f dan 128 kompresi SHA-256 (di bawah), dan setiap KiB bukti dikenai biaya menurut harga per byte.
- Program EVM dan Solana tidak dapat di-deploy pada chain 20, dan panggilannya melampaui batas tier panggilan. Guest interpreter (
evm.bin, 18.009 kata;sbpf.bin, 8.317) dan image hasil terjemahan (ERC-20, 11.686 kata; SPL Token, 65.096) melampaui batas bawaan 4.096 kata dan berada di bawah 65.535 yang ditetapkan chain 13 dan dipertahankan oleh setiap chain sesudahnya. Kedua image hasil terjemahan telah di-deploy pada chain 13 pada 2026-09-19, SPL Token dengan ELF-nya sebagai input publik. Chain 14 dan 15 dibuat baru, dan tidak satu pun dari kedua image di-deploy ulang pada keduanya. Chain 20, seperti chain 19, menolak men-deploy keempatnya: berdasarkan aturanhardening_v6, program yang tidak dapat ditampung oleh panggilan tier-14 mana pun, yaitu lebih dari 8.180 kata tanpa segmen publik dan lebih sedikit bila ada segmen publik, ditolak saat deploy (ProgramUncallable), sehingga biaya deploy tidak dibayarkan untuk program yang tidak dapat dipanggil siapa pun. Panggilan ERC-20 dibuktikan pada tier 16 atau 18:approvetier-16 dipanggil pada chain 13 pada 2026-09-19 dengan bukti produksi sebesar 3.412.405 byte (Ethereum transpiler), dan chain 20 menolak setiap panggilan di atas tier 14 (butir berikutnya), sehingga saat ini tidak ada panggilan ERC-20 yang dapat diterima di sana. Panggilan SPL Token berada pada tier 20, yang membutuhkan sekitar 330 GB; belum ada bukti panggilan SPL (proving memory). Opcode konteks blok EVM mengalami trap, dan tidak ada state EVM on-chain. - Panggilan dibuktikan pada tier 14 atau lebih rendah. Sejak fullnode v0.5.6 (2026-09-25), bukti panggilan di atas tier 14 ditolak (
CallTierTooHigh), demikian pula bukti dengan lebih dari 128 permutasi Keccak-f atau 128 kompresi SHA-256.approveERC-20 tier-16 milik chain 13 akan ditolak pada chain 20, sebagaimana akan ditolak pada chain 15, 18, dan 19, dan demikian pula setiap panggilan ERC-20 tier-18 atau SPL Token tier-20; semuanya tetap dapat dibuktikan di luar chain (the budget). - Proving dengan GPU belum pernah dijalankan pada perangkat keras.
--cudamembutuhkan build--features cudadan PTX yang sudah di-commit; keduanya tidak ada pada fleet. Pada chain 20, bukti panggilan dibuat pada backend CPU apa pun build-nya. hctidak bersifat hiding, seperti dijelaskan di atas, dan sebuah permintaan witness tetap memberi tahu node leaf mana yang dibelanjakan sebuah wallet.