evm2rv przyjmuje bajtkod uruchomieniowy EVM, czyli wynik solc --bin-runtime, i zamienia go na program Rand. Generuje kod w C, a rand-guest build kompiluje go do obrazu RV32IM. Obraz przyjmuje ten sam wektor wejściowy co gość interpretera EVM w Rand, evm.bin, i publikuje te same osiem słów wyjściowych. Kontrakt wykonuje natywnie, zamiast interpretować go opkod po opkodzie. Ta strona pokazuje całą ścieżkę na przykładzie ERC-20.
Czym jest
| wejście | uruchomieniowy bajtkod EVM, jako tekst szesnastkowy (.hex) lub surowe bajty |
| wyjście | crate z powłoką w C; rand-guest build zamienia go w kontener obrazu |
| gdzie działa | poza łańcuchem, na maszynie programisty; łańcuch widzi tylko obraz |
| z czym musi się zgadzać | status, osiem słów wyjściowych i gas_used z evm.bin |
| repozytorium | evm2rv/ w repozytorium circuits |
| przypięty toolchain | Rust 1.98.1, clang 23.1.1, crate cc 1.4.6 |
Translator przyjmuje kod uruchomieniowy, nie kod tworzący. Dowód obejmuje jedno wywołanie wdrożonego kontraktu, więc konstruktor nigdy się nie wykonuje. Stan, który zapisałby konstruktor, wchodzi natomiast w skład stanu początkowego, jako świadectwa składowania (storage witnesses).
Istnieją dwa etapy translacji. Oba dają te same wyniki i ten sam gaz; każdy jest osobnym programem z własnym hc.
| etap | flaga | co robi |
|---|---|---|
| pierwszy | --stage 1 | każdy opkod na stosie w pamięci |
| drugi | --stage 2, domyślny | słowa stosu każdego bloku w zmiennych lokalnych C, stałe obliczane podczas translacji |
Wektor wejściowy jest taki jak w interpreterze: kod, calldata, wywołujący i pozostałe słowa środowiska, limit gazu, korzeń stanu początkowego oraz jedno świadectwo składowania na każdy slot, którego dotyka wywołanie. Wyjściami są out[0], czyli status (1 – powodzenie, 0 – revert, 2 – wyjątkowe zatrzymanie), oraz out[1..8], skrót EVM_OUT obejmujący skrót kodu, oba korzenie stanu, dane zwrotne i logi.
Model zaufania
Weryfikator sprawdza przetłumaczony kontrakt w dwóch krokach.
hc == translate(bytecode). Uruchomevm2rvponownie na opublikowanym bajtkodzie z tym samym--stagei--chain-id, zbuduj ponownie przypiętym toolchainem i porównajhc. Wygenerowany crate przypinaccdokładnie i zawiera własnyCargo.lock.- Strażnik kodu wiąże
hcz bajtkodem. Przetłumaczona logika jest skompilowana w obrazie, aleCODECOPYiCODESIZEczytają kod z wektora wejściowego. Bez kontroli ten samhcmógłby działać na bajtach kodu wybranych przez wywołującego. Dlategocontract.czawiera skrót Poseidon2 źródłowego bajtkodu (jego długości i bajtów), a powłoka hashuje kod z wektora wejściowego w ten sam sposób, zanim wykona się jakikolwiek przetłumaczony kod. Inny kod jest odrzucany: status 2,gas_used0, zatrzymanieOutOfBounds.
Skrót EVM_OUT wiąże też keccak256 kodu, tak jak w interpreterze. Łańcuch nie zapisuje źródłowego bajtkodu ani jego skrótu. Aby inni mogli sprawdzić hc, opublikuj bajtkod albo kod źródłowy Solidity i dokładną wersję solc.
Strażnik kosztuje 1 008 cykli przy transferze. Kod różniący się od źródła jednym bajtem jest odrzucany w 30 418 cyklach na etapie drugim (poziom 16).
Zakres i to, co przerywa wykonanie
Opkody. Zestaw Shanghai. Kompiluj z --evm-version shanghai: nowsze cele emitują MCOPY i inne opkody Cancun, które przerywają wykonanie.
Opkody środowiska:
| opkod | translacja |
|---|---|
ADDRESS, CALLER, CALLVALUE, CALLDATASIZE, CODESIZE | z wektora wejściowego, tak jak czyta je interpreter |
CHAINID | wartość --chain-id, wpisana na stałe podczas translacji, więc hc ją wiąże; wymagana, gdy kod zawiera CHAINID |
ORIGIN | równy CALLER (jedno wywołanie, brak przekaźnika) |
GASPRICE, COINBASE, TIMESTAMP, NUMBER, PREVRANDAO, GASLIMIT, SELFBALANCE, BASEFEE, BLOCKHASH | przerywają wykonanie (status 2), tak jak w interpreterze |
Dziewięć opkodów kontekstu bloku przerywa wykonanie, dopóki nie powstanie projekt ich wiązania z blokiem. Prywatne wejście nie może przenosić faktu o bloku, ponieważ weryfikator nie może otworzyć H_IN. Do czasu podjęcia tej decyzji kontrakt odczytujący czas lub numer bloku (na przykład termin ważności permitu) przerywa wykonanie.
Wywołania. CALL, CALLCODE, DELEGATECALL i STATICCALL uruchamiają prekompilację, gdy celem jest adres od 1 do 9. Każdy inny cel przerywa wykonanie. Niezerowa wartość w CALL lub CALLCODE przerywa wykonanie: nie ma modelu sald.
Prekompilacje. Wszystkie dziewięć działa programowo. Niektóre są dziś zbyt wolne, by je udowodnić, ponieważ dowód mieści co najwyżej 2²⁰ wierszy:
| prekompilacja | wektor | cykle | mieści się w 2²⁰ |
|---|---|---|---|
| 1 ecrecover | ValidKey | 14 510 525 | nie |
| 2 sha256 | ”abc” / 200 bajtów | 2 791 / 5 289 | tak |
| 3 ripemd160 | ”abc” | 12 195 | tak |
| 4 identity | 100 bajtów | 4 498 | tak |
| 5 modexp | nagydani-1-square / -1-pow0x10001 | 122 332 / 874 548 | tak |
| 5 modexp | eip_example1 (256 bitów) | 11 170 118 | nie |
| 5 modexp | nagydani-5-pow0x10001 (1 024 bajty) | 55 076 950 | nie |
| 6 bn256 add | chfast1 | 978 262 | tak, ledwo |
| 7 bn256 mul | chfast1 | 3 060 669 | nie |
| 8 bn256 pairing | 1 para / 2 pary | 1 853 656 212 / 2 019 000 469 | nie |
| 9 blake2f | 12 rund | 14 493 | tak, do około 1 800 rund |
Podstawa i moduł w modexp są ograniczone do 1 024 bajtów każde.
Akceptowane rozbieżności. Status, osiem słów i gas_used muszą się zgadzać. Akceptowane są trzy różnice: rodzaj zatrzymania może się różnić (gaz statyczny jest naliczany na początku każdego bloku, więc OutOfGas i inne zatrzymanie mogą się zamienić; oba oznaczają status 2 przy zużyciu całego gazu); translacja implementuje CHAINID, ORIGIN i wywołania prekompilacji, które interpreter przerywa; a strażnik kodu odrzuca kod inny niż jego źródło.
Liczby
Wywołania ERC-20 z wbudowanym strażnikiem kodu. Cykle z rand-guest run; poziom w nawiasie.
| wywołanie | interpreter (evm.bin) | etap pierwszy | etap drugi (domyślny) |
|---|---|---|---|
transfer(BOB, 250) | 121 638 (18) | 80 211 (18) | 66 235 (18) |
approve(BOB, 5) | 85 645 (18) | 56 261 (16) | 48 119 (16) |
transferFrom(ALICE, BOB, 100) | 161 434 (18) | 110 074 (18) | 88 824 (18) |
| program | słowa | hc |
|---|---|---|
evm.bin, interpreter | 18 009 | 7e1aea2b…854c08 |
| ERC-20, etap pierwszy | 15 804 | 9cdb79e7…2fd048c8 |
| ERC-20, etap drugi | 11 686 | a0feae92a7311c9562495717100eb7aea71270a38ed435d06dc31387e0ea8ff6 |
Etap drugi wykonuje te trzy wywołania w 54,5%, 56,2% i 55,0% cykli interpretera. Transfer pozostaje na poziomie 18: jego 66 235 cykli plus 3 155 wierszy skrótu daje 69 390 wierszy, czyli 3 855 ponad 65 535 z poziomu 16.
Około 60% transferu na etapie drugim (około 39 928 cykli) to uprząż wspólna dla obu obrazów: dekodowanie wejścia, weryfikacja świadectw składowania, wywołania keccak256 w ABI i skrót wyjściowy. Żadna praca translacji nie schodzi poniżej tej podłogi.
Przewodnik: ERC-20, od Solidity do zgodnych wyjść
Każde polecenie uruchamia się z katalogu głównego kopii circuits na 7ef3220, z toolchainem z Wdrożenie programu w Rust i clang 23.1.1 z Wdrożenie programu RISC-V. Długie wyjście jest obcięte w miejscach oznaczonych ….
0. Zbuduj narzędzia
(cd evm2rv && cargo +1.98.1 build --release)
(cd rand-guest && cargo +1.98.1 build --release)
1. Skompiluj Solidity do bajtkodu uruchomieniowego
Kontraktem jest zatwierdzony guests-compiled/evm/contracts/ERC20.sol: samodzielny ERC-20 z układem składowania z OpenZeppelin v4, pragma solidity 0.8.37. Użyj dokładnie solc 0.8.37; inna wersja optymalizuje inaczej i daje inny bajtkod.
| wydanie | v0.8.37 z github.com/ethereum/solidity/releases |
| plik dla macOS | solc-macos, sha256 a27396e7732aa52e80ff89ad7bd8a2e46fec2a6dcc4ef20cd16e5e0c502d6821 |
| plik dla Linuksa | solc-static-linux, z tego samego wydania |
$ curl -sSL -o solc https://github.com/ethereum/solidity/releases/download/v0.8.37/solc-macos
$ shasum -a 256 solc
a27396e7732aa52e80ff89ad7bd8a2e46fec2a6dcc4ef20cd16e5e0c502d6821 solc
$ chmod +x solc && ./solc --version
solc, the solidity compiler commandline interface
Version: 0.8.37+commit.f401782d.Darwin.appleclang
$ (cd guests-compiled/evm && ../../solc --optimize --optimize-runs 200 --evm-version shanghai \
--bin-runtime contracts/ERC20.sol) | tee solc.out
======= contracts/ERC20.sol:ERC20 =======
Binary of the runtime part:
608060405234801561000f575f5ffd5b5060043610610060575f3560e01c8063095ea7b31461006457806318160ddd1461008c57806323b872dd1461…
$ tail -1 solc.out > evm2rv/target/mytoken.hex
Ostatni wiersz to bajtkod uruchomieniowy, 1 296 bajtów. Jest identyczny bajt w bajt z zatwierdzonym guests-compiled/evm/contracts/erc20.runtime.hex; SOLC=$PWD/solc bash guests-compiled/evm/contracts/build.sh sprawdza to i wypisuje contracts: erc20.runtime.hex reproduces.
Flagi mają znaczenie:
--bin-runtime: kod wdrożony, nie kod tworzący.--evm-version shanghai: domyślny cel dla 0.8.37 emitujeMCOPY, który przerywa wykonanie.--optimize --optimize-runs 200: profil dla wdrożonego kontraktu.
2. Przetłumacz
$ evm2rv/target/release/evm2rv evm2rv/target/mytoken.hex --out evm2rv/target/mytoken --chain-id 12
1296 code bytes: 74 blocks, 798 opcodes, 51 jumpdests (stage 2)
CHAINID is the constant 12
no trapping opcodes present
wrote evm2rv/target/mytoken (crate mytoken): contract.c, Cargo.toml, Cargo.lock, build.rs, src/main.rs, shim.ld
--outmusi wskazywać wewnątrz kopii circuits. Bez niegoevm2rvtylko analizuje kod.- Każdy opkod przerywający wykonanie zostałby tu wymieniony jako ostrzeżenie, wraz z jego pc.
- Ta sesja została zarejestrowana z
--chain-id 12. Ten ERC-20 nie zawieraCHAINID, więc--chain-idnie zmienia jegohc. Kontrakt odczytującyCHAINIDwymaga tej flagi; ustaw ją na łańcuch, w którym będziesz wdrażać (--chain-id 19dla działającego łańcucha).
contract.c kończy się skrótem strażnika kodu:
const uint32_t *evm_code_digest(void) {
static const uint32_t d[8] = {0xf679280fu, 0x86c10e83u, 0x7e8f1f39u, 0xa2377de3u, 0x8a2e282fu, 0xc54cad42u, 0xddfaf009u, 0x7d28a8afu};
return d;
}
3. Zbuduj obraz
Domyślny limit to 4 096 słów, więc przekaż --max-words 65535.
$ rand-guest/target/release/rand-guest build evm2rv/target/mytoken --max-words 65535
…
11686 words against a cap of 65535 (fits); 0 ecall(s) with a non-static a7
OK
wrote evm2rv/target/mytoken/image.bin and its .sha256 (11686 words, hc a0feae92a7311c9562495717100eb7aea71270a38ed435d06dc31387e0ea8ff6, program id f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d)
$ rand-guest/target/release/rand-guest info evm2rv/target/mytoken/image.bin
form: image container
text 11147 words at 0x10000; data 408 words (205 non-zero) at 0x1ae2c; prologue 539 words; program 11686 words from base_pc 0xf794
hc a0feae92a7311c9562495717100eb7aea71270a38ed435d06dc31387e0ea8ff6
program id f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d
11686 words against a cap of 4096: does not fit
To jest opublikowany hc etapu drugiego. Nazwa crate’a nie ma na niego wpływu.
4. Zbuduj wektor wejściowy i uruchom transfer
Przykład erc20_vector wypisuje wektory testu zgodności jako słowa wejściowe: transfer (ALICE wysyła BOB 250 ze swoich 1 000), approve (ALICE pozwala BOB wydać 5) i transferFrom (BOB przenosi 100 z 1 000 ALICE przy przydziale 300). Dla własnego kontraktu zbuduj EvmCall w Rust w ten sam sposób; przykład jest wzorcem.
$ (cd evm2rv && cargo +1.98.1 run -q --release --example erc20_vector -- transfer > target/transfer.words)
921 input words
$ rand-guest/target/release/rand-guest run evm2rv/target/mytoken/image.bin --input $(cat evm2rv/target/transfer.words)
out[0] = 1
out[1] = 513227413
out[2] = 3087537901
out[3] = 995619457
out[4] = 4004100029
out[5] = 234390638
out[6] = 3262201797
out[7] = 3842361427
cycles 66235
tier 18
5. Porównaj z interpreterem
To samo wejście w gościu interpretera:
$ rand-guest/target/release/rand-guest run guests-compiled/bin/evm.bin --input $(cat evm2rv/target/transfer.words)
out[0] = 1
out[1] = 513227413
out[2] = 3087537901
out[3] = 995619457
out[4] = 4004100029
out[5] = 234390638
out[6] = 3262201797
out[7] = 3842361427
cycles 121638
tier 18
And the interpreter run natively on the host, the tests’ oracle: → Oraz interpreter uruchomiony natywnie na hoście, wyrocznia dla testów:
$ (cd evm2rv && cargo +1.98.1 run -q --release --example erc20_vector -- transfer --expected)
out[0] = 1
out[1] = 513227413
…
out[7] = 3842361427
interpreter (native): status 1, Return, gas_used 29956
Sprawdzenie w jednym poleceniu:
$ diff <(rand-guest/target/release/rand-guest run evm2rv/target/mytoken/image.bin --input $(cat evm2rv/target/transfer.words) | grep '^out') \
<(rand-guest/target/release/rand-guest run guests-compiled/bin/evm.bin --input $(cat evm2rv/target/transfer.words) | grep '^out') \
&& echo "the eight words are identical"
the eight words are identical
Powtórz kroki 4 i 5 dla approve i transferFrom; oba dają identyczne słowa. cd evm2rv && cargo +1.98.1 test --release uruchamia je oraz pięć dalszych wektorów w obu etapach, a także sprawdza gas_used (70 testów oraz 2 pominięte dowody).
| przetłumaczony (etap drugi) | interpreter (evm.bin) | |
|---|---|---|
| osiem słów wyjściowych | identyczne | identyczne |
| cykle, transfer | 66 235 | 121 638 |
| poziom | 18 | 18 |
| słowa programu | 11 686 | 18 009 |
6. Wdrożenie
rand program deploy evm2rv/target/mytoken/image.bin
Portfel wypisuje identyfikator programu, liczbę słów i hc, a następnie sprawdza limit łańcucha, zanim wygeneruje jakikolwiek dowód. Obraz ma 11 686 słów, więc wymaga łańcucha, którego genesis ustawia max_program_words na co najmniej 11 686. Łańcuch 12 działał z domyślną wartością 4 096, więc wdrożenie zostało tam odrzucone. Łańcuch 13, łańcuch wersji v0.4, ustawił max_program_words na 65 535 i każdy kolejny łańcuch zachowuje tę wartość. Łańcuch 20, aktualny łańcuch (genesis 6210cf071a390d7ac61d8cbea5dd9d139d1a493a862b54a45a498f36af2d5135), zachowuje także limity bloku, koperty wywołania i danych publicznych z łańcucha 13, a limit dowodu zmniejsza o połowę do 4 MiB (4 194 304 bajtów, od łańcucha 17; łańcuchy od 13 do 16 ustawiały 8 MiB). Limit słów nie jest już jedyną bramką. Genesis łańcucha 20 ustawia hardening_v6, a przy nim wdrożenie programu o większej liczbie słów, niż może pomieścić wywołanie przy limicie wywołania poziomu 14, jest nieprawidłowe (ProgramUncallable): co najwyżej 8 180 słów bez danych publicznych. Ten obraz ma 11 686 słów, więc łańcuch 20 odrzuca wdrożenie i odrzuciłby też wywołania: każde wywołanie ERC-20 generuje dowód na poziomie 16 lub 18, powyżej limitu wywołania poziomu 14 (krok 7). Agregacja bloków jest na łańcuchu 20 wyłączona (jego genesis nie ma sekcji aggregation); jego węzły startowe są wymienione w Uruchamianie walidatora. Opłata za wdrożenie wynosi 0.001 + 0.0001 × 11,686 = 1,1696 RAND, czyli tyle, ile zapłaciło wdrożenie w łańcuchu 13 opisane poniżej.
To wdrożenie odbyło się w łańcuchu 13 w dniu 2026-09-19, gdy łańcuch 13 był aktualnym łańcuchem (produkcyjny profil FRI, genesis 8123ccac1883a45750e4df6964fb7cd3f0b321798cde4c0ef406a0293939ece3), z genesisowego portfela shielded-1. Każdy kolejny łańcuch (od 14 do 19) został uruchomiony od nowa, bez programów łańcucha 13, a obraz nie został w żadnym z nich wdrożony ponownie, więc poniższa transakcja i wysokość należą do łańcucha 13 i nie wyświetlają się już w eksploratorze. Identyfikator programu jest skrótem samych base_pc i słów, więc ten sam obraz dostaje ten sam identyfikator w każdym łańcuchu, który dopuszcza wdrożenie. Wyjście portfela, z pominiętymi liniami postępu (…):
$ rand program deploy <image.bin>
program id: f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d (11686 words, hc 92aefea0951c31a717574962aeb70e10a37012a7d035d48e8713c36df68feae0)
…
proved in 92.2s: tier 14, 1419655 bytes
submitted deploy c7a66dc4d9cdb7f9bfc4bde01f618c356e5abad7097e6bf7dc04e2e49c53acd0
…
| identyfikator programu | f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d |
| obraz | 11 686 słów; hc a0feae92… w zapisie rand-guest, 92aefea0… w zapisie portfela |
| pakiet opłaty (pakiet 2-in-2-out łańcucha 13) | poziom 14, 1 419 655 bajtów, dowód w 92,2 s |
| transakcja wdrożenia (łańcuch 13) | c7a66dc4d9cdb7f9bfc4bde01f618c356e5abad7097e6bf7dc04e2e49c53acd0 |
| zatwierdzona na wysokości (łańcuch 13) | 381 |
Od łańcucha 14 pakietem płacącym jest jeden pakiet 4-in-4-out z ukrytym aktywem, który niesie każda transakcja, udowodniony względem wiązania transakcji. Nadal jest to poziom 14: około 100 s i około 1,42 MB przy profilu produkcyjnym w łańcuchach 14 i 15. Od łańcucha 17 pakiet niesie także dowód uwierzytelnienia poziomu 10 (podzielona autoryzacja), więc w łańcuchach 18 i 19 pakiet opłaty transakcji to około 1,49 MB dowodu pakietu i około 1,37 MB dowodu uwierzytelnienia.
7. Wywołanie
Wywołanie transferu niesie wektor 921 słów jako dane prywatne, mieszczący się w limicie danych wejściowych w każdym łańcuchu (domyślnie 4 295 słów, 16 071 w łańcuchu 20), i żadnych słów publicznych. Nie można go przesłać do łańcucha 20: program nie może tam zostać wdrożony (krok 6), transfer generuje dowód na poziomie 18, a od fullnode v0.5.6 (2026-09-25) węzeł odrzuca każdy dowód wywołania powyżej poziomu 14 z błędem CallTierTooHigh, zanim zbuduje klucz weryfikatora. Poniższe polecenie generuje dowód lokalnie, a łańcuch odrzuca wynik; pomiary dotyczą dowodów poza łańcuchem. rand call przyjmuje każde słowo jako powtarzane --input:
rand call f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d \
$(for w in $(cat evm2rv/target/transfer.words); do printf -- '--input %s ' "$w"; done)
Teraz zmierzone. Dowód poziomu 18 został przerwany na 48-gigabajtowym laptopie przy 24,7 GB, ale na 128-gigabajtowym droplecie (m-16vcpu-128gb) przetłumaczone wywołanie transfer zostało udowodnione: szczytowe RSS 85,0 GB, 3 230,5 s (53,8 min), dowód o rozmiarze 811 600 bajtów. Został zweryfikowany w 101,4 s na droplecie oraz w 50,2 s przy 3,66 GB RSS na 48-gigabajtowym laptopie z procesorem Apple silicon (pamięć do generowania dowodów). Przy płaskim harmonogramie poziomów księgi, czyli regule w łańcuchach bez sekcji gas (do łańcucha 17), opłata za wywołanie na poziomie 18 wynosiła 0,0024 RAND. Łańcuchy 18 i 19 wyceniają wywołanie według zadeklarowanego limitu gazu i jego bajtów, przy cenach genesis 100 jednostek za gaz i 800 za KiB, i nie dopuszczają żadnego wywołania powyżej poziomu 14.
Wywołanie w łańcuchu 13, 2026-09-19
Wywołanie approve(BOB, 5) (649 słów prywatnych, poziom 16) odbyło się w łańcuchu 13 w dniu 2026-09-19, gdy był on aktualnym łańcuchem, z profilem produkcyjnym FRI, z tego samego portfela. Żadne wywołanie nie zostało wykonane w żadnym późniejszym łańcuchu, w którym program nie jest wdrożony, a łańcuch 20 odrzuca ten dowód wywołania poziomu 16 (CallTierTooHigh). Wyjście portfela, z pominiętymi liniami postępu (…):
$ rand call f074c4eb834cf01886a8241b6a2e0caf6e1cee5327fee6cb1a1a37436607280d --input <w0> --input <w1> … # the 649 words of approve(BOB, 5)
…
proved in 388.7s: tier 16, 3412405 bytes, outputs [1, 942495465, 790002515, 1351749335, 1059083501, 2923046783, 2814575942, 696258848]
…
proved in 96.0s: tier 14, 1420423 bytes
submitted call 279e1f62abf3f177ca71b08c633e051c37bc4720118c79ddb00936f036c4bfa7
…
| dowód wywołania | poziom 16, 3 412 405 bajtów, dowód w 388,7 s |
| pakiet opłaty (pakiet 2-in-2-out łańcucha 13) | poziom 14, 1 420 423 bajtów, dowód w 96,0 s |
| zapieczętowana koperta | 2 700 bajtów |
| transakcja wywołania (łańcuch 13) | 279e1f62abf3f177ca71b08c633e051c37bc4720118c79ddb00936f036c4bfa7 |
| zakotwiczona na / zatwierdzona na | wysokość 802 / wysokość 919 |
| opłata | 0,00357 RAND |
potwierdzenie h_pub | null |
| wyjścia potwierdzenia | równe ośmiu słowom interpretera dla tego samego wektora |
| czas rzeczywisty, szczytowe RSS | 622,8 s, 22,9 GB, na 48-gigabajtowym laptopie serii M |
- Dowód produkcyjny ma 3 412 405 bajtów, więc przekracza limit dowodu łańcucha 12 wynoszący 2 MiB. Łańcuch 12 nie mógł przyjąć tego wywołania; limit 8 MiB łańcucha 13 mógł. Łańcuchy od 14 do 16 zachowały ten sam limit, a łańcuchy od 17 do 20 ustawiają 4 MiB (4 194 304 bajtów), w który dowód tego rozmiaru nadal się mieści. Od v0.5.6 węzeł odrzuca wywołanie ze względu na jego poziom, zanim spojrzy na jego rozmiar.
- Opłata obejmuje składnik bajtowy harmonogramu łańcucha 13: dowód 3,41 MB przekracza bezpłatny limit 2 MiB + 18 432 bajtów. Od łańcucha 18 każde wywołanie płaci za KiB od bajtu 0.
Osiem słów potwierdzenia to te z kroku 4. Łańcuch nie przechowuje stanu EVM: wywołujący dostarcza korzeń stanu początkowego i świadectwa pamięci, a korzeń stanu końcowego znajduje się wewnątrz skrótu EVM_OUT.
Limity
- Brak kontekstu bloku. Dziewięć opkodów kontekstu bloku kończy się pułapką (trap), dopóki nie powstanie projekt wiązania z blokiem.
- Brak transferów wartości.
CALLz niezerową wartością kończy się pułapką. Wywołania kontraktów innych niż prekompilaty również kończą się pułapką. - ecrecover, bn256 mul, parowanie i duże modexp nie mogą być dziś udowodnione. Każde przekracza limit warstwy 2²⁰ wierszy; potrzebują tablic koprocesora.
- Brak stanu EVM w łańcuchu. Wywołanie to jeden dowód dla jednego przebiegu; stan przenosi wywołujący.
- Ani wdrożenie, ani żadne wywołanie ERC-20 nie jest dopuszczalne w chain 20. W ramach
hardening_v6chain 20 wdrożenie większej liczby słów, niż może pomieścić wywołanie warstwy 14, jest nieprawidłowe (ProgramUncallable; maksymalnie 8 180 słów), a obraz ma 11 686. Od fullnode v0.5.6 dowód wywołania musi należeć do warstwy 14 lub niższej (CallTierTooHigh);approvejest dowodzone w warstwie 16, atransferitransferFromw warstwie 18. Ta sama kontrola ogranicza tablice skrótów, które wywołanie może zadeklarować: 2¹² wierszy Keccak (128 permutacji) i 2¹³ wierszy SHA-256 (128 kompresji). Wywołania nadal dają się udowodnić poza łańcuchem, jak poniżej. - Indeks pamięci masowej ma głębokość 32 bitów.
evm-coreumieszcza liść pamięci kontraktu według górnych 32 bitówkeccak256(slot), więc slot kolidujący z wybranym kosztuje około 2³² skrótów Keccak do znalezienia, a dopóki przechowuje on niezerową wartość, wybrany slot jest zamrożony (bez fałszerstwa i bez utraty wartości). Jest to uśpione:evm.binma 18 009 słów, a wywołanie na limicie warstwy 14 mieści co najwyżej 8 184, więc żaden runtime EVM nie jest wywoływalny w żadnym łańcuchu. Plikdocs/confidential.mdw fullnode odnotowuje ten warunek wstępny obok limitu wywołań (audyt v6, ZKV-6; namainod 2026-09-30, po tagu v0.6.7): zanim łańcuch zniesie limit wywołań warstwy 14 lub dopuści runtime EVM na tyle mały, by dało się go wywołać, indeks pamięci masowej musi zostać pogłębiony, aevm.binponownie przypięty. - Udowodnione. Dowód transferu etapu pierwszego (warstwa 18) został zabity przez SIGKILL na laptopie z 48 GB przy 24,7 GB po 1 016 s, ale wywołanie
transferetapu drugiego zostało udowodnione na droplecie z 128 GB (m-16vcpu-128gb): szczytowe RSS 85,0 GB, 3 230,5 s (53,8 min), dowód o rozmiarze 811 600 bajtów, zweryfikowany w 101,4 s (droplet) i 50,2 s przy 3,66 GB RSS (laptop 48 GB). Dowód transferu dlaevm.bininterpretera był bardzo zbliżony: 85,5 GB, 3 143,3 s (52,4 min), dowód 805 108 bajtów — a oba dowody mają identyczne publiczne słowa wyjściowe, co potwierdza zgodność na prawdziwym proverze.approve(warstwa 16, przetłumaczony) jest znacznie tańszy: 21,7 GB, 786,7 s (13,1 min), dowód 798 930 bajtów. Translacja obniża koszt dowodzenia tylko wtedy, gdy przenosi wywołanie do mniejszej warstwy. - Łańcuch nie zapisuje bytecode’u. Opublikuj go, aby inni mogli odbudować
hc.