Porozumění specifikacím EVM v yellow paperu
Yellow paper (opens in a new tab) je formální specifikace Etherea. Kromě případů, kdy je pozměněn procesem EIP, obsahuje přesný popis toho, jak vše funguje. Je napsán jako matematický článek, což zahrnuje terminologii, která programátorům nemusí být povědomá. V tomto článku se dozvíte, jak jej číst, a v širším smyslu i další související matematické články.
Který yellow paper?
Jako téměř všechno ostatní v Ethereu se i yellow paper postupem času vyvíjí. Abych mohl odkazovat na konkrétní verzi, nahrál jsem aktuální verzi v době psaní. Čísla sekcí, stránek a rovnic, která používám, budou odkazovat na tuto verzi. Při čtení tohoto dokumentu je dobré mít jej otevřený v jiném okně.
Proč EVM?
Původní yellow paper byl napsán hned na začátku vývoje Etherea. Popisuje původní mechanismus konsensu založený na důkazu prací (PoW), který se původně používal k zabezpečení sítě. Ethereum však v září 2022 vypnulo důkaz prací a začalo používat konsensus založený na důkazu podílem (PoS). Tento tutoriál se zaměří na části yellow paperu definující virtuální stroj Etherea (EVM). EVM zůstal přechodem na důkaz podílem nezměněn (s výjimkou návratové hodnoty operačního kódu DIFFICULTY).
9 Exekuční model
Tato sekce (str. 12-14) obsahuje většinu definice EVM.
Pojem stav systému (system state) zahrnuje vše, co potřebujete o systému vědět, abyste jej mohli spustit. V typickém počítači to znamená paměť, obsah registrů atd.
Turingův stroj (opens in a new tab) je výpočetní model. V podstatě se jedná o zjednodušenou verzi počítače, u které je dokázáno, že má stejnou schopnost provádět výpočty jako normální počítač (vše, co dokáže spočítat počítač, dokáže spočítat i Turingův stroj a naopak). Tento model usnadňuje dokazování různých teorémů o tom, co je a co není vyčíslitelné.
Pojem Turingovsky úplný (opens in a new tab) označuje počítač, který dokáže provádět stejné výpočty jako Turingův stroj. Turingovy stroje se mohou dostat do nekonečných smyček, což EVM nemůže, protože by mu došel gas, takže je pouze kvazi-Turingovsky úplný.
9.1 Základy
Tato sekce popisuje základy EVM a jeho srovnání s jinými výpočetními modely.
Zásobníkový stroj (opens in a new tab) je počítač, který neukládá mezivýsledky do registrů, ale do zásobníku (opens in a new tab). Toto je preferovaná architektura pro virtuální stroje, protože se snadno implementuje, což znamená, že chyby a bezpečnostní zranitelnosti jsou mnohem méně pravděpodobné. Paměť v zásobníku je rozdělena na 256bitová slova. To bylo zvoleno, protože je to výhodné pro základní kryptografické operace Etherea, jako je hashování Keccak-256 a výpočty na eliptické křivce. Maximální velikost zásobníku je 1024 položek (1024 x 256 bitů). Když se provádějí operační kódy, obvykle získávají své parametry ze zásobníku. Existují operační kódy určené speciálně pro reorganizaci prvků v zásobníku, jako je POP (odstraní položku z vrcholu zásobníku), DUP_N (duplikuje N-tou položku v zásobníku) atd.
EVM má také volatilní prostor zvaný paměť (memory), který se používá k ukládání dat během provádění. Tato paměť je organizována do 32bajtových slov. Všechna paměťová místa jsou inicializována na nulu. Pokud spustíte tento kód v jazyce Yul (opens in a new tab) pro přidání slova do paměti, zaplní 32 bajtů paměti tím, že prázdné místo ve slově vyplní nulami, tj. vytvoří jedno slovo – s nulami na pozicích 0-29, 0x60 na 30 a 0xA7 na 31.
mstore(0, 0x60A7)
mstore je jedním ze tří operačních kódů, které EVM poskytuje pro interakci s pamětí – načte slovo do paměti. Další dva jsou mstore8, který načte jeden bajt do paměti, a mload, který přesune slovo z paměti do zásobníku.
EVM má také samostatný nevolatilní model úložiště (storage), který je udržován jako součást stavu systému – tato paměť je organizována do polí slov (na rozdíl od polí bajtů adresovatelných po slovech v zásobníku). V tomto úložišti kontrakty uchovávají trvalá data – kontrakt může interagovat pouze se svým vlastním úložištěm. Úložiště je organizováno v mapování klíč-hodnota.
Ačkoli to v této sekci yellow paperu není zmíněno, je také užitečné vědět, že existuje čtvrtý typ paměti. Data volání (calldata) je bajtově adresovatelná paměť pouze pro čtení, která se používá k uložení hodnoty předané s parametrem data transakce. EVM má specifické operační kódy pro správu calldata. calldatasize vrací velikost dat. calldataload načte data do zásobníku. calldatacopy zkopíruje data do paměti.
Standardní von Neumannova architektura (opens in a new tab) ukládá kód a data do stejné paměti. EVM se tímto standardem z bezpečnostních důvodů neřídí – sdílení volatilní paměti by umožnilo měnit kód programu. Místo toho se kód ukládá do úložiště.
Existují pouze dva případy, kdy se kód spouští z paměti:
- Když kontrakt vytvoří jiný kontrakt (pomocí
CREATE(opens in a new tab) neboCREATE2(opens in a new tab)), kód pro konstruktor kontraktu pochází z paměti. - Během vytváření jakéhokoli kontraktu se spustí kód konstruktoru a poté se vrátí s kódem samotného kontraktu, rovněž z paměti.
Pojem výjimečné provedení (exceptional execution) znamená výjimku, která způsobí zastavení provádění aktuálního kontraktu.
9.2 Přehled poplatků
Tato sekce vysvětluje, jak se počítají poplatky za gas. Existují tři druhy nákladů:
Cena operačního kódu
Základní cena konkrétního operačního kódu. Chcete-li získat tuto hodnotu, najděte nákladovou skupinu operačního kódu v příloze H (str. 28, pod rovnicí (327)) a najděte nákladovou skupinu v rovnici (324). Tím získáte nákladovou funkci, která ve většině případů používá parametry z přílohy G (str. 27).
Například operační kód CALLDATACOPY (opens in a new tab) je členem skupiny Wcopy. Cena operačního kódu pro tuto skupinu je Gverylow+Gcopy×⌈μs[2]÷32⌉. Při pohledu na přílohu G vidíme, že obě konstanty jsou 3, což nám dává 3+3×⌈μs[2]÷32⌉.
Stále musíme rozluštit výraz ⌈μs[2]÷32⌉. Vnější část, ⌈ <hodnota> ⌉, je funkce horní celá část (ceiling), funkce, která pro danou hodnotu vrací nejmenší celé číslo, které není menší než tato hodnota. Například ⌈2.5⌉ = ⌈3⌉ = 3. Vnitřní část je μs[2]÷32. Při pohledu na sekci 3 (Konvence) na str. 3 je μ stav stroje. Stav stroje je definován v sekci 9.4.1 na str. 13. Podle této sekce je jedním z parametrů stavu stroje s pro zásobník. Když to dáme všechno dohromady, zdá se, že μs[2] je pozice č. 2 v zásobníku. Při pohledu na operační kód (opens in a new tab) je pozice č. 2 v zásobníku velikost dat v bajtech. Při pohledu na ostatní operační kódy ve skupině Wcopy, CODECOPY (opens in a new tab) a RETURNDATACOPY (opens in a new tab), mají také velikost dat na stejné pozici. Takže ⌈μs[2]÷32⌉ je počet 32bajtových slov potřebných k uložení kopírovaných dat. Když to všechno shrneme, základní cena CALLDATACOPY (opens in a new tab) je 3 gas plus 3 za každé slovo kopírovaných dat.
Cena za spuštění
Cena za spuštění kódu, který voláme.
- V případě
CREATE(opens in a new tab) aCREATE2(opens in a new tab) jde o konstruktor nového kontraktu. - V případě
CALL(opens in a new tab),CALLCODE(opens in a new tab),STATICCALL(opens in a new tab) neboDELEGATECALL(opens in a new tab) jde o kontrakt, který voláme.
Cena za rozšíření paměti
Cena za rozšíření paměti (pokud je to nutné).
V rovnici 324 je tato hodnota zapsána jako Cmem(μi')-Cmem(μi). Při opětovném pohledu na sekci 9.4.1 vidíme, že μi je počet slov v paměti. Takže μi je počet slov v paměti před operačním kódem a μi' je počet slov v paměti po operačním kódu.
Funkce Cmem je definována v rovnici 326: Cmem(a) = Gmemory × a + ⌊a2 ÷ 512⌋. ⌊x⌋ je funkce dolní celá část (floor), funkce, která pro danou hodnotu vrací největší celé číslo, které není větší než tato hodnota. Například ⌊2.5⌋ = ⌊2⌋ = 2. Když a < √512, a2 < 512 a výsledek funkce dolní celá část je nula. Takže pro prvních 22 slov (704 bajtů) cena roste lineárně s počtem požadovaných paměťových slov. Za tímto bodem je ⌊a2 ÷ 512⌋ kladné. Když je požadovaná paměť dostatečně velká, cena gasu je úměrná druhé mocnině množství paměti.
Poznámka: Tyto faktory ovlivňují pouze základní cenu gasu – nezohledňují trh s poplatky ani spropitné pro validátory, které určují, kolik musí koncový uživatel zaplatit – jedná se pouze o hrubou cenu za spuštění konkrétní operace na EVM.
9.3 Exekuční prostředí
Exekuční prostředí je n-tice, I, která obsahuje informace, jež nejsou součástí stavu blockchainu ani EVM.
| Parametr | Operační kód pro přístup k datům | Kód v Solidity pro přístup k datům |
|---|---|---|
| Ia | ADDRESS (opens in a new tab) | address(this) |
| Io | ORIGIN (opens in a new tab) | tx.origin |
| Ip | GASPRICE (opens in a new tab) | tx.gasprice |
| Id | CALLDATALOAD (opens in a new tab), atd. | msg.data |
| Is | CALLER (opens in a new tab) | msg.sender |
| Iv | CALLVALUE (opens in a new tab) | msg.value |
| Ib | CODECOPY (opens in a new tab) | address(this).code |
| IH | Pole hlavičky bloku, jako je NUMBER (opens in a new tab) a DIFFICULTY (opens in a new tab) | block.number, block.difficulty, atd. |
| Ie | Hloubka zásobníku volání pro volání mezi kontrakty (včetně vytváření kontraktů) | |
| Iw | Zda má EVM povoleno měnit stav, nebo zda běží staticky |
K pochopení zbytku sekce 9 je nezbytných několik dalších parametrů:
| Parametr | Definováno v sekci | Význam |
|---|---|---|
| σ | 2 (str. 2, rovnice 1) | Stav blockchainu |
| g | 9.3 (str. 13) | Zbývající gas |
| A | 6.1 (str. 8) | Nahromaděný podstav (změny naplánované na konec transakce) |
| o | 9.3 (str. 13) | Výstup – vrácený výsledek v případě interní transakce (když jeden kontrakt volá jiný) a volání view funkcí (když pouze žádáte o informace, takže není třeba čekat na transakci) |
9.4 Přehled provádění
Nyní, když máme všechny přípravy za sebou, můžeme konečně začít pracovat na tom, jak EVM funguje.
Rovnice 137-142 nám dávají počáteční podmínky pro spuštění EVM:
| Symbol | Počáteční hodnota | Význam |
|---|---|---|
| μg | g | Zbývající gas |
| μpc | 0 | Čítač programu, adresa další instrukce k provedení |
| μm | (0, 0, ...) | Paměť, inicializovaná na samé nuly |
| μi | 0 | Nejvyšší použité paměťové místo |
| μs | () | Zásobník, zpočátku prázdný |
| μo | ∅ | Výstup, prázdná množina, dokud se nezastavíme buď s návratovými daty (RETURN (opens in a new tab) nebo REVERT (opens in a new tab)), nebo bez nich (STOP (opens in a new tab) nebo SELFDESTRUCT (opens in a new tab)). |
Rovnice 143 nám říká, že v každém okamžiku během provádění existují čtyři možné stavy a co s nimi dělat:
Z(σ,μ,A,I). Z představuje funkci, která testuje, zda operace vytváří neplatný přechod stavu (viz výjimečné zastavení). Pokud se vyhodnotí jako True, nový stav je identický se starým (kromě toho, že se spálí gas), protože změny nebyly implementovány.- Pokud je prováděným operačním kódem
REVERT(opens in a new tab), nový stav je stejný jako starý stav, část gasu je ztracena. - Pokud je sekvence operací dokončena, což je signalizováno pomocí
RETURN(opens in a new tab)), stav se aktualizuje na nový stav. - Pokud nejsme v jedné z koncových podmínek 1-3, pokračujeme v běhu.
9.4.1 Stav stroje
Tato sekce podrobněji vysvětluje stav stroje. Specifikuje, že w je aktuální operační kód. Pokud je μpc menší než ||Ib||, což je délka kódu, pak je tento bajt (Ib[μpc]) operačním kódem. V opačném případě je operační kód definován jako STOP (opens in a new tab).
Jelikož se jedná o zásobníkový stroj (opens in a new tab), musíme sledovat počet položek vyjmutých (δ) a vložených (α) každým operačním kódem.
9.4.2 Výjimečné zastavení
Tato sekce definuje funkci Z, která specifikuje, kdy dojde k abnormálnímu ukončení. Jedná se o booleovskou (opens in a new tab) funkci, takže používá ∨ pro logické NEBO (OR) (opens in a new tab) a ∧ pro logické A (AND) (opens in a new tab).
K výjimečnému zastavení dojde, pokud je splněna kterákoli z těchto podmínek:
-
μg < C(σ,μ,A,I) Jak jsme viděli v sekci 9.2, C je funkce, která specifikuje cenu gasu. Nezbývá dostatek gasu na pokrytí dalšího operačního kódu.
-
δw=∅ Pokud je počet vyjmutých položek pro operační kód nedefinovaný, pak je nedefinovaný i samotný operační kód.
-
|| μs || < δw Podtečení zásobníku, v zásobníku není dostatek položek pro aktuální operační kód.
-
w = JUMP ∧ μs[0]∉D(Ib) Operační kód je
JUMP(opens in a new tab) a adresa neníJUMPDEST(opens in a new tab). Skoky jsou platné pouze tehdy, když je cílemJUMPDEST(opens in a new tab). -
w = JUMPI ∧ μs[1]≠0 ∧ μs[0] ∉ D(Ib) Operační kód je
JUMPI(opens in a new tab), podmínka je pravdivá (nenulová), takže by měl proběhnout skok, a adresa neníJUMPDEST(opens in a new tab). Skoky jsou platné pouze tehdy, když je cílemJUMPDEST(opens in a new tab). -
w = RETURNDATACOPY ∧ μs[1]+μs[2]>|| μo || Operační kód je
RETURNDATACOPY(opens in a new tab). V tomto operačním kódu je prvek zásobníku μs[1] offset, ze kterého se má číst v bufferu návratových dat, a prvek zásobníku μs[2] je délka dat. Tato podmínka nastane, když se pokusíte číst za koncem bufferu návratových dat. Všimněte si, že pro data volání (calldata) nebo pro samotný kód podobná podmínka neexistuje. Když se pokusíte číst za koncem těchto bufferů, dostanete jednoduše nuly. -
|| μs || - δw + αw > 1024
Přetečení zásobníku. Pokud spuštění operačního kódu povede k zásobníku s více než 1024 položkami, dojde k přerušení.
-
¬Iw ∧ W(w,μ) Běžíme staticky (¬ je negace (opens in a new tab) a Iw je pravda, když máme povoleno měnit stav blockchainu)? Pokud ano a pokoušíme se o operaci měnící stav, nemůže k ní dojít.
Funkce W(w,μ) je definována později v rovnici 150. W(w,μ) je pravda, pokud je splněna jedna z těchto podmínek:
-
w ∈ {CREATE, CREATE2, SSTORE, SELFDESTRUCT} Tyto operační kódy mění stav, ať už vytvořením nového kontraktu, uložením hodnoty nebo zničením aktuálního kontraktu.
-
LOG0≤w ∧ w≤LOG4 Pokud jsme voláni staticky, nemůžeme emitovat záznamy logu. Všechny operační kódy logu jsou v rozsahu mezi
LOG0(A0) (opens in a new tab) aLOG4(A4) (opens in a new tab). Číslo za operačním kódem logu určuje, kolik témat (topics) záznam logu obsahuje. -
w=CALL ∧ μs[2]≠0 Můžete zavolat jiný kontrakt, když jste statičtí, ale pokud tak učiníte, nemůžete na něj převést ETH.
-
-
w = SSTORE ∧ μg ≤ Gcallstipend Nemůžete spustit
SSTORE(opens in a new tab), pokud nemáte více než Gcallstipend (definováno jako 2300 v příloze G) gasu.
9.4.3 Platnost cíle skoku
Zde formálně definujeme, co jsou operační kódy JUMPDEST (opens in a new tab). Nemůžeme jednoduše hledat bajtovou hodnotu 0x5B, protože by mohla být uvnitř PUSH (a tedy by šlo o data, nikoli o operační kód).
V rovnici (153) definujeme funkci N(i,w). První parametr, i, je pozice operačního kódu. Druhý, w, je samotný operační kód. Pokud w∈[PUSH1, PUSH32], znamená to, že operační kód je PUSH (hranaté závorky definují rozsah, který zahrnuje koncové body). V takovém případě je další operační kód na i+2+(w−PUSH1). Pro PUSH1 (opens in a new tab) se musíme posunout o dva bajty (samotný PUSH a jednobajtová hodnota), pro PUSH2 (opens in a new tab) se musíme posunout o tři bajty, protože jde o dvoubajtovou hodnotu atd. Všechny ostatní operační kódy EVM jsou dlouhé pouze jeden bajt, takže ve všech ostatních případech N(i,w)=i+1.
Tato funkce se používá v rovnici (152) k definování DJ(c,i), což je množina (opens in a new tab) všech platných cílů skoku v kódu c, počínaje pozicí operačního kódu i. Tato funkce je definována rekurzivně. Pokud i≥||c||, znamená to, že jsme na konci kódu nebo za ním. Už nenajdeme žádné další cíle skoku, takže jednoduše vrátíme prázdnou množinu.
Ve všech ostatních případech se podíváme na zbytek kódu tak, že přejdeme na další operační kód a získáme množinu začínající od něj. c[i] je aktuální operační kód, takže N(i,c[i]) je pozice dalšího operačního kódu. DJ(c,N(i,c[i])) je tedy množina platných cílů skoku, která začíná na dalším operačním kódu. Pokud aktuální operační kód není JUMPDEST, jednoduše vraťte tuto množinu. Pokud je to JUMPDEST, zahrňte jej do výsledné množiny a tu vraťte.
9.4.4 Normální zastavení
Funkce zastavení H může vracet tři typy hodnot.
- Pokud nejsme v operačním kódu zastavení, vraťte ∅, prázdnou množinu. Podle konvence je tato hodnota interpretována jako booleovská nepravda (false).
- Pokud máme operační kód zastavení, který neprodukuje výstup (buď
STOP(opens in a new tab) neboSELFDESTRUCT(opens in a new tab)), vraťte jako návratovou hodnotu sekvenci o velikosti nula bajtů. Všimněte si, že se to velmi liší od prázdné množiny. Tato hodnota znamená, že se EVM skutečně zastavil, jen nejsou k dispozici žádná návratová data ke čtení. - Pokud máme operační kód zastavení, který produkuje výstup (buď
RETURN(opens in a new tab) neboREVERT(opens in a new tab)), vraťte sekvenci bajtů specifikovanou tímto operačním kódem. Tato sekvence je převzata z paměti, hodnota na vrcholu zásobníku (μs[0]) je první bajt a hodnota za ní (μs[1]) je délka.
H.2 Instrukční sada
Než přejdeme k závěrečné podsekci EVM, 9.5, podívejme se na samotné instrukce. Jsou definovány v příloze H.2, která začíná na str. 29. Očekává se, že cokoli, co není specifikováno jako měnící se s tímto konkrétním operačním kódem, zůstane stejné. Proměnné, které se mění, jsou specifikovány jako <něco>′.
Podívejme se například na operační kód ADD (opens in a new tab).
| Hodnota | Mnemotechnika | δ | α | Popis |
|---|---|---|---|---|
| 0x01 | ADD | 2 | 1 | Operace sčítání. |
| μ′s[0] ≡ μs[0] + μs[1] |
δ je počet hodnot, které vyjmeme ze zásobníku. V tomto případě dvě, protože sčítáme dvě vrchní hodnoty.
α je počet hodnot, které vložíme zpět. V tomto případě jedna, součet.
Takže nový vrchol zásobníku (μ′s[0]) je součtem starého vrcholu zásobníku (μs[0]) a staré hodnoty pod ním (μs[1]).
Místo toho, abychom procházeli všechny operační kódy pomocí „seznamu, ze kterého přechází zrak“, tento článek vysvětluje pouze ty operační kódy, které přinášejí něco nového.
| Hodnota | Mnemotechnika | δ | α | Popis |
|---|---|---|---|---|
| 0x20 | KECCAK256 | 2 | 1 | Vypočítá hash Keccak-256. |
| μ′s[0] ≡ KEC(μm[μs[0] . . . (μs[0] + μs[1] − 1)]) | ||||
| μ′i ≡ M(μi,μs[0],μs[1]) |
Toto je první operační kód, který přistupuje k paměti (v tomto případě pouze pro čtení). Může se však rozšířit za aktuální limity paměti, takže musíme aktualizovat μi. Děláme to pomocí funkce M definované v rovnici 328 na str. 29.
| Hodnota | Mnemotechnika | δ | α | Popis |
|---|---|---|---|---|
| 0x31 | BALANCE | 1 | 1 | Získá zůstatek daného účtu. |
| ... |
Adresa, jejíž zůstatek potřebujeme zjistit, je μs[0] mod 2160. Na vrcholu zásobníku je adresa, ale protože adresy mají pouze 160 bitů, počítáme hodnotu modulo (opens in a new tab) 2160.
Pokud σ[μs[0] mod 2160] ≠ ∅, znamená to, že o této adrese existují informace. V tom případě je σ[μs[0] mod 2160]b zůstatek pro tuto adresu. Pokud σ[μs[0] mod 2160] = ∅, znamená to, že tato adresa není inicializována a zůstatek je nula. Seznam polí s informacemi o účtu si můžete prohlédnout v sekci 4.1 na str. 4.
Druhá rovnice, A'a ≡ Aa ∪ {μs[0] mod 2160}, souvisí s rozdílem v ceně mezi přístupem k teplému úložišti (warm storage – úložiště, ke kterému se nedávno přistupovalo a pravděpodobně je v mezipaměti) a studenému úložišti (cold storage – úložiště, ke kterému se nepřistupovalo a pravděpodobně je v pomalejším úložišti, jehož načtení je dražší). Aa je seznam adres, ke kterým transakce dříve přistupovala, a proto by k nim měl být přístup levnější, jak je definováno v sekci 6.1 na str. 8. Více si o tomto tématu můžete přečíst v EIP-2929 (opens in a new tab).
| Hodnota | Mnemotechnika | δ | α | Popis |
|---|---|---|---|---|
| 0x8F | DUP16 | 16 | 17 | Duplikuje 16. položku zásobníku. |
| μ′s[0] ≡ μs[15] |
Všimněte si, že abychom mohli použít jakoukoli položku zásobníku, musíme ji vyjmout, což znamená, že musíme vyjmout i všechny položky zásobníku nad ní. V případě DUP<n> (opens in a new tab) a SWAP<n> (opens in a new tab) to znamená nutnost vyjmout a poté vložit až šestnáct hodnot.
9.5 Exekuční cyklus
Nyní, když máme všechny části, můžeme konečně pochopit, jak je dokumentován exekuční cyklus EVM.
Rovnice (155) říká, že vzhledem ke stavu:
- σ (globální stav blockchainu)
- μ (stav EVM)
- A (podstav, změny, které nastanou po skončení transakce)
- I (exekuční prostředí)
Nový stav je (σ', μ', A', I').
Rovnice (156)-(158) definují zásobník a jeho změnu v důsledku operačního kódu (μs). Rovnice (159) je změna gasu (μg). Rovnice (160) je změna čítače programu (μpc). Nakonec rovnice (161)-(164) specifikují, že ostatní parametry zůstávají stejné, pokud nejsou explicitně změněny operačním kódem.
Tímto je EVM plně definován.
Závěr
Matematický zápis je přesný a umožnil yellow paperu specifikovat každý detail Etherea. Má však i některé nevýhody:
- Mohou mu porozumět pouze lidé, což znamená, že testy shody (opens in a new tab) musí být psány ručně.
- Programátoři rozumí počítačovému kódu. Matematickému zápisu rozumět mohou, ale nemusí.
Možná z těchto důvodů jsou novější specifikace vrstvy konsensu (opens in a new tab) napsány v jazyce Python. Existují specifikace exekuční vrstvy v Pythonu (opens in a new tab), ale nejsou kompletní. Dokud a pokud nebude celý yellow paper také přeložen do Pythonu nebo podobného jazyka, bude yellow paper i nadále sloužit a je užitečné umět jej číst.