Rand Protocol
Dokumentasi
Program RISC-V

Transpiler Solana

sbpf2rv menerjemahkan program Solana sBPF ke dalam RISC-V ISA milik Rand - apa itu sbpf2rv, model kepercayaan beserta penjaga ELF-nya, apa yang memicu trap dan apa yang ditolak, angka-angka hasil pengukuran, serta panduan lengkap yang menerjemahkan program SPL Token yang sesungguhnya dan cocok dengan interpreter sBPF kata demi kata.

sbpf2rv mengambil program Solana yang telah dikompilasi (ELF sBPF, yaitu berkas .so yang dihasilkan cargo build-sbf) dan mengubahnya menjadi program Rand. Alat ini menulis C, dan rand-guest build mengompilasi C tersebut menjadi image RV32IM. Image tersebut menerbitkan delapan kata keluaran yang sama dengan guest interpreter sBPF milik Rand, sbpf.bin, untuk ELF dan instruksi yang sama. Halaman ini menunjukkan seluruh alurnya pada program SPL Token yang sebenarnya.

Apa itu

masukansebuah ELF sBPF v1
keluaransebuah crate shim C; rand-guest build mengubahnya menjadi kontainer image
tempat berjalandi luar rantai, pada mesin pengembang; rantai hanya melihat image-nya
yang harus dicocokkandelapan kata keluaran sbpf.bin, pada dua pita masukan yang sama
repositorisbpf2rv/ di repositori circuits
toolchain yang dipatokRust 1.98.1, clang 23.1.1, crate cc 1.4.6

Program hasil terjemahan mempertahankan ABI interpreter. Program ini membaca pita yang sama: ELF pada pita publik dan instruksi yang diserialisasi (akun, lalu data instruksi) pada pita privat. Program ini menjalankan harness sbpf-core yang sama di sekeliling program: mendekode masukan, memuat ELF, memeriksa wilayah akun, dan menghitung hash masukan serta keluaran. Hanya eksekusi sBPF itu sendiri yang digantikan oleh kode native. Itulah sebabnya keluarannya sama dengan keluaran interpreter kata demi kata.

Model kepercayaan

Tiga hal mengikat bukti dari program hasil terjemahan.

  1. hc mengikat kode hasil terjemahan. C dikompilasi ke dalam image, sehingga hc milik image mencakupnya.
  2. Penjaga ELF mengikat hc pada satu program. Shim memuat program dari ELF pada pita, sehingga tanpa pemeriksaan, satu image dapat menjalankan ELF lain yang dipilih penelepon di bawah hc yang sama. Karena itu program.c yang dihasilkan diakhiri dengan digest dari program termuat yang menjadi sumber terjemahannya: teks, data hanya-baca, alamat keduanya, dan titik masuk. Sebelum menjalankan apa pun, shim menghitung hash program termuat pada pita dengan cara yang sama (Poseidon2) dan membandingkannya. Program lain akan dihentikan dengan BadElf, status 2, di atas pra-status. Jadi bukti yang terverifikasi terhadap hc ini adalah hasil eksekusi program tersebut.
  3. H_PUB mengikat byte ELF. ELF dikirim pada pita publik, dan digest masukan publik dari bukti mencakupnya kata demi kata.

Apakah hc merupakan terjemahan yang setia dari suatu ELF diperiksa dengan membangun ulang. Jalankan sbpf2rv yang dipatok pada ELF tersebut, bangun dengan toolchain yang dipatok, lalu bandingkan hc. Karena alasan inilah build-nya dapat direproduksi.

Rantai tidak mencatat ELF sumber maupun hash-nya. Rantai menyimpan image dan id programnya. Pengembang yang ingin ELF-nya diketahui publik menerbitkannya di samping program.

Penjaga mengikat program termuat, bukan berkasnya. Dua ELF yang berbeda hanya pada bagian yang tidak dilihat loader (padding header, tabel simbol) dimuat menjadi program yang sama dan berjalan identik di kedua sisi. ELF dengan satu byte .rodata yang diubah, bahkan byte yang tidak pernah dibaca oleh transfer, ditolak oleh terjemahan dan dijalankan oleh interpreter.

Apa yang menyebabkan trap dan apa yang ditolak

Tidak ada yang ditolak saat penerjemahan. ELF yang cacat ditolak dengan pesan milik loader sendiri, tetapi tidak ada instruksi dalam ELF yang tertata baik yang ditolak. Pemindai melaporkan apa yang dapat dijumpai suatu program sebagai peringatan, dan program hasil terjemahan melakukan trap saat dijalankan tepat di tempat interpreter melakukannya:

peringatanapa itusaat dijalankan
UnknownSyscallhash syscall yang tidak diimplementasikan runtimetrap UnknownSyscall
Cpipemanggilan lintas program (sol_invoke_signed*)trap UnknownSyscall yang sama; CPI tidak diimplementasikan
RegisterOutOfRangeregister r11..r15, atau register callx di atas r10trap BadInsn
UnknownOpcodeopcode tanpa kelas v1, termasuk keluarga sdiv/srem khusus v2 dan hor64trap BadInsn
JumpOutOfTextlompatan, pemanggilan, atau fall-through di luar teks fungsitrap BadJump
BadCallImmSrccall imm dengan src dalam 2..=10 (hanya pada ELF yang dibuat manual)trap BadInsn

Penerjemah yang menolak kode yang tidak pernah dijangkau akan menolak program yang saat ini dijalankan interpreter. SPL Token adalah program semacam itu: program ini memanggil sol_set_return_data dan sol_get_sysvar, yang tidak pernah dijangkau oleh jalur Transfer.

Tiga divergensi diterima. Masing-masing hanya membuat terjemahan berhenti di tempat yang mungkin tidak menghentikan interpreter; terjemahan tidak pernah menyelesaikan eksekusi yang dihentikan interpreter.

  1. callx di luar himpunan yang dipindai melakukan trap BadJump, padahal interpreter mungkin menjalankan kode sungguhan pada alamat tersebut.
  2. Pemeriksaan anggaran dapat ditunda satu basic block. Agar SPL Token muat di bawah batas 65.535 kata, 1.505 dari 3.546 block-nya melewati pemeriksaan batas instruksinya sendiri. Jenis penghentian dapat berbeda di dalam satu block yang melintasi batas. Status dan kedelapan katanya sama.
  3. Hanya program sumber yang berjalan. ELF lain ditolak (penjaga, di atas).

Ed25519 dan secp256k1. Implementasi perangkat lunak sol_ed25519_verify dan sol_secp256k1_recover ada di sbpf-rt/ tetapi tidak ditautkan. Interpreter melakukan trap pada keduanya, sehingga demi paritas terjemahan pun melakukan trap. Setiap pemanggilan menghabiskan sekitar 14,3 juta dan 15,7 juta siklus secara berturut-turut, jauh di atas tier terbesar (2²⁰). Keduanya memerlukan tabel koprosesor.

Angka-angkanya

Diukur pada SPL Token (guests-compiled/sbpf/programs/spl_token.so, fixture uji milik interpreter sendiri), dengan penjaga ELF terpasang.

imagekata programbatashc
SPL Token, hasil terjemahan65.09665.535 (sisa 439)8ca905ae…758b
sbpf.bin, interpreter8.31765.535059a7086…f476
vektorstatusinstruksi sBPFsiklus hasil terjemahansiklus sbpf.bintier (keduanya)
Transfer 2501143765.851694.49820
Transfer melebihi saldo0133748.836679.81420
MintTo 2501120708.648634.42320
MintTo oleh otoritas yang salah0134696.694627.24120
Burn 2501131710.245637.03820
Burn melebihi saldo0121695.434624.78120
Transfer dengan dua akun069645.015569.65620
terlalu banyak akun (harness menolak)20303.933304.61620

Ke mana siklus digunakan pada Transfer:

tahaphasil terjemahansbpf.bin
membaca kedua pita302.881302.880
memuat ELF177.012173.859
memeriksa wilayah akun103.829103.824
mengosongkan stack dan heap sBPF49.18149.181
hash keluaran dan masukan, kata publik, glue51.09142.723
penjaga ELF72.949—
program sBPF itu sendiri8.90822.031
total765.851694.498

Eksekusi program hasil terjemahan sekitar 2,4 hingga 2,5 kali lebih murah per instruksi sBPF (sekitar 62 siklus berbanding 154). Namun sekitar 98% dari setiap eksekusi adalah harness tetap, dan penjaga menambahkan 73 ribu siklus. Jadi untuk SPL Token, image hasil terjemahan lebih mahal 69 ribu hingga 75 ribu siklus, dan keduanya tetap berada di tier 20.

Penerjemahan hanya bermanfaat untuk program yang padat komputasi. Dengan penghematan sekitar 90 siklus per instruksi, pemanggilan yang mengeksekusi 10.000 instruksi sBPF menghemat sekitar 0,9 juta siklus. SPL Token mengeksekusi 120 hingga 143.

Panduan langkah demi langkah: SPL Token, diterjemahkan dan dicocokkan

Setiap perintah dijalankan dari root checkout circuits pada 7ef3220, dengan toolchain dari Deploy a Rust program dan clang 23.1.1 dari Deploy a RISC-V program. Keluaran yang panjang dipotong pada bagian yang ditandai ….

0. Bangun alat-alatnya

(cd sbpf2rv && cargo +1.98.1 build --release)
(cd rand-guest && cargo +1.98.1 build --release)

1. Terjemahkan

--out harus berupa direktori di dalam checkout circuits.

$ sbpf2rv/target/release/sbpf2rv guests-compiled/sbpf/programs/spl_token.so --out sbpf2rv/target/spl-token --name spl-token
entry pc 225: 30 function(s), 3546 block(s), 12061 instruction(s), 30 callx target(s), 0 refusal(s), 4 warning(s)
  fn 225: 2065 block(s)
  …                                                (30 functions in all)
  warning: UnknownSyscall { pc: 7803, hash: 2720453611 }
  warning: UnknownSyscall { pc: 9530, hash: 2720453611 }
  warning: UnknownSyscall { pc: 8698, hash: 2720453611 }
  warning: UnknownSyscall { pc: 11547, hash: 331461893 }
wrote sbpf2rv/target/spl-token/program.c (521757 bytes of C) and the spl-token shim crate: rand-guest build sbpf2rv/target/spl-token

0 refusal(s). Keempat peringatan itu adalah syscall nyata yang tidak pernah dijangkau Transfer: hash 2720453611 adalah sol_set_return_data (tiga lokasi pemanggilan) dan 331461893 adalah sol_get_sysvar.

2. Bangun image

Image melebihi batas bawaan 4.096 kata, jadi berikan --max-words 65535.

$ rand-guest/target/release/rand-guest build sbpf2rv/target/spl-token --max-words 65535
…
65096 words against a cap of 65535 (fits); 2 ecall(s) with a non-static a7
OK
wrote sbpf2rv/target/spl-token/image.bin and its .sha256 (65096 words, hc 8ca905ae3c62f503de7de86829040f323e098b53dba5fffe09b42f1aad16758b, program id 65d234ce9ca4d082f487c038abfa76e67f41a0d91e10b9ac388f1e1541d59184)

$ rand-guest/target/release/rand-guest info sbpf2rv/target/spl-token/image.bin
form: image container
text 64819 words at 0x10000; data 102 words (101 non-zero) at 0x4f4cc; prologue 277 words; program 65096 words from base_pc 0xfbac
hc 8ca905ae3c62f503de7de86829040f323e098b53dba5fffe09b42f1aad16758b
program id 65d234ce9ca4d082f487c038abfa76e67f41a0d91e10b9ac388f1e1541d59184
65096 words against a cap of 4096: does not fit

Siapa pun yang menjalankan kedua langkah ini dengan toolchain yang sama akan mendapatkan hc ini.

3. Jalankan keduanya, lalu bandingkan

Transfer sebesar 250 membutuhkan dua daftar kata, yang dibangun oleh tests/parity.rs dari pengodean pemanggilan milik interpreter sendiri: 27.151 kata publik (ELF, dikodekan dalam kata) dan 10.458 kata privat (akun, lalu diskriminan dan jumlah Transfer). rand-guest run menerimanya sebagai --public dan --input. Dipersingkat menjadi kata-kata pertama dari masing-masing daftar:

$ rand-guest run sbpf2rv/target/spl-token/image.bin \
    --public 108600 1179403647 65794 0 0 17235971 1 2088 …   (27 151 words)
    --input  41825 4 0 65791 0 50529027 50529027 50529027 …  (10 458 words)
out[0] = 1
out[1] = 2892832079
out[2] = 376091303
out[3] = 1311040261
out[4] = 2015764099
out[5] = 3682593600
out[6] = 3311553006
out[7] = 141115266
cycles 765851
tier 20

Kedua daftar yang sama terhadap guest interpreter:

$ rand-guest run guests-compiled/bin/sbpf.bin \
    --public 108600 1179403647 65794 0 0 17235971 1 2088 …   (27 151 words)
    --input  41825 4 0 65791 0 50529027 50529027 50529027 …  (10 458 words)
out[0] = 1
out[1] = 2892832079
out[2] = 376091303
out[3] = 1311040261
out[4] = 2015764099
out[5] = 3682593600
out[6] = 3311553006
out[7] = 141115266
cycles 694498
tier 20

Kedelapan kata identik. out[0] = 1 adalah status (berhasil). out[1..8] adalah digest yang didefinisikan ABI interpreter atas masukan dan keluaran.

4. Periksa kedelapan vektor dengan satu perintah

Uji paritas membangun image hasil terjemahan, menjalankan setiap vektor melalui rand-guest run pada kedua image, dan gagal pada setiap perbedaan di kedelapan kata:

$ cd sbpf2rv && cargo +1.98.1 test --test parity the_spl_token -- --nocapture
…
translated SPL Token: 65096 program words (cap 65 535), hc 8ca905ae3c62f503de7de86829040f323e098b53dba5fffe09b42f1aad16758b
transfer 250: Ok(0), status 1; cycles translated 765851, interpreter guest 694498
transfer too much: Ok(1), status 0; cycles translated 748836, interpreter guest 679814
MintTo 250: Ok(0), status 1; cycles translated 708648, interpreter guest 634423
MintTo 250 signed by someone else: Ok(4), status 0; cycles translated 696694, interpreter guest 627241
Burn 250: Ok(0), status 1; cycles translated 710245, interpreter guest 637038
Burn 1 000 001 (balance 1 000 000): Ok(1), status 0; cycles translated 695434, interpreter guest 624781
transfer with two accounts: Ok(47244640256), status 0; cycles translated 645015, interpreter guest 569656
an account count above MAX_ACCOUNTS: Err(BadElf), status 2; cycles translated 303933, interpreter guest 304616
…
test the_spl_token_transfer_translates_and_matches_the_interpreter_word_for_word ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 8 filtered out; finished in 27.84s

5. Deploy

rand program deploy sbpf2rv/target/spl-token/image.bin --public spl_token.so

Image membaca ELF dari tape publik, sehingga ELF menjadi input publik program, yang ditetapkan saat deploy. --public menerima berkas .so itu sendiri; wallet mengodekan berkas tersebut menjadi kata (word) yang sama sebanyak 27,151 kata seperti pada langkah 4.

Hal ini memerlukan chain yang genesis-nya menetapkan max_program_words setidaknya 65,096 dan max_program_public_words setidaknya 27,151. Chain 12 membatasi deploy pada 4,096 kata dan tidak menerima input publik, sehingga wallet menolak image ini di sana sebelum membuktikan apa pun. Chain 13, chain v0.4, menetapkan 65,535 dan 32,768, dan setiap chain sesudahnya mempertahankan kedua nilai tersebut. Chain 20, chain yang aktif (genesis 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135), juga mempertahankan batas blok dan batas call-envelope milik chain 13, serta memangkas batas proof menjadi setengahnya, yakni 4 MiB (4,194,304 byte, sejak chain 17; chain 13 hingga 16 menetapkan 8 MiB). Batas ukuran bukan lagi satu-satunya penghalang. Genesis chain 20 menetapkan hardening_v6, dan di bawahnya deploy dengan jumlah kata program yang lebih besar daripada yang dapat dimuat sebuah call pada batas call tier-14 dinyatakan tidak valid (ProgramUncallable): paling banyak 8,180 kata tanpa input publik, lebih sedikit bila disertai input publik. Image ini berukuran 65,096 kata dengan input publik 27,151 kata, sehingga chain 20 menolak deploy-nya, dan akan menolak call-nya juga: setiap vektor SPL berjalan pada tier 20, di atas batas call tier-14 (Batasan). Agregasi blok nonaktif pada chain 20 (genesis-nya tidak memiliki bagian aggregation); node bootstrap-nya tercantum di Menjalankan validator. Biaya deploy menghitung kata publik bersama kata kode: 0.001 + 0.0001 × (65,096 + 27,151) = 9.2257 RAND, biaya yang dibayar oleh deploy chain 13 di bawah ini.

Deploy ini dijalankan di chain 13 pada 2026-09-19, ketika chain 13 menjadi chain yang aktif (profil FRI produksi, genesis 8123ccac1883a45750e4df6964fb7cd3f0b321798cde4c0ef406a0293939ece3), dari wallet genesis shielded-1. Setiap chain sesudahnya (14 hingga 19) dibuat sebagai chain baru tanpa program milik chain 13, dan image ini belum dideploy ulang di salah satunya, sehingga transaksi dan tinggi blok di bawah ini milik chain 13 dan tidak lagi dapat ditemukan di explorer. Program id adalah hash dari base_pc, kata-kata, dan kata publik saja, sehingga image dan ELF yang sama mendapatkan id yang sama pada chain mana pun yang menerima deploy tersebut. Keluaran wallet, dengan baris progresnya dihilangkan (…):

$ rand program deploy <image.bin> --public spl_token.so
program id: 740236918310f8e52bb0c1ef49b2b0e0c018762e289666660685b0694c8dd00a (65096 words, hc ae05a98c03f5623c68e87dde320f0429538b093efeffa5db1a2fb4098b7516ad, public input 27151 words, digest ec57b10ed6f3a3d5fe87ec072f691322ad747377ba2f0a1788bcfe3e7334d67e)
…
proved in 94.3s: tier 14, 1418406 bytes
submitted deploy 626fc9387ecc1f6b39f44184807303ac2843029d8fb8e28338bf186445927530
…
program id740236918310f8e52bb0c1ef49b2b0e0c018762e289666660685b0694c8dd00a
image65,096 kata; hc 8ca905ae… dalam penulisan rand-guest, ae05a98c… dalam penulisan wallet
input publik27,151 kata (ELF), digest ec57b10ed6f3a3d5fe87ec072f691322ad747377ba2f0a1788bcfe3e7334d67e
bundel biaya (bundel 2-in-2-out milik chain 13)tier 14, 1,418,406 byte, dibuktikan dalam 94.3 s
tx deploy (chain 13)626fc9387ecc1f6b39f44184807303ac2843029d8fb8e28338bf186445927530
di-anchor pada tinggi (chain 13)400
biaya9.2257 RAND

Sejak chain 14, bundel pembayar adalah satu bundel hidden-asset 4-in-4-out yang dibawa setiap transaksi, dibuktikan terhadap binding transaksi. Bundel ini masih tier 14: sekitar 100 s dan sekitar 1.42 MB pada profil produksi di chain 14 dan 15. Sejak chain 17, sebuah bundel juga membawa proof auth tier-10 (otorisasi terpisah), sehingga pada chain 18 dan 19 bundel biaya sebuah transaksi berukuran sekitar 1.49 MB proof bundel dan sekitar 1.37 MB proof auth.

Program id mengikat ELF, sehingga berbeda dari id yang dicetak rand-guest info untuk image kosong. Panggil id yang dicetak oleh deploy.

Batasan

  • Tidak ada call ke program ini yang pernah dibuktikan, program ini tidak dideploy di chain 20, dan chain 20 menolak deploy maupun call-nya. Deploy di atas dijalankan di chain 13. Di bawah hardening_v6 milik chain 20, deploy dengan kata yang lebih banyak daripada yang dapat dimuat call tier-14 dinyatakan tidak valid (ProgramUncallable; paling banyak 8,180 kata), sedangkan image ini berukuran 65,096. Sisi input masih akan muat: ELF adalah input publik deploy, yang diambil sendiri oleh rand call, dan 10,458 kata privat muat dalam batas input 16,071, yang dipertahankan chain 20. Namun setiap vektor SPL berada pada tier 20, dan sejak fullnode v0.5.6 (2026-09-25) sebuah node menolak setiap proof call di atas tier 14 (CallTierTooHigh), sebelum membangun verifier key. Pemeriksaan yang sama juga membatasi tabel hash yang boleh dideklarasikan sebuah call: 2¹³ baris SHA-256 (128 kompresi) dan 2¹² baris Keccak (128 permutasi). Call tier-20 hanya dapat dibuktikan di luar chain, dan belum ada proof tier-20 yang tersedia (poin berikutnya).
  • Belum ada proof yang dibuat pada tier 20. Proof tier-20 dihentikan paksa pada laptop 48 GB di sekitar 31 GB, dan dimatikan oleh OOM pada droplet 64 GB di 65.1 GB setelah 10 m 41 s. Diekstrapolasi dari penskalaan tier-16/18 yang terukur (memori sekitar ×3.9, waktu sekitar ×4.1 per +2 tier), tier 20 membutuhkan sekitar 330 GB dan sekitar 3.6 jam — lebih dari droplet memori terbesar DigitalOcean (m-32vcpu-256gb, 256 GB). Prover berjalan dengan satu thread: kotak 16-vCPU berada pada 99% dari satu core. Lihat memori pembuktian.
  • Tidak ada CPI. Cross-program invocation menyebabkan trap.
  • Hanya sBPF v1. Opcode khusus v2 menyebabkan trap.
  • Syscall Ed25519 dan secp256k1 menyebabkan trap hingga tersedia tabel koprosesor untuknya.
  • Chain hanya mencatat ELF sebagai input publik. Deploy dengan --public menyimpan kata-kata ELF dan digest-nya, dan rand_getProgramPublic menyajikannya. Chain tidak mencatat bagaimana image dibangun darinya: publikasikan input build agar pihak lain dapat membangun ulang hc.

Terakhir diverifikasi terhadap commit fullnode c0878c3f (chain 21) pada 2026-10-12, dan circuits `7ef3220` (`sbpf2rv/README.md`, `docs/superpowers/specs/2026-09-18-sbpf-to-rv32-translator-design.md`); steps 1, 2 and the parity test re-run on 2026-09-19. Jika kode dan halaman ini tidak sesuai, kodelah yang benar; beri tahu kami.