Rand Protocol
Dokumentasi
Program RISC-V

Penranslasi Solana

sbpf2rv menterjemahkan program Solana sBPF kepada ISA RISC-V milik Rand - apakah ia, model kepercayaan dan pengawal ELF-nya, perkara yang menyebabkan perangkapan dan perkara yang ditolak, angka yang diukur, serta panduan lengkap yang menterjemahkan program SPL Token sebenar dan sepadan dengan penterjemah sBPF perkataan demi perkataan.

sbpf2rv mengambil program Solana yang telah dikompil (ELF sBPF, iaitu .so yang dihasilkan oleh cargo build-sbf) dan menukarkannya kepada program Rand. Ia menulis C, dan rand-guest build mengompil C itu menjadi imej RV32IM. Imej tersebut menerbitkan lapan perkataan output yang sama seperti guest penterjemah sBPF Rand, sbpf.bin, bagi ELF dan arahan yang sama. Halaman ini menunjukkan keseluruhan laluan tersebut pada program SPL Token yang sebenar.

Apakah itu

inputELF sBPF v1
outputcrate shim C; rand-guest build menjadikannya bekas imej
tempat ia dijalankandi luar rantaian, pada mesin pembangun; rantaian hanya melihat imej
apa yang mesti dipadankanlapan perkataan output sbpf.bin, pada dua pita input yang sama
repositorisbpf2rv/ dalam repositori circuits
rantaian alat yang dikunciRust 1.98.1, clang 23.1.1, crate cc 1.4.6

Program yang diterjemahkan mengekalkan ABI penterjemah. Ia membaca pita yang sama: ELF pada pita awam dan arahan bersiri (akaun, kemudian data arahan) pada pita persendirian. Ia menjalankan harness sbpf-core yang sama di sekeliling program: ia menyahkod input, memuatkan ELF, menyemak rantau akaun serta mencincang input dan output. Hanya pelaksanaan sBPF itu sendiri yang digantikan dengan kod natif. Itulah sebabnya outputnya sama dengan output penterjemah perkataan demi perkataan.

Model kepercayaan

Tiga perkara mengikat bukti bagi program yang diterjemahkan.

  1. hc mengikat kod yang diterjemahkan. C itu dikompil ke dalam imej, maka hc imej meliputinya.
  2. Pengawal ELF mengikat hc kepada satu program. Shim memuatkan program daripada ELF pada pita, jadi tanpa semakan, satu imej boleh menjalankan ELF lain pilihan pemanggil di bawah hc yang sama. Oleh itu program.c yang dijana diakhiri dengan digest program termuat yang daripadanya ia diterjemahkan: teks, data baca sahaja, alamatnya dan titik masuk. Sebelum menjalankan apa-apa, shim mencincang program termuat pada pita dengan cara yang sama (Poseidon2) dan membandingkannya. Mana-mana program lain dihentikan dengan BadElf, status 2, ke atas keadaan pra. Maka bukti yang disahkan terhadap hc ini ialah larian program tersebut.
  3. H_PUB mengikat bait ELF. ELF dibawa pada pita awam, dan digest input awam bagi bukti itu meliputinya perkataan demi perkataan.

Sama ada hc ialah terjemahan yang setia bagi sesuatu ELF disemak melalui pembinaan semula. Jalankan sbpf2rv yang dikunci pada ELF itu, bina dengan rantaian alat yang dikunci, dan bandingkan hc. Binaan ini boleh dihasilkan semula atas sebab ini.

Rantaian tidak merekodkan ELF sumber atau cincangnya. Ia menyimpan imej dan id programnya. Pembangun yang mahu ELF itu diketahui umum menerbitkannya bersama program.

Pengawal mengikat program termuat, bukan fail. Dua ELF yang berbeza hanya di tempat yang tidak dilihat oleh pemuat (pelapik pengepala, jadual simbol) dimuatkan menjadi program yang sama dan berjalan secara serupa pada kedua-dua belah. ELF dengan satu bait .rodata yang diubah, walaupun bait yang tidak pernah dibaca oleh pemindahan, ditolak oleh terjemahan dan dijalankan oleh penterjemah.

Apa yang memerangkap dan apa yang ditolak

Tiada apa-apa yang ditolak semasa penterjemahan. ELF yang cacat ditolak dengan mesej pemuat sendiri, tetapi tiada arahan dalam ELF yang sempurna bentuknya ditolak. Pengimbas melaporkan apa yang boleh dicapai oleh sesebuah program sebagai amaran, dan program yang diterjemahkan memerangkap semasa larian tepat di tempat penterjemah akan berbuat demikian:

amaranapakah itusemasa larian
UnknownSyscallcincang syscall yang tidak dilaksanakan oleh runtimeperangkap UnknownSyscall
Cpipemanggilan merentas program (sol_invoke_signed*)perangkap UnknownSyscall yang sama; CPI tidak dilaksanakan
RegisterOutOfRangeregister r11..r15, atau register callx melebihi r10perangkap BadInsn
UnknownOpcodeopcode tanpa kelas v1, termasuk keluarga sdiv/srem khusus v2 dan hor64perangkap BadInsn
JumpOutOfTextlompatan, panggilan atau lalu terus di luar teks fungsiperangkap BadJump
BadCallImmSrccall imm dengan src dalam 2..=10 (hanya dalam ELF yang dibina secara manual)perangkap BadInsn

Penterjemah yang menolak kod yang tidak dicapai akan menolak program yang dijalankan oleh penterjemah hari ini. SPL Token ialah program sedemikian: ia memanggil sol_set_return_data dan sol_get_sysvar, yang tidak pernah dicapai oleh laluan Transfer.

Tiga percanggahan diterima. Setiap satunya hanya menyebabkan terjemahan berhenti di tempat penterjemah mungkin tidak berhenti; terjemahan tidak pernah melengkapkan larian yang dihentikan oleh penterjemah.

  1. callx di luar set yang diimbas memerangkap BadJump, sedangkan penterjemah mungkin menjalankan kod sebenar pada alamat itu.
  2. Semakan bajet boleh ditangguhkan satu blok asas. Untuk memuatkan SPL Token di bawah had 65,535 perkataan, 1,505 daripada 3,546 bloknya melangkau semakan had arahan masing-masing. Jenis penghentian boleh berbeza dalam satu blok yang melintasi had itu. Status dan lapan perkataan adalah sama.
  3. Hanya program sumber yang dijalankan. ELF lain ditolak (pengawal, di atas).

Ed25519 dan secp256k1. Pelaksanaan perisian bagi sol_ed25519_verify dan sol_secp256k1_recover wujud dalam sbpf-rt/ tetapi tidak dipautkan. Penterjemah memerangkap pada kedua-duanya, maka demi kesamaan, terjemahan juga memerangkap. Setiap panggilan memakan kira-kira 14.3M dan 15.7M kitaran masing-masing, jauh melebihi peringkat terbesar (2²⁰). Ia memerlukan jadual koprosesor.

Angka-angkanya

Diukur pada SPL Token (guests-compiled/sbpf/programs/spl_token.so, fixture ujian penterjemah sendiri), dengan pengawal ELF disertakan.

imejperkataan programhadhc
SPL Token, diterjemahkan65,09665,535 (439 berbaki)8ca905ae…758b
sbpf.bin, penterjemah8,31765,535059a7086…f476
vektorstatusarahan sBPFkitaran diterjemahkankitaran sbpf.binperingkat (kedua-duanya)
Transfer 2501143765,851694,49820
Transfer melebihi baki0133748,836679,81420
MintTo 2501120708,648634,42320
MintTo oleh pihak berkuasa yang salah0134696,694627,24120
Burn 2501131710,245637,03820
Burn melebihi baki0121695,434624,78120
Transfer dengan dua akaun069645,015569,65620
terlalu banyak akaun (harness menolak)20303,933304,61620

Ke mana perginya kitaran pada Transfer:

peringkatditerjemahkansbpf.bin
baca kedua-dua pita302,881302,880
muatkan ELF177,012173,859
semak rantau akaun103,829103,824
sifarkan tindanan dan heap sBPF49,18149,181
cincang output dan input, perkataan awam, glue51,09142,723
pengawal ELF72,949—
program sBPF itu sendiri8,90822,031
jumlah765,851694,498

Pelaksanaan program yang diterjemahkan itu sendiri kira-kira 2.4 hingga 2.5 kali lebih murah bagi setiap arahan sBPF (kira-kira 62 kitaran berbanding 154). Tetapi kira-kira 98% daripada setiap larian ialah harness tetap, dan pengawal menambah 73k kitaran. Maka bagi SPL Token, imej yang diterjemahkan lebih mahal sebanyak 69k hingga 75k kitaran, dan kedua-duanya kekal pada peringkat 20.

Penterjemahan hanya berbaloi untuk program yang berat dari segi pengiraan. Pada kira-kira 90 kitaran yang dijimatkan bagi setiap arahan, panggilan yang melaksanakan 10,000 arahan sBPF menjimatkan kira-kira 0.9M kitaran. SPL Token melaksanakan 120 hingga 143.

Panduan langkah demi langkah: SPL Token, diterjemahkan dan dipadankan

Setiap arahan dijalankan dari akar checkout circuits pada 7ef3220, dengan rantaian alat daripada Deploy a Rust program dan clang 23.1.1 daripada Deploy a RISC-V program. Output yang panjang dipotong di tempat bertanda ….

0. Bina alat

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

1. Terjemah

--out mestilah 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). Empat amaran itu ialah syscall sebenar yang tidak pernah dicapai oleh Transfer: cincang 2720453611 ialah sol_set_return_data (tiga tapak panggilan) dan 331461893 ialah sol_get_sysvar.

2. Bina imej

Imej ini melebihi had lalai 4,096 perkataan, maka 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

Sesiapa yang menjalankan kedua-dua langkah ini dengan rantaian alat yang sama akan memperoleh hc ini.

3. Jalankan kedua-duanya, dan bandingkan

Transfer sebanyak 250 mengambil dua senarai perkataan, yang dibina oleh tests/parity.rs daripada pengekodan panggilan penterjemah sendiri: 27,151 perkataan awam (ELF, dikodkan sebagai perkataan) dan 10,458 perkataan persendirian (akaun, kemudian diskriminan Transfer dan jumlah). rand-guest run menerimanya sebagai --public dan --input. Dipendekkan kepada beberapa perkataan pertama bagi setiap senarai:

$ 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

Dua senarai yang sama terhadap guest penterjemah:

$ 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

Kesemua lapan perkataan adalah serupa. out[0] = 1 ialah status (berjaya). out[1..8] ialah digest yang ditakrifkan oleh ABI penterjemah ke atas input dan output.

4. Semak kesemua lapan vektor dalam satu arahan

Ujian kesamaan membina imej yang diterjemahkan, menjalankan setiap vektor melalui rand-guest run pada kedua-dua imej, dan gagal pada sebarang perbezaan dalam lapan perkataan itu:

$ 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

Imej ini membaca ELF daripada pita awam, jadi ELF ialah input awam program yang ditetapkan semasa penempatan. --public menerima fail .so itu sendiri; dompet mengekod perkataannya kepada 27,151 perkataan yang sama seperti langkah 4.

Ini memerlukan rantaian yang genesisnya menetapkan max_program_words sekurang-kurangnya 65,096 dan max_program_public_words sekurang-kurangnya 27,151. Chain 12 mengehadkan penempatan kepada 4,096 perkataan dan tidak menerima input awam, maka dompet menolak imej ini di sana sebelum sebarang pembuktian. Chain 13, rantaian v0.4, menetapkan 65,535 dan 32,768, dan setiap rantaian sejak itu mengekalkan kedua-dua nilai tersebut. Chain 20, rantaian yang sedang beroperasi (genesis 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135), turut mengekalkan had blok dan had sampul panggilan Chain 13, dan mengurangkan separuh had bukti kepada 4 MiB (4,194,304 bait, sejak chain 17; chain 13 hingga 16 menetapkan 8 MiB). Had saiz bukan lagi satu-satunya syarat. Genesis Chain 20 menetapkan hardening_v6, dan di bawahnya penempatan dengan perkataan program yang lebih banyak daripada yang dapat dimuatkan oleh satu panggilan pada had panggilan tier-14 adalah tidak sah (ProgramUncallable): paling banyak 8,180 perkataan tanpa input awam, dan lebih sedikit jika disertai input awam. Imej ini ialah 65,096 perkataan bersama input awam 27,151 perkataan, maka chain 20 menolak penempatan tersebut, dan akan menolak panggilan juga: setiap vektor SPL dijalankan pada tier 20, melebihi had panggilan tier-14 (Had). Pengagregatan blok dimatikan pada chain 20 (genesisnya tiada bahagian aggregation); nod bootstrapnya disenaraikan dalam Menjalankan validator. Yuran penempatan mengira perkataan awam bersama perkataan kod: 0.001 + 0.0001 × (65,096 + 27,151) = 9.2257 RAND, iaitu yuran yang dibayar oleh penempatan chain 13 di bawah.

Penempatan ini dijalankan pada chain 13 pada 2026-09-19, ketika chain 13 ialah rantaian yang sedang beroperasi (profil FRI pengeluaran, genesis 8123ccac1883a45750e4df6964fb7cd3f0b321798cde4c0ef406a0293939ece3), daripada dompet genesis shielded-1. Setiap rantaian sejak itu (14 hingga 19) dibina sebagai rantaian baharu tanpa program chain 13, dan imej ini belum ditempatkan semula pada mana-mana daripadanya, maka transaksi dan ketinggian di bawah adalah milik chain 13 dan tidak lagi dapat dicari di penjelajah. ID program ialah cincangan base_pc, perkataan dan perkataan awam sahaja, maka imej dan ELF yang sama mendapat ID yang sama pada mana-mana rantaian yang menerima penempatan tersebut. Output dompet, dengan baris kemajuannya dipendekkan (…):

$ 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
…
ID program740236918310f8e52bb0c1ef49b2b0e0c018762e289666660685b0694c8dd00a
imej65,096 perkataan; hc 8ca905ae… dalam ejaan rand-guest, ae05a98c… dalam ejaan dompet
input awam27,151 perkataan (ELF), digest ec57b10ed6f3a3d5fe87ec072f691322ad747377ba2f0a1788bcfe3e7334d67e
bundel yuran (bundel 2-masuk-2-keluar chain 13)tier 14, 1,418,406 bait, dibuktikan dalam 94.3 s
tx penempatan (chain 13)626fc9387ecc1f6b39f44184807303ac2843029d8fb8e28338bf186445927530
ditambatkan pada ketinggian (chain 13)400
yuran9.2257 RAND

Sejak chain 14, bundel pembayaran ialah satu bundel aset tersembunyi 4-masuk-4-keluar yang dibawa oleh setiap transaksi, dibuktikan terhadap pengikatan transaksi. Ia masih tier 14: kira-kira 100 s dan kira-kira 1.42 MB pada profil pengeluaran pada chain 14 dan 15. Sejak chain 17, sesebuah bundel turut membawa bukti auth tier-10 (pengesahan terpisah), maka pada chain 18 dan 19 bundel yuran sesebuah transaksi ialah kira-kira 1.49 MB bukti bundel dan kira-kira 1.37 MB bukti auth.

ID program mengikat ELF, maka ia berbeza daripada ID yang dicetak oleh rand-guest info untuk imej kosong. Panggil ID yang dicetak oleh deploy.

Had

  • Tiada panggilan kepada program ini yang telah dibuktikan, ia tidak ditempatkan pada chain 20, dan chain 20 menolak penempatan serta panggilan. Penempatan di atas dibuat pada chain 13. Di bawah hardening_v6 chain 20, penempatan dengan perkataan yang lebih banyak daripada yang dapat dimuatkan oleh panggilan tier-14 adalah tidak sah (ProgramUncallable; paling banyak 8,180 perkataan), dan imej ini ialah 65,096. Bahagian input akan muat: ELF ialah input awam penempatan, yang diambil sendiri oleh rand call, dan 10,458 perkataan persendirian muat dalam had input 16,071, yang dikekalkan oleh chain 20. Tetapi setiap vektor SPL ialah tier 20, dan sejak fullnode v0.5.6 (2026-09-25) nod menolak sebarang bukti panggilan di atas tier 14 (CallTierTooHigh), sebelum ia membina kunci pengesah. Semakan yang sama turut mengehadkan jadual cincangan yang boleh diisytiharkan oleh sesuatu panggilan: 2¹³ baris SHA-256 (128 pemampatan) dan 2¹² baris Keccak (128 pilih atur). Panggilan tier-20 hanya boleh dibuktikan di luar rantaian, dan belum ada bukti tier-20 (perkara seterusnya).
  • Belum ada bukti dibuat pada tier 20. Satu bukti tier-20 dimatikan pada komputer riba 48 GB pada kira-kira 31 GB, dan dimatikan oleh OOM pada droplet 64 GB pada 65.1 GB selepas 10 m 41 s. Berdasarkan ekstrapolasi skala tier-16/18 yang diukur (memori kira-kira ×3.9, masa kira-kira ×4.1 bagi setiap +2 tier), tier 20 memerlukan kira-kira 330 GB dan kira-kira 3.6 j, iaitu lebih daripada droplet memori terbesar DigitalOcean (m-32vcpu-256gb, 256 GB). Prover berjalan dengan satu thread: kotak 16-vCPU berada pada 99% satu teras. Lihat memori pembuktian.
  • Tiada CPI. Pemanggilan antara program akan trap.
  • sBPF v1 sahaja. Opcode khusus v2 akan trap.
  • Syscall Ed25519 dan secp256k1 trap sehingga ia mempunyai jadual koprosesor.
  • Rantaian merekodkan ELF hanya sebagai input awam. Penempatan dengan --public menyimpan perkataan ELF dan digestnya, dan rand_getProgramPublic menyajikannya. Rantaian tidak merekodkan bagaimana imej dibina daripadanya: terbitkan input binaan supaya pihak lain dapat membina semula hc.

Disahkan kali terakhir terhadap commit fullnode c0878c3f (rantai 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 kod dan halaman ini tidak selari, kodlah yang betul; sila maklumkan kepada kami.