sbpf2rv एक संकलित Solana प्रोग्राम (एक sBPF ELF, यानी वह .so जो cargo build-sbf बनाता है) लेकर उसे एक Rand प्रोग्राम में बदलता है। यह C लिखता है, और rand-guest build उस C को एक RV32IM इमेज में संकलित करता है। समान ELF और समान निर्देश के लिए यह इमेज वही आठ आउटपुट शब्द प्रकाशित करती है जो Rand का sBPF इंटरप्रेटर गेस्ट, sbpf.bin, करता है। यह पृष्ठ वास्तविक SPL Token प्रोग्राम पर पूरी प्रक्रिया दिखाता है।
यह क्या है
| इनपुट | एक sBPF v1 ELF |
| आउटपुट | एक C शिम क्रेट; rand-guest build इसे एक इमेज कंटेनर बनाता है |
| यह कहाँ चलता है | ऑफ़-चेन, डेवलपर की मशीन पर; चेन केवल इमेज देखती है |
| इसे किससे मेल खाना चाहिए | उन्हीं दो इनपुट टेपों पर sbpf.bin के आठ आउटपुट शब्दों से |
| रिपॉज़िटरी | circuits रिपॉज़िटरी में sbpf2rv/ |
| निर्धारित टूलचेन | Rust 1.98.1, clang 23.1.1, cc क्रेट 1.4.6 |
अनूदित प्रोग्राम इंटरप्रेटर का ABI बनाए रखता है। यह वही टेप पढ़ता है: सार्वजनिक टेप पर ELF और निजी टेप पर क्रमबद्ध निर्देश (पहले अकाउंट, फिर निर्देश डेटा)। यह प्रोग्राम के चारों ओर वही sbpf-core हार्नेस चलाता है: यह इनपुट को डिकोड करता है, ELF लोड करता है, अकाउंट क्षेत्र की जाँच करता है और इनपुट तथा आउटपुट का हैश बनाता है। केवल sBPF निष्पादन को ही नेटिव कोड से बदला जाता है। इसीलिए इसके आउटपुट शब्दशः इंटरप्रेटर के आउटपुट के बराबर होते हैं।
ट्रस्ट मॉडल
तीन चीज़ें किसी अनूदित प्रोग्राम के प्रूफ़ को बाँधती हैं।
hcअनूदित कोड को बाँधता है। C इमेज में संकलित होता है, इसलिए इमेज काhcउसे समाहित करता है।- ELF गार्ड
hcको एक ही प्रोग्राम से बाँधता है। शिम प्रोग्राम को टेप पर मौजूद ELF से लोड करता है, इसलिए बिना जाँच के एक ही इमेज उसीhcके अंतर्गत कॉलर द्वारा चुना गया कोई दूसरा ELF चला सकती थी। इसलिए जनरेट की गईprogram.cउस लोड किए गए प्रोग्राम के डाइजेस्ट के साथ समाप्त होती है जिससे उसका अनुवाद हुआ था: टेक्स्ट, केवल-पठन डेटा, उनके पते और एंट्री पॉइंट। कुछ भी चलाने से पहले शिम टेप के लोड किए गए प्रोग्राम का उसी तरह (Poseidon2) हैश बनाता है और तुलना करता है। कोई भी अन्य प्रोग्राम प्री-स्टेट परBadElf, स्टेटस 2, के साथ रुक जाता है। अतः जो प्रूफ़ इसhcके विरुद्ध सत्यापित होता है, वह उसी प्रोग्राम का एक रन है। H_PUBELF के बाइट्स को बाँधता है। ELF सार्वजनिक टेप पर जाता है, और प्रूफ़ का पब्लिक-इनपुट डाइजेस्ट उसे शब्दशः समाहित करता है।
hc किसी दिए गए ELF का सटीक अनुवाद है या नहीं, इसकी जाँच पुनर्निर्माण से की जाती है। ELF पर निर्धारित sbpf2rv चलाएँ, निर्धारित टूलचेन से बिल्ड करें, और hc की तुलना करें। इसी कारण बिल्ड पुनरुत्पादनीय है।
चेन स्रोत ELF या उसका हैश दर्ज नहीं करती। वह इमेज और उसकी प्रोग्राम id संग्रहीत करती है। जो डिप्लॉयर ELF को सार्वजनिक करना चाहता है, वह उसे प्रोग्राम के साथ प्रकाशित करता है।
गार्ड लोड किए गए प्रोग्राम को बाँधता है, फ़ाइल को नहीं। दो ELF जो केवल वहीं भिन्न हैं जहाँ लोडर नहीं देखता (हेडर पैडिंग, सिंबल टेबल), वे एक ही प्रोग्राम में लोड होते हैं और दोनों ओर एक समान चलते हैं। जिस ELF में .rodata का एक बाइट बदला हुआ हो, भले ही ट्रांसफ़र उसे कभी न पढ़े, उसे अनुवाद अस्वीकार कर देता है और इंटरप्रेटर चला देता है।
क्या ट्रैप होता है और क्या अस्वीकार होता है
अनुवाद के समय कुछ भी अस्वीकार नहीं होता। विकृत ELF को लोडर के अपने संदेश के साथ अस्वीकार किया जाता है, पर सुगठित ELF का कोई भी निर्देश अस्वीकार नहीं होता। स्कैनर चेतावनियों के रूप में बताता है कि कोई प्रोग्राम किन स्थितियों में पहुँच सकता है, और अनूदित प्रोग्राम रन टाइम पर ठीक वहीं ट्रैप करता है जहाँ इंटरप्रेटर करता:
| चेतावनी | यह क्या है | रन टाइम पर |
|---|---|---|
UnknownSyscall | एक syscall हैश जिसे रनटाइम लागू नहीं करता | ट्रैप UnknownSyscall |
Cpi | एक क्रॉस-प्रोग्राम इनवोकेशन (sol_invoke_signed*) | वही UnknownSyscall ट्रैप; CPI लागू नहीं है |
RegisterOutOfRange | एक रजिस्टर r11..r15, या r10 से ऊपर का callx रजिस्टर | ट्रैप BadInsn |
UnknownOpcode | ऐसा ऑपकोड जिसकी कोई v1 श्रेणी नहीं है, जिसमें केवल-v2 sdiv/srem परिवार और hor64 शामिल हैं | ट्रैप BadInsn |
JumpOutOfText | फ़ंक्शन के टेक्स्ट से बाहर कोई जंप, कॉल या फ़ॉल-थ्रू | ट्रैप BadJump |
BadCallImmSrc | 2..=10 में src वाला call imm (केवल हाथ से बनाए गए ELF में) | ट्रैप BadInsn |
जो अनुवादक अप्राप्य कोड को अस्वीकार करता, वह उन प्रोग्रामों को अस्वीकार कर देता जिन्हें इंटरप्रेटर आज चलाता है। SPL Token ऐसा ही एक प्रोग्राम है: यह sol_set_return_data और sol_get_sysvar को कॉल करता है, जिन तक Transfer पथ कभी नहीं पहुँचता।
तीन विचलन स्वीकार किए गए हैं। प्रत्येक केवल अनुवाद को वहाँ रोकता है जहाँ इंटरप्रेटर शायद न रुके; अनुवाद कभी ऐसा रन पूरा नहीं करता जिसे इंटरप्रेटर रोक देता है।
- स्कैन किए गए समुच्चय से बाहर का
callxBadJumpट्रैप करता है, जबकि इंटरप्रेटर उस पते पर वास्तविक कोड चला सकता है। - बजट जाँच एक बेसिक ब्लॉक तक स्थगित हो सकती है। SPL Token को 65,535-शब्द की सीमा में समाने के लिए, उसके 3,546 ब्लॉकों में से 1,505 अपनी निर्देश-सीमा जाँच छोड़ देते हैं। सीमा पार करने वाले उस एक ब्लॉक के भीतर रुकने का प्रकार भिन्न हो सकता है। स्टेटस और आठ शब्द समान रहते हैं।
- केवल स्रोत प्रोग्राम चलता है। कोई अन्य ELF अस्वीकार होता है (ऊपर वर्णित गार्ड)।
Ed25519 और secp256k1. sol_ed25519_verify और sol_secp256k1_recover के सॉफ़्टवेयर कार्यान्वयन sbpf-rt/ में मौजूद हैं, पर लिंक नहीं किए गए हैं। इंटरप्रेटर दोनों पर ट्रैप करता है, इसलिए समानता के लिए अनुवाद भी ट्रैप करता है। प्रत्येक कॉल की लागत क्रमशः लगभग 14.3M और 15.7M साइकिल है, जो सबसे बड़े टियर (2²⁰) से बहुत अधिक है। इनके लिए कोप्रोसेसर तालिकाओं की आवश्यकता है।
आँकड़े
SPL Token (guests-compiled/sbpf/programs/spl_token.so, इंटरप्रेटर का अपना टेस्ट फ़िक्स्चर) पर, ELF गार्ड सहित, मापा गया।
| इमेज | प्रोग्राम शब्द | सीमा | hc |
|---|---|---|---|
| SPL Token, अनूदित | 65,096 | 65,535 (439 शेष) | 8ca905ae…758b |
sbpf.bin, इंटरप्रेटर | 8,317 | 65,535 | 059a7086…f476 |
| वेक्टर | स्टेटस | sBPF निर्देश | अनूदित साइकिल | sbpf.bin साइकिल | टियर (दोनों) |
|---|---|---|---|---|---|
Transfer 250 | 1 | 143 | 765,851 | 694,498 | 20 |
Transfer बैलेंस से अधिक | 0 | 133 | 748,836 | 679,814 | 20 |
MintTo 250 | 1 | 120 | 708,648 | 634,423 | 20 |
MintTo गलत अथॉरिटी द्वारा | 0 | 134 | 696,694 | 627,241 | 20 |
Burn 250 | 1 | 131 | 710,245 | 637,038 | 20 |
Burn बैलेंस से अधिक | 0 | 121 | 695,434 | 624,781 | 20 |
दो अकाउंट के साथ Transfer | 0 | 69 | 645,015 | 569,656 | 20 |
| बहुत अधिक अकाउंट (हार्नेस अस्वीकार करता है) | 2 | 0 | 303,933 | 304,616 | 20 |
Transfer पर साइकिल कहाँ खर्च होते हैं:
| चरण | अनूदित | sbpf.bin |
|---|---|---|
| दोनों टेप पढ़ना | 302,881 | 302,880 |
| ELF लोड करना | 177,012 | 173,859 |
| अकाउंट क्षेत्र की जाँच | 103,829 | 103,824 |
| sBPF स्टैक और हीप को शून्य करना | 49,181 | 49,181 |
| आउटपुट और इनपुट हैश, सार्वजनिक शब्द, ग्लू | 51,091 | 42,723 |
| ELF गार्ड | 72,949 | — |
| स्वयं sBPF प्रोग्राम | 8,908 | 22,031 |
| कुल | 765,851 | 694,498 |
अनूदित प्रोग्राम का अपना निष्पादन प्रति sBPF निर्देश लगभग 2.4 से 2.5 गुना सस्ता है (लगभग 62 साइकिल बनाम 154)। पर हर रन का लगभग 98% हिस्सा स्थिर हार्नेस है, और गार्ड 73k साइकिल जोड़ता है। इसलिए SPL Token के लिए अनूदित इमेज 69k से 75k साइकिल अधिक महँगी है, और दोनों टियर 20 पर ही रहती हैं।
अनुवाद केवल गणना-प्रधान प्रोग्रामों के लिए लाभदायक है। प्रति निर्देश लगभग 90 साइकिल की बचत पर, 10,000 sBPF निर्देश निष्पादित करने वाला कॉल लगभग 0.9M साइकिल बचाता है। SPL Token 120 से 143 निर्देश निष्पादित करता है।
वॉकथ्रू: SPL Token, अनूदित और मिलान किया हुआ
हर कमांड 7ef3220 पर circuits चेकआउट की रूट से चलती है, जिसमें Rust प्रोग्राम डिप्लॉय करें वाला टूलचेन और RISC-V प्रोग्राम डिप्लॉय करें वाला clang 23.1.1 हो। लंबा आउटपुट वहाँ काटा गया है जहाँ … अंकित है।
0. टूल बनाएँ
(cd sbpf2rv && cargo +1.98.1 build --release)
(cd rand-guest && cargo +1.98.1 build --release)
1. अनुवाद करें
--out 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)। चारों चेतावनियाँ वास्तविक syscall हैं जिन तक Transfer कभी नहीं पहुँचता: हैश 2720453611 sol_set_return_data है (तीन कॉल साइट) और 331461893 sol_get_sysvar है।
2. इमेज बनाएँ
इमेज डिफ़ॉल्ट 4,096-शब्द सीमा से बड़ी है, इसलिए --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
जो कोई भी इन दो चरणों को उसी टूलचेन से चलाता है, उसे यही hc मिलता है।
3. दोनों चलाएँ और तुलना करें
250 का Transfer दो शब्द-सूचियाँ लेता है, जिन्हें tests/parity.rs इंटरप्रेटर की अपनी कॉल एन्कोडिंग से बनाता है: 27,151 सार्वजनिक शब्द (ELF, शब्दों में एन्कोड किया हुआ) और 10,458 निजी शब्द (पहले अकाउंट, फिर Transfer डिस्क्रिमिनेंट और राशि)। rand-guest run इन्हें --public और --input के रूप में लेता है। प्रत्येक सूची के पहले शब्दों तक संक्षिप्त:
$ 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
वही दो सूचियाँ इंटरप्रेटर गेस्ट के विरुद्ध:
$ 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
सभी आठ शब्द समान हैं। out[0] = 1 स्टेटस (सफलता) है। out[1..8] वह डाइजेस्ट है जिसे इंटरप्रेटर का ABI इनपुट और आउटपुट पर परिभाषित करता है।
4. एक ही कमांड में सभी आठ वेक्टर जाँचें
पैरिटी टेस्ट अनूदित इमेज बनाता है, हर वेक्टर को दोनों इमेज पर rand-guest run से चलाता है, और आठ शब्दों में किसी भी अंतर पर विफल हो जाता है:
$ 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. डिप्लॉय करें
rand program deploy sbpf2rv/target/spl-token/image.bin --public spl_token.so
इमेज ELF को सार्वजनिक टेप से पढ़ती है, इसलिए ELF प्रोग्राम का सार्वजनिक इनपुट है, जो डिप्लॉय के समय नियत हो जाता है। --public स्वयं .so फ़ाइल लेता है; वॉलेट उसे word-encode करके उन्हीं 27,151 words में बदलता है जो चरण 4 में थे।
इसके लिए ऐसी chain चाहिए जिसका genesis max_program_words को कम से कम 65,096 और max_program_public_words को कम से कम 27,151 पर सेट करे। Chain 12 एक डिप्लॉय को 4,096 words तक सीमित करती थी और कोई सार्वजनिक इनपुट नहीं लेती थी, इसलिए वॉलेट ने वहाँ कुछ भी प्रूव करने से पहले ही इस इमेज को अस्वीकार कर दिया। Chain 13, यानी v0.4 chain, ने 65,535 और 32,768 सेट किए, और उसके बाद की हर chain दोनों मान बनाए रखती है। Chain 20, जो लाइव chain है (genesis 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135), chain 13 की ब्लॉक और call-envelope सीमाएँ भी बनाए रखती है और प्रूफ़ की सीमा को आधा करके 4 MiB कर देती है (4,194,304 bytes, chain 17 से; chains 13 से 16 ने 8 MiB सेट किया था)। अब आकार की सीमाएँ ही एकमात्र अवरोध नहीं हैं। Chain 20 का genesis hardening_v6 सेट करता है, और इसके अंतर्गत ऐसा डिप्लॉय अमान्य है जिसमें tier-14 call सीमा पर एक call जितने program words समा सकती है उससे अधिक words हों (ProgramUncallable): सार्वजनिक इनपुट के बिना अधिकतम 8,180 words, और सार्वजनिक इनपुट के साथ इससे कम। यह इमेज 27,151-word सार्वजनिक इनपुट के साथ 65,096 words की है, इसलिए chain 20 डिप्लॉय को अस्वीकार करती है, और वह call को भी अस्वीकार करेगी: हर SPL vector tier 20 पर चलता है, जो tier-14 call सीमा से ऊपर है (सीमाएँ)। Chain 20 पर block aggregation बंद है (उसके genesis में कोई aggregation खंड नहीं है); उसके bootstrap नोड वैलिडेटर चलाना में सूचीबद्ध हैं। डिप्लॉय शुल्क में code words के साथ सार्वजनिक words भी गिने जाते हैं: 0.001 + 0.0001 × (65,096 + 27,151) = 9.2257 RAND, जो नीचे दिए गए chain-13 डिप्लॉय ने चुकाया।
यह डिप्लॉय 2026-09-19 को chain 13 पर चला, जब chain 13 लाइव chain थी (उत्पादन FRI प्रोफ़ाइल, genesis 8123ccac1883a45750e4df6964fb7cd3f0b321798cde4c0ef406a0293939ece3), genesis वॉलेट shielded-1 से। उसके बाद की हर chain (14 से 19) chain 13 के प्रोग्रामों के बिना नई chain के रूप में शुरू की गई, और इमेज को उनमें से किसी पर भी दोबारा डिप्लॉय नहीं किया गया है, इसलिए नीचे दिया गया ट्रांज़ैक्शन और ऊँचाई chain 13 के हैं और अब एक्सप्लोरर पर नहीं मिलते। Program id केवल base_pc, words और सार्वजनिक words का हैश है, इसलिए वही इमेज और ELF हर उस chain पर वही id पाते हैं जो डिप्लॉय को स्वीकार करती है। वॉलेट का आउटपुट, प्रगति पंक्तियों को छोड़कर (…):
$ 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 id | 740236918310f8e52bb0c1ef49b2b0e0c018762e289666660685b0694c8dd00a |
| इमेज | 65,096 words; rand-guest की वर्तनी में hc 8ca905ae…, वॉलेट की वर्तनी में ae05a98c… |
| सार्वजनिक इनपुट | 27,151 words (ELF), digest ec57b10ed6f3a3d5fe87ec072f691322ad747377ba2f0a1788bcfe3e7334d67e |
| शुल्क bundle (chain 13 का 2-in-2-out bundle) | tier 14, 1,418,406 bytes, 94.3 s में प्रूव किया गया |
| डिप्लॉय tx (chain 13) | 626fc9387ecc1f6b39f44184807303ac2843029d8fb8e28338bf186445927530 |
| ऊँचाई पर anchored (chain 13) | 400 |
| शुल्क | 9.2257 RAND |
Chain 14 से भुगतान करने वाला bundle वही एक 4-in-4-out hidden-asset bundle है जो हर ट्रांज़ैक्शन साथ रखता है, और वह ट्रांज़ैक्शन के binding के विरुद्ध प्रूव किया जाता है। वह अब भी tier 14 है: chains 14 और 15 पर उत्पादन प्रोफ़ाइल में लगभग 100 s और लगभग 1.42 MB। Chain 17 से एक bundle में tier-10 auth प्रूफ़ भी होता है (विभाजित प्राधिकरण), इसलिए chains 18 और 19 पर एक ट्रांज़ैक्शन का शुल्क bundle लगभग 1.49 MB bundle प्रूफ़ और लगभग 1.37 MB auth प्रूफ़ का होता है।
Program id ELF को बाँधता है, इसलिए यह उस id से भिन्न है जो rand-guest info केवल इमेज के लिए प्रिंट करता है। deploy द्वारा प्रिंट किए गए id को call करें।
सीमाएँ
- प्रोग्राम का कोई भी call प्रूव नहीं किया गया है, वह chain 20 पर डिप्लॉय नहीं है, और chain 20 डिप्लॉय और call दोनों को अस्वीकार करती है। ऊपर का डिप्लॉय chain 13 पर था। Chain 20 के
hardening_v6के अंतर्गत ऐसा डिप्लॉय अमान्य है जिसमें एक tier-14 call जितने words समा सकता है उससे अधिक words हों (ProgramUncallable; अधिकतम 8,180 words), और इमेज 65,096 की है। इनपुट पक्ष समा जाता: ELF डिप्लॉय का सार्वजनिक इनपुट है, जिसेrand callस्वयं प्राप्त करता है, और 10,458 निजी words 16,071 की इनपुट सीमा में समा जाते हैं, जिसे chain 20 बनाए रखती है। लेकिन हर SPL vector tier 20 का है, और fullnode v0.5.6 (2026-09-25) से नोड tier 14 से ऊपर के किसी भी call प्रूफ़ को सत्यापनकर्ता कुंजी बनाने से पहले ही अस्वीकार कर देता है (CallTierTooHigh)। यही जाँच उन hash तालिकाओं को भी सीमित करती है जिन्हें एक call घोषित कर सकता है: 2¹³ SHA-256 पंक्तियाँ (128 compressions) और 2¹² Keccak पंक्तियाँ (128 permutations)। Tier-20 call केवल chain के बाहर प्रूव किया जा सकता है, और अभी तक कोई tier-20 प्रूफ़ मौजूद नहीं है (अगला बिंदु)। - अभी तक tier 20 पर कोई प्रूफ़ नहीं बनाया गया है। एक tier-20 प्रूफ़ 48 GB लैपटॉप पर लगभग 31 GB पर रोक दिया गया, और 64 GB droplet पर 10 m 41 s के बाद 65.1 GB पर OOM द्वारा समाप्त कर दिया गया। मापी गई tier-16/18 स्केलिंग (प्रति +2 tiers मेमोरी लगभग ×3.9, समय लगभग ×4.1) से बहिर्वेशन करने पर tier 20 को लगभग 330 GB और लगभग 3.6 h चाहिए — जो DigitalOcean के सबसे बड़े मेमोरी droplet (m-32vcpu-256gb, 256 GB) से अधिक है। प्रूवर single-threaded चला: 16-vCPU मशीन एक कोर के 99% पर रही। देखें प्रूविंग मेमोरी।
- कोई CPI नहीं। Cross-program invocations trap होते हैं।
- केवल sBPF v1। केवल v2 वाले opcodes trap होते हैं।
- Ed25519 और secp256k1 syscalls trap होते हैं जब तक उनके लिए coprocessor तालिकाएँ नहीं बन जातीं।
- Chain ELF को केवल सार्वजनिक इनपुट के रूप में दर्ज करती है।
--publicके साथ किया गया डिप्लॉय ELF के words और उनका digest संग्रहीत करता है, औरrand_getProgramPublicउन्हें उपलब्ध कराता है। Chain यह दर्ज नहीं करती कि इमेज उससे कैसे बनाई गई: build inputs प्रकाशित करें ताकि अन्य लोगhcको दोबारा बना सकें।