Rand Protocol
Dokumentasi
Program RISC-V

ISA RISC-V

Maksud RV32IM pada Rand - arahan yang dibuktikan oleh zkVM, perkara yang ditolak oleh pemeriksa, lapan syscall, memori, bekas imej yang digunakan untuk menghantar sesebuah atur cara, dan had atur cara.

Baca halaman ini sebelum anda menulis atur cara untuk Rand. Halaman ini menyatakan mesin yang menjalankan kod anda, perkara yang ditolak oleh rantaian alat, cara atur cara berhubung dengan dunia luar, dan fail yang anda sebarkan. Halaman seterusnya menggunakannya: Deploy a Rust program, Deploy a RISC-V program, dan kedua-dua transpiler.

Mesin

Atur cara Rand ialah RV32IM: set integer asas RISC-V 32-bit ditambah sambungan darab dan bahagi. Atur cara ini berjalan di dalam Rand zkVM, yang membuktikan setiap larian dengan batch STARK Plonky3. Pengesah tidak pernah melihat sebarang arahan. Ia menyemak bukti terhadap hc, ringkasan Poseidon2 dalam litar bagi atur cara tersebut.

kumpulanarahan
atas / lompatanLUI AUIPC JAL JALR
cabangBEQ BNE BLT BGE BLTU BGEU
muat / simpanLW 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
sistemECALL sahaja

JALR mengosongkan bit 0 pada sasarannya, seperti yang ditetapkan RV32I, dan pengekodannya mesti mempunyai funct3 = 0. Kedua-dua peraturan ini hadir bersama set kekangan 7 (chain 16); sebelum itu, sasaran ganjil tidak dapat diambil dan larian tidak dapat dibuktikan. Sasaran yang genap tetapi bukan gandaan empat masih tidak dapat diambil.

Tiada titik terapung, tiada atomik (sambungan A), tiada arahan termampat (sambungan C) dan tiada daftar 64-bit. Pembahagian 64-bit dalam C menjadi panggilan kepada pembantu perisian; lihat laluan C.

Perkara yang ditolak

rand-guest check menjalankan setiap perkataan teks melalui penyahkod mesin itu sendiri. Atur cara yang lulus tidak boleh gagal dalam litar atas sebab pengekodan, nombor syscall atau susun atur. Penyemak menolak:

dapatanmaksudnya
Compressedpengekodan RVC 16-bit; mesin hanya menyahkod perkataan 32-bit
Undecodableopcode, funct atau jumlah anjakan yang tidak dilaksanakan oleh mesin
FenceFENCE atau FENCE.I; mesin tidak mempunyai tertib memori
Csrsebarang arahan CSR; mesin tidak mempunyai CSR
EbreakEBREAK; perangkap tidak dimodelkan
Syscallecall yang a7-nya ditetapkan oleh li sebelum arahan itu dan tidak menamakan sebarang syscall
Capperkataan melebihi --max-words, dikira seperti yang dikira oleh pemuat
Layouttapak teks yang tidak sejajar perkataan

Atur cara empat perkataan dengan fence, ebreak dan ecall bernombor 9, seperti yang dilaporkan oleh rand-guest check (kod keluar 1):

$ rand-guest check bad.elf
note: the loader refuses this image (Decode { index: 0, word: 267386895, err: Opcode(15) }), so its data prologue could not be counted; the word count below is the text alone
0x00001000  0x0ff0000f  Fence: FENCE/FENCE.I: the machine has no memory ordering instructions
0x00001004  0x00100073  Ebreak: EBREAK: traps are not modelled
0x0000100c  0x00000073  Syscall: ecall with a7 = 9, which is no syscall the machine implements
4 words against a cap of 4096 (fits); 0 ecall(s) with a non-static a7
REJECTED

ecall yang a7-nya tidak dapat dilihat oleh penyemak (ditetapkan oleh selain li, atau selepas cabang) dikira sebagai unresolved_ecalls, bukan ditolak. Mesin tetap membuat perangkap pada nombor yang salah semasa larian.

Penyemak tidak menyemak nilai penuding, panjang atau indeks input, tindanan 64 KiB berbanding RAM, atau penjajaran alamat yang dikira semasa larian. Capaian tidak sejajar ialah pelanggaran kekangan, maka rantaian alat mengkompil dengan -unaligned-scalar-mem. rand-guest run melaporkan sebarang perangkap semasa larian.

Syscall

ECALL membaca nombor syscall daripada a7, argumen pertama daripada a0 dan argumen kedua daripada a1. Satu nilai dikembalikan dalam a0.

#syscallkesangasRust (guest-sdk)C (guest.h)
0HALTmenamatkan larian1halt()rand_halt()
1WRITE_OUTPUT slot wordmenetapkan output awam slot < 8, paling banyak sekali bagi setiap slot; slot yang tidak ditulis bernilai sifar1write_output(slot, word)rand_write_output
2READ_INPUT idxmengembalikan perkataan input persendirian idx, terikat kepada komitmen bergaram H_IN1read_input(idx)rand_read_input
3POSEIDON2 ptr nmeringkaskan n ≤ 4096 perkataan pada alamat perkataan ptr dan menulis ringkasan 8 perkataan di atas ptr..ptr+8; tanpa pelapik3 + 3·⌈n/4⌉unsafe poseidon2(ptr, n)rand_poseidon2
4KECCAK ptrsatu pilih atur Keccak-f[1600] di tempat pada 50 perkataan192keccak(state), keccak256(msg)rand_keccak
5SHA256 ptrsatu mampatan SHA-256 di tempat pada 24 perkataan64sha256_compress(buf), sha256(msg)rand_sha256_compress
6READ_PUBLIC idxmengembalikan perkataan segmen awam idx, terikat kepada H_PUB tanpa garam1read_public(idx)rand_read_public
7POSEIDON2_LEN ptr nPOSEIDON2 dengan panjang n terikat ke dalam span, sekurang-kurangnya satu pilih atur (set kekangan 7)3 + 3·max(⌈n/4⌉, 1)poseidon2_len(buf, n)tiada

Setiap arahan lain berharga 1 gas: gas ialah satu bagi setiap baris cpu, dan hanya syscall cincang yang lebih berat (set kekangan 8, sejak chain 18). Satu panggilan Poseidon2 ialah baris ecall-nya, dua baris tulis balik dan ⌈n/4⌉ baris serap pada 3 gas setiap satu.

POSEIDON2 tidak melapik. Span menulis ganti lorong pertamanya dengan setiap ketulan empat perkataan, jadi [a], [a, 0], [a, 0, 0] dan [a, 0, 0, 0] menghasilkan satu ringkasan yang sama. Atur cara yang meringkaskan data yang panjangnya boleh berubah mesti meletakkan panjang itu dalam mesej, meringkaskan pengekodan berpanjang tetap, atau memanggil POSEIDON2_LEN, yang menyemai n ke dalam kapasiti span dan memberikan ringkasan yang berbeza bagi perkataan yang sama. Dalam SDK Rust, poseidon2 ialah unsafe fn ke atas penuding mentah dan poseidon2_len ialah panggilan selamat ke atas hirisan; keccak dan sha256_compress menerima &mut [u32; 50] dan &mut [u32; 24].

Satu jurang rantaian alat. Pada circuits aeacf31, mesin, emulator dan SDK Rust melaksanakan syscall 7, tetapi rand-guest check tidak: senarai syscall-nya berhenti pada 6, jadi ia melaporkan ecall dengan a7 = 7 sebagai dapatan Syscall dan rand-guest build keluar dengan kod bukan sifar pada guest yang memanggil poseidon2_len (circuits issue #1). guest.h juga tidak mempunyai pembungkus untuknya. Sehingga ini dibaiki, guest yang dibina dengan alat stok menggunakan POSEIDON2 pada mesej berpanjang tetap.

Satu bukti menerbitkan tepat perkara ini: hc, H_IN, H_PUB, tier, had gas yang diisytiharkan, dan lapan perkataan output. Dua had berlaku pada chain hari ini:

  • Segmen awam ditetapkan semasa penyebaran. Pada chain 20, rand program deploy --public menetapkan perkataan awam sesuatu atur cara (paling banyak max_program_public_words, 32,768), dan setiap panggilan disemak terhadapnya. Tiada perkataan awam bagi setiap panggilan yang dimiliki oleh atur cara itu sendiri. Chain 20, seperti chain 19, menambahkan lapan perkataan pada segmen setiap panggilan selepas perkataan tersebut, iaitu pengikatan panggilan yang mengaitkan bukti dengan transaksinya (pada chain 20 ia turut merangkumi cincang genesis); guest membaca perkataannya sendiri pada indeks yang sama seperti sebelumnya. Invoke RPL-2 menambahkan peralihan yang diisytiharkan selepas pengikatan itu, yang dibaca oleh atur cara dari public_len + 8 seterusnya (Programs). Pada chain tanpa medan had, seperti chain 12, segmen awam kosong dan READ_PUBLIC tiada apa-apa untuk dibaca.
  • Perkataan input persendirian bagi sesuatu panggilan dihadkan oleh sampul termeterai. max_call_envelope_bytes chain 20 sebanyak 65,536 membenarkan 16,071 perkataan; chain tanpa medan itu membenarkan 4,295.

Panggilan KECCAK atau SHA256 menambah satu jadual pada bukti, dan pengepala bukti kemudian menunjukkan bahawa panggilan itu meringkaskan. Bukti yang membawa keccak berukuran kira-kira 3.3 MB: melebihi had bukti lalai 2 MiB, di bawah 4 MiB milik chain 20, dan satu panggilan boleh menggunakan paling banyak 128 pilih atur Keccak-f dan 128 mampatan SHA-256 (Programs).

Memori

  • 32 daftar; x0 ialah sifar.
  • RAM bermula pada sifar. Setiap alamat berada di bawah 2³⁰.
  • Skrip pemaut lalai, guest-sdk/guest.ld, meletakkan atur cara pada 0x1000, kemudian .rodata, .data dan .bss, kemudian tindanan 64 KiB pada __stack_top.
  • Atur cara yang mempunyai segmen data memerlukan ruang di bawah teksnya untuk prolog pemuat (bahagian seterusnya). .ld miliknya sendiri menaikkan ORIGIN kepada 0x10000, seperti yang dilakukan oleh evm.ld dan sbpf.ld.

Bekas imej

rand-guest build dan rand-guest pack menulis satu format fail, iaitu bekas imej. Semua nombor ialah perkataan 32-bit little-endian:

[0x444e4152 ("RAND"), 1, text_base, n_text, data_base, n_data] text… data…

Pemuat menukar bekas itu menjadi atur cara { base_pc, words }:

  1. Ia menulis pasangan li/sw bagi setiap perkataan data bukan sifar. Perkataan sifar dilangkau, kerana RAM sudah dibaca sebagai sifar.
  2. Ia meletakkan prolog itu terus di bawah text_base, jadi base_pc = text_base − 4 × prologue words. Prolog itu jatuh terus ke _start milik atur cara itu sendiri.
  3. hc dan id atur cara dikira ke atas seluruh words, termasuk prolog. Jadi hc mengikat data serta kod.

Bekas tanpa data tidak menghasilkan prolog, dan menghasilkan atur cara serta hc yang sama seperti binari rata tanpa pengepala pada tapak yang sama.

rand program deploy dalam fullnode v0.3 dan ke atas mengenali bekas itu melalui perkataan pertamanya. 0x444e4152 tidak pernah dinyahkod sebagai arahan, maka .bin mentah tidak boleh tersilap dianggap sebagai bekas. Fail yang bermula dengan nombor ajaib tetapi cacat ialah ralat, bukan sandaran.

Dua identiti

namamaksudnyasiapa yang menggunakannya
hcdigest Poseidon2 litar bagi (base_pc, len, words)setiap bukti panggilan disahkan terhadapnya; rand_getProgram memaparkannya sebagai code_hash
program idblake3("rand-program" ‖ base_pc ‖ words); pelaksanaan dengan --public turut mengikat perkataan awam, di bawah teg rand-program-2kunci yang digunakan untuk menyimpan dan memanggil program yang telah dilaksanakan

rand-guest build dan rand-guest info mencetak kedua-duanya. hc bersifat mengikat tetapi tidak menyembunyikan: sesiapa yang mempunyai program calon boleh mengesahkannya.

Had program

Satu deploy boleh membawa paling banyak sejumlah had program rantaian, dalam perkataan.

rantaianhad
genesis tanpa max_program_words (chain 12)4,096
genesis dengan max_program_wordsnilai tersebut, 1..=65535
had keras zkVM, mana-mana rantaian65,535

Had ini sebahagian daripada hash genesis, jadi ia tidak boleh diubah pada rantaian yang sedang berjalan. rand-guest menyemak terhadap --max-words (lalai 4,096). rand program deploy bertanya kepada nod dengan rand_estimateFee dan menolak program yang melebihi had sebelum membuktikan apa-apa.

Chain 20, rantaian yang sedang beroperasi, menaikkan had ini. Hash genesisnya ialah 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135 dan max_program_wordsnya ialah 65,535. Ia mengekalkan had yang diperkenalkan oleh chain 13 (rantaian v0.4), kecuali had bukti, yang dikurangkan separuh oleh chain 17 hingga 20. Had lainnya:

hadchain 20
max_proof_bytes4,194,304 (4 MiB); 8 MiB pada chain 13 hingga 16
max_block_bytes20,971,520 (20 MiB)
max_call_envelope_bytes65,536
max_program_public_words32,768

Pada chain 20, seperti pada chain 19, had perkataan bukanlah had yang mengikat. Genesisnya menetapkan hardening_v6, yang mana deploy ditolak (ProgramUncallable) apabila tiada panggilan yang dapat membuktikan program itu. Sesuatu panggilan dihadkan pada tier 14, yang jadual Poseidon2-nya memuatkan 2,048 permutasi. Digest program mengambil satu bagi setiap empat perkataan, baris salt input satu dan lapan perkataan pengikat panggilan dua, yang meninggalkan 2,045: 8,180 perkataan bagi program tanpa input awam, dan lebih sedikit apabila ada input awam (8,168 dengan sembilan perkataan awam). Kumpulan transaksi setiap nod menolak deploy sedemikian pada mana-mana rantaian.

Pengagregatan blok dimatikan pada chain 20: genesisnya tidak mempunyai bahagian aggregation. Chain 20 beroperasi sejak 2026-10-01 06:17 UTC pada fullnode v0.6.8, satu hard fork yang dipotong daripada keadaan chain 19 pada ketinggian 7,258 (chain 19 berhenti pada 7,700); chain 19 (beroperasi sejak 03:43 UTC pada hari yang sama) sendiri merupakan re-genesis bagi chain 18 pada ketinggian 141,935. Program tidak dibawa merentasi pemotongan, jadi tiada program yang dilaksanakan pada rantaian terdahulu wujud pada chain 20. Chain 20 juga rantaian pertama dengan keadaan program RPL-2 (Atur cara). Ia berjalan pada rangkaian melalui nod bootstrap berikut:

/ip4/164.90.239.200/tcp/30303/p2p/12D3KooWEQEbUwZRgqhDPXhW7vNBmcRcnhUDGUADe81VFdv3ALYe
/ip4/165.245.173.74/tcp/30303/p2p/12D3KooWJyc5oDHggAr89e9QrRFBy9Tg8TxXh18yzrb1SM6KKLYw
/ip4/188.166.235.187/tcp/30303/p2p/12D3KooWSyX84P1DAbWByLHpRBMLRWD53r3Jj4aqVt6tHoF8B2ZQ
imejperkataanmuat 4,096muat 65,535dilaksanakan pada chain 20 (8,180 boleh dipanggil)
fib (Rust)26yayaya
c-fib (C)25yayaya
ERC-20, diterjemahkan (peringkat kedua)11,686tidakyatidak
evm.bin, pentafsir EVM18,009tidakyatidak
sbpf.bin, pentafsir sBPF8,317tidakyatidak
SPL Token, diterjemahkan65,096tidakya, dengan baki 439tidak

Tier

Tier t sesuatu bukti mengehadkan larian pada 2ᵗ − 1 baris: kitaran ditambah baris digest (satu bagi setiap empat perkataan program, satu bagi setiap empat perkataan input, dan digest input awam). Tier itu juga menetapkan belanjawan Poseidon2 yang berasingan. rand-guest run --tier t melaporkan kedua-duanya:

tier 10: fits (cycles 146 of 1023, Poseidon2 permutations 10 of 128)

Tier itu awam, begitu juga had gas yang diisytiharkan oleh bukti. Pada chain 20, yuran panggilan mengikut had itu dan saiz bukti, bukan tier: sekurang-kurangnya 0.001 RAND + gas_price × gas_limit + byte_price × ⌈bytes / 1024⌉, pada harga semasa rantaian, yang bermula pada 100 dan 800 unit 10⁻⁹ RAND, berubah mengikut kepenuhan blok dan pada chain 20 berhenti pada 10,000 dan 80,000 unit (Yuran). Had tidak boleh melebihi siling pengepala, (2ᵗ − 1) + 2ᵗ⁻² ditambah 191 bagi setiap blok Keccak dan 63 bagi setiap blok SHA-256 yang diisytiharkan bukti: 1,279 pada tier 10 dan 20,479 pada tier 14 tanpa jadual hash. rand-guest run melaporkan kitaran dan permutasi, bukan gas. rand call menjalankan program terlebih dahulu dan mencetak gas yang digunakannya serta had yang diisytiharkannya, secara lalai gas tepat dibundarkan ke atas kepada gandaan 2ᵗ⁻² yang seterusnya, sebelum membuktikan:

gas: 5636 (declaring 6144, tier 12)

Baris itu datang daripada satu panggilan pada chain 18 pada 2026-09-30 (Undian tanpa nama). Pada rantaian tanpa bahagian gas genesis, chain 15 dan terdahulu, yuran ialah jadual tier: 0.001 + (0.001 + 0.0001 × (t − 10) / 2) RAND. Memori yang diperlukan sesuatu bukti meningkat dengan curam mengikut tier; lihat Perkakasan validator dan agregator.

Sejak fullnode v0.5.6 (2026-09-25), sesuatu panggilan boleh mengisytiharkan paling tinggi tier 14: nod menolak bukti panggilan tier yang lebih tinggi dengan CallTierTooHigh sebelum membina kunci pengesah, dan blok yang membawanya tidak sah. Belanjawan tier 14 ialah 16,383 baris dan 2,048 permutasi Poseidon2, dan digest program itu sendiri menggunakan kira-kira satu permutasi bagi setiap empat perkataan, jadi program melebihi 8,180 perkataan tidak boleh dipanggil, dan chain 20, seperti chain 19, menolak deploynya. Menulis program dalam Rust atau C menghuraikan belanjawan ini.

Disahkan kali terakhir terhadap commit fullnode c0878c3f (rantai 21) pada 2026-10-12, dan circuits `aeacf31` (`rand-guest/README.md`, `rand-guest/src/check.rs`, `research/docs/01-isa.md`, `guest-sdk/`), fullnode tag v0.6.8 `c9c9bd3c` (`docs/program-state.md`, `ledger/program_state.rs`, `deploy/cut-chain20-genesis.sh`), chain 20's genesis and `rand_getLimits`, read on 2026-10-01, fullnode tag v0.8.0 `c0878c3f` (`docs/zkvm.md` §8a, constraint set 9), `deploy/genesis-chain21.json` and `rand_getLimits` on chain 21, read on 2026-10-12. Jika kod dan halaman ini tidak selari, kodlah yang betul; sila maklumkan kepada kami.