Rand Protocol
لاسوندونه
RISC-V پروګرامونه

د RISC-V پروګرام ځای پر ځای کول

د Rust پرته د ځای پر ځای کېدونکي انځور (image) ته دوه لارې: یو C پروګرام چې rand-guest یې د ټاکل شوي clang په مرسته جوړوي، او یو لاسي لیکل شوی پروګرام چې اسمبل او بسته کېږي، یا د انځور په کانټینر کې بایټ په بایټ بسته کېږي.

هر هغه پروګرام چې د RV32IM ماشیني کوډ وي ځای پر ځای کېدای شي، که هر څه یې جوړ کړي وي. دا پاڼه دوه لارې ښيي: C د rand-guest build --lang c له لارې، او یو پروګرام چې تاسو یې په assembly ژبه لیکئ او پخپله یې بسته کوئ. دواړه په هماغه image container پای ته رسېږي چې د Rust پروګرام ځای پر ځای کول یې جوړوي، او دواړه د rand program deploy په واسطه ځای پر ځای کېږي. لومړی د circuits checkout او rand-guest چمتو کړئ، لکه څنګه چې د هغې پاڼې په ۱ ګام کې راغلي. د 18 تر 20 chainونو لپاره checkout په commit aeacf31 کې دی، چې fullnode v0.6.7 او v0.6.8 دواړه یې pin کوي. لاندې پایلې په 2026-09-19 د 7ef3220 پر بنسټ ترلاسه شوې او بیا نه دي چلول شوې. د rand-guest لارښود، د guest.h او rt.c په ګډون، په دواړو commitونو کې یو شان دی.

C د clang له لارې

څه ته اړتیا لرئ

وسیلهنسخهڅنګه
clang23.1.1، د RISC-V backend سرهپه macOS کې brew install llvm؛ د Apple سیستمي clang د RISC-V backend نه لري. یا $CLANG د 23.1.1 یوې باینري ته وټاکئ
rust-lldله Rust 1.98.1 څخهrustup +1.98.1 component add llvm-tools

rand-guest هر هغه clang ردوي چې نسخه یې 23.1.1 نه وي. RAND_GUEST_CLANG_UNPINNED=1 له بلې نسخې سره جوړونه کوي، د دې خبرداري سره چې hc به له خپرو شوو imageونو سره سمون ونه لري.

guest ولیکئ

د C guest لارښود یوازې .c فایلونه لري (او یو اختیاري .ld). rand-guest، guest.h، _start او یو کوچنی runtime برابروي. خپل guest.h یا start.S مه زیاتوئ: build --lang c هغه لارښود ردوي چې له دې دوو څخه یو پکې وي.

دا commit شوی guests-compiled/c-fib/fib.c دی:

#include "guest.h"

static uint32_t fib(uint32_t n) {
    uint32_t a = 0, b = 1;
    for (uint32_t i = 0; i < n; i++) {
        uint32_t c = a + b;
        a = b;
        b = c;
    }
    return a;
}

void main(void) {
    rand_write_output(0, fib(rand_read_input(0)));
    rand_halt();
}

guest.h دا اعلانوي: rand_read_input، rand_read_public، rand_write_output، rand_poseidon2، rand_keccak، rand_sha256_compress او rand_halt. دا د syscall 7 لپاره wrapper نه لري، چې د اوږدوالي پورې تړلی POSEIDON2_LEN دی او ماشین یې له constraint set 7 راهیسې چلوي، او په aeacf31 کې rand-guest check هغه ecall ردوي چې a7 = 7 ولري (zkp-circuits issue #1). نو د chain 20 لپاره د C یا assembly guest له 0 تر 6 syscallونه کاروي.

جوړول، چلول، کتنه

$ rand-guest build --lang c guests-compiled/c-fib --out c-fib.bin
25 words against a cap of 4096 (fits); 0 ecall(s) with a non-static a7
OK
wrote c-fib.bin and its .sha256 (25 words, hc 76e723cb4c218f9a7f657f39b9f95ee2353d8fbeb601aaea394afa29928f3aee, program id c213cf5c94679cab4585ed1e81b61736a7d2fe5605dc7884e4acec4144665999)

$ rand-guest run c-fib.bin --input 20 --tier 10
out[0] = 6765
out[1] = 0
out[2] = 0
out[3] = 0
out[4] = 0
out[5] = 0
out[6] = 0
out[7] = 0
cycles 116
tier 10
tier 10: fits (cycles 126 of 1023, Poseidon2 permutations 10 of 128)

fib(20) = 6765، هماغه ځواب چې د Rust fib guest یې ورکوي.

build --lang c په لارښود کې هر .c فایل (په ترتیب شوي ډول)، او همدارنګه بسته شوي start.S او rt.c، په دې ډول کمپایل کوي:

clang --no-default-config --target=riscv32-unknown-none-elf -march=rv32im -mabi=ilp32 -mno-relax
      -nostdlib -ffreestanding -fno-builtin -ffunction-sections -fdata-sections -Os
      -ffile-prefix-map=<checkout>=/rand-circuits -c

او د pin شوي Rust toolchain څخه د rust-lld -flavor gnu --gc-sections -T <ld> په واسطه یې link کوي. --gc-sections یوازې هغه څه ساتي چې guest یې راغواړي.

د C runtime

-ffreestanding -fno-builtin clang د کتابتون د فنکشنونو له پېژندلو منع کوي، خو د هغوی د غوښتنو له تولیدولو یې نه منع کوي. د struct کاپي په memcpy اوړي، یو لوی صفري ابتدايي ارزښت په memset اوړي، او د run-time ارزښت پر بنسټ ۶۴-bit وېش د یو مرستندوی فنکشن په غوښتنه اوړي، ځکه چې RV32IM یوازې ۳۲-bit ارزښتونه وېشي. rt.c دا اته تعریفوي:

فنکشند څه لپاره
memcpy، memmove، memset، memcmpکاپي، ډکول، پرتله
__udivdi3، __umoddi3، __divdi3، __moddi3۶۴-bit / او %

دا د byte لوپونه او د shift-subtract وېش دي. ورو دي: په ګرم لوپ کې، په ۳۲-bit کلمو کاپي او وېش وکړئ.

په لاس لیکل شوی پروګرام

تاسو کولای شئ ماشیني کوډ پخپله هم ولیکئ: assemble یې کړئ، د هماغه linker script سره یې link کړئ، او ELF بسته کړئ. دا پروګرام دوه خصوصي ننوتې جمع کوي او حاصل یې خپروي.

add.S:

# Reads private inputs 0 and 1, writes their sum to output slot 0, halts.
    .section .text._start
    .globl _start
_start:
    li   a7, 2          # READ_INPUT
    li   a0, 0
    ecall               # a0 = input 0
    mv   t0, a0
    li   a7, 2          # READ_INPUT
    li   a0, 1
    ecall               # a0 = input 1
    add  t1, t0, a0
    li   a7, 1          # WRITE_OUTPUT slot, word
    li   a0, 0
    mv   a1, t1
    ecall
    li   a7, 0          # HALT
    ecall

د هر syscall شمېره د خپل ecall څخه سمدستي مخکې د li a7, n په واسطه وټاکئ. په دې توګه checker کولای شي شمېره تایید کړي.

د pin شوي clang سره assemble کړئ، د rust-lld او guest-sdk/guest.ld سره link کړئ، بیا بسته کړئ. د circuits checkout دننه یې وچلوئ:

CLANG=/opt/homebrew/opt/llvm/bin/clang
LLD=$(rustc +1.98.1 --print sysroot)/lib/rustlib/$(rustc +1.98.1 -vV | sed -n 's/host: //p')/bin/rust-lld
$CLANG --no-default-config --target=riscv32-unknown-none-elf -march=rv32im -mabi=ilp32 -mno-relax -c add.S -o add.o
$LLD -flavor gnu -T guest-sdk/guest.ld add.o -o add.elf
$ rand-guest pack add.elf --out add.bin
wrote add.bin (80 bytes) and add.bin.sha256

$ rand-guest check add.bin
14 words against a cap of 4096 (fits); 0 ecall(s) with a non-static a7
OK

$ rand-guest run add.bin --input 40 --input 2
out[0] = 42
out[1] = 0
out[2] = 0
out[3] = 0
out[4] = 0
out[5] = 0
out[6] = 0
out[7] = 0
cycles 14
tier 10

$ rand-guest info add.bin
form: image container
text 14 words at 0x1000; data 0 words (0 non-zero) at 0x0; prologue 0 words; program 14 words from base_pc 0x1000
hc 42986ac1f93396d7de75f6757149523e7f1e9c5999d748af9b1915ada8ee14bd
program id 3b34c9d16adbd81a4849148675a914d10e5da0bd5b6aa64967e5f8a5fc75d941
14 words against a cap of 4096: fits

pack د ELF .text د متن د برخې په توګه اخلي او هره بله ځای شوې PROGBITS برخه د یوې data segment په توګه. .bss پرېښودل کېږي، ځکه چې RAM له صفر څخه پیلېږي.

په لاس د container بسته کول

image container شپږ سرلیک کلمې او بیا پخپله کلمې دي (د RISC-V ISA). تاسو کولای شئ پرته له کوم toolchain یو ولیکئ. دا Python script هماغه 80 بایټه لیکي چې پورته pack لیکلي وو:

import struct

text = [
    0x00200893,  # li   a7, 2      READ_INPUT
    0x00000513,  # li   a0, 0
    0x00000073,  # ecall           a0 = input 0
    0x00050293,  # mv   t0, a0
    0x00200893,  # li   a7, 2      READ_INPUT
    0x00100513,  # li   a0, 1
    0x00000073,  # ecall           a0 = input 1
    0x00a28333,  # add  t1, t0, a0
    0x00100893,  # li   a7, 1      WRITE_OUTPUT
    0x00000513,  # li   a0, 0      slot 0
    0x00030593,  # mv   a1, t1     word
    0x00000073,  # ecall
    0x00000893,  # li   a7, 0      HALT
    0x00000073,  # ecall
]
#          magic ("RAND")  version  text_base  n_text     data_base  n_data
header = [0x444E4152,      1,       0x1000,    len(text), 0,         0]
with open("add-hand.bin", "wb") as f:
    f.write(struct.pack(f"<{len(header) + len(text)}I", *header, *text))

rand-guest info add-hand.bin هماغه hc 42986ac1…14bd چاپوي، او cmp add-hand.bin add.bin هېڅ توپیر نه مومي. په لاس بسته شوي image باندې تل rand-guest check وچلوئ: node هره هغه کلمه ردوي چې decode نه شي، خو یوازې د ځای پر ځای کولو پر مهال.

wallet دوه زاړه بڼې هم ځای پر ځای کوي: یو .json فایل { "base_pc", "words" }، او د little-endian کلمو یو خام .bin چې په base 0 کې بارېږي. container یوازینۍ بڼه ده چې data segment لري.

ځای پر ځای کول او غوښتنه

پورته هره لاره په یو ډول پای ته رسېږي. د fullnode v0.3 یا وروسته نسخې د rand wallet سره (په chain 20، ژوندي chain، v0.6.8 یا وروسته: د v0.6.7 wallet هلته لېږل نه شي کولای، ځکه چې chain 20 هر ثبوت او لاسلیک د خپل genesis hash پورې تړي؛ د Rust پروګرام ځای پر ځای کول وګورئ):

rand program deploy add.bin
rand call <program id> --input 40 --input 2

د ځای پر ځای کولو فیس 0.001 RAND + 0.0001 RAND × words دی: د add.bin د 14 کلمو لپاره 0.0024 RAND او د c-fib.bin د 25 کلمو لپاره 0.0035 RAND. دواړه له 4,096 کلمو کم دي، نو د هر chain له حد سره برابرېږي: پېش‌فرض 4,096 او د chain 20 حد 65,535. غوښتنه په محلي توګه په tier 10 کې ثابتېږي. په chain 15 کې یې لګښت 0.002 RAND و. په chain 20 کې فیس نور 0.001 + call_fee(tier) نه دی: لږترلږه اندازه BUNDLE_BASE + gas_price × declared gas limit + byte_price × ⌈bytes / 1024⌉ ده، rand call د ثبوت څخه مخکې gas: <exact> (declaring <limit>, tier <t>) او فیس چاپوي، او په chain 18 کې د څلورو اندازه شوو غوښتنو لګښت هر یو له 0.0057 تر 0.0075 RAND و (بېلګه پروګرامونه). په chain 20 کې هر ځای پر ځای کول او غوښتنه دوه د bundle اړخ ثبوتونه هم لري: د tier-10 د لګښت اجازه او د tier-14 bundle. د Rust پروګرام ځای پر ځای کول بیانوي چې هر کمانډ څه کوي.

د دې لپاره چې نور هغه څه وڅېړي چې تاسو ځای پر ځای کړي، سرچینه او خپل circuits commit (د 18 تر 20 chainونو لپاره aeacf31) خپاره کړئ. د clang 23.1.1 او Rust 1.98.1 سره، rand-guest build په هر ماشین کې هماغه hc ورکوي.

وروستی ځل د 2026-10-12 په نېټه د fullnode د c0878c3f کمېټ (زنځیره 21) پر وړاندې تایید شوی، او circuits `7ef3220` (`rand-guest/README.md`, `guests-compiled/c-fib`, `guest-sdk/guest.ld`); every `rand-guest` output on this page was produced on 2026-09-19, circuits `aeacf31` (`rand-guest/guest.h`, `rand-guest/src/check.rs`; `git diff 7ef3220 aeacf31 -- guest-sdk rand-guest`), read on 2026-09-30; no output on this page was re-run at that commit, fullnode tag v0.6.8 `c9c9bd3c` (`docs/deploy.md` on `binding_domain`, `.github/workflows/ci.yml` circuits pin) and `rand_getLimits` on chain 20, read on 2026-10-01; nothing on this page was deployed or called on chain 20, fullnode tag v0.8.0 `c0878c3f` (`CHANGELOG.md`, `docs/zkvm.md` §8a) and `rand_getLimits` on chain 21, read on 2026-10-12; nothing on this page was deployed or called on chain 21. چېرې چې کوډ او دا پاڼه سره توپیر ولري، کوډ سم دی؛ موږ ته خبر راکړئ.