EVM a gas

Virtuální stroj, za co se platí a proč to jde tak snadno přestřelit.

Co se naučíš: Budeš vědět, za co se přesně platí a proč je zápis do úložiště tisíckrát dražší než výpočet.

5 min čtení + cvičeníNavazuje na:📜 Smart kontrakty

Kontrakt musí spustit každý uzel a všem musí vyjít totéž. K tomu je potřeba stroj se zcela předvídatelným chováním a způsob, jak zabránit tomu, aby někdo poslal nekonečnou smyčku a zastavil celou síť.

První řeší virtuální stroj, druhé gas.


Proč vlastní virtuální stroj

Kdyby kontrakty běžely přímo na procesoru, lišily by se výsledky mezi architekturami, verzemi knihoven a nastavením. Virtuální stroj definuje chování do posledního detailu: kolik bitů má číslo, co se stane při přetečení, v jakém pořadí se co vykoná.

Tím se získá vlastnost, bez které by to nefungovalo: stejný vstup dá na každém stroji na světě stejný výstup.


Gas: účtenka za každou instrukci

Kdyby bylo provádění zdarma, poslal by někdo nekonečnou smyčku a síť by se zastavila. Nejde to vyřešit časovým limitem, protože „jak dlouho to běželo" se na různých strojích liší, a shoda by se rozpadla.

Řešení je počítat kroky, ne čas. Každá instrukce má pevnou cenu v jednotkách zvaných gas:

OperaceŘádová cena
Sčítání, porovnáníjednotky
Hashdesítky
Čtení z úložištěstovky až tisíce
Zápis do úložištědesítky tisíc
Vytvoření kontraktudesítky tisíc

Ta tabulka je nejdůležitější věc celé kapitoly. Zápis do trvalého úložiště je řádově dražší než výpočet. Je to naopak, než jsi zvyklý: v běžném programu je paměť levná a výpočet drahý, tady je to obráceně, protože úložiště musí navždy držet každý uzel na světě.


Jak se platí

Odesílatel nastaví dvě věci:

  • Limit gasu, tedy kolik kroků je ochoten zaplatit. Když dojde, provádění se přeruší, změny se zahodí, ale poplatek propadá, protože práci uzly odvedly.
  • Cenu za jednotku gasu, což je nabídka v aukci o místo v bloku.

Odtud plyne past, na kterou lidé narazí: neúspěšná transakce taky stojí peníze. Nedostaneš nic a zaplatíš, protože se počítalo.


Co to znamená pro návrh kontraktu

Cena za kroky mění, co je dobrý kód:

  • Cyklus přes pole, které roste, je časovaná bomba. Když se pole rozroste, průchod přeleze limit bloku a funkce se stane neproveditelnou navždy. Řeší se stránkováním nebo tím, že se práce přesune na uživatele.
  • Ukládej co nejmíň. Co jde dopočítat, nedrž v úložišti. Co jde nechat mimo blockchain, nech mimo.
  • Vracení prostředků je levnější než jejich rozesílání. Místo aby kontrakt poslal peníze stovce lidí, nechá si je vyzvednout. Ušetří to gas a odstraní to celou třídu chyb.

Ten poslední bod má i bezpečnostní rozměr, ke kterému se vrátíme v kapitole o reentrancy.


Cvičení

  1. Transakce spadne kvůli chybě v kontraktu. Dostaneš poplatek zpátky?
  2. Proč je zápis do úložiště tisíckrát dražší než sčítání?
  3. Kontrakt rozesílá odměny cyklem přes seznam účastníků. Co se stane, až jich bude deset tisíc?
Náčrt řešení: rozbal, až si cvičení zkusíš sám
  1. Ne. Provádění se přeruší a všechny změny stavu se vrátí, jako by se nic nestalo, ale spotřebovaný gas se neproplácí. Uzly totiž tu práci skutečně odvedly a musí za ni být zaplaceny, jinak by šlo síť zdarma zaměstnávat neúspěšnými transakcemi. Vrátí se ti jen nespotřebovaná část limitu.
  2. Protože výsledek zápisu musí navždy uchovávat každý uzel na světě. Sčítání proběhne jednou a zmizí, kdežto uložená hodnota zvětší stav, který musí každý plný uzel držet a synchronizovat po celou dobu existence sítě. Cena tedy neodráží náklad na provedení, ale náklad na trvalé břemeno pro celou síť. Proto se také za uvolnění úložiště vrací část gasu.
  3. Funkce se stane neproveditelnou. Cena poroste s délkou seznamu, až průchod překročí limit gasu na blok, a od té chvíle transakce vždycky selže, přičemž poplatek propadne. Prostředky mohou zůstat v kontraktu trvale zamčené. Správný návrh proto nechá každého, aby si svůj podíl vyzvedl sám, čímž se cena rozdělí a nikdy nenaroste nad limit.

Shrnutí

  • Virtuální stroj definuje chování do detailu, aby všem uzlům vyšel stejný výsledek.
  • Gas počítá kroky, ne čas, protože čas se mezi stroji liší a shoda by se rozpadla.
  • Zápis do úložiště je řádově dražší než výpočet, opačně než v běžném programování.
  • Neúspěšná transakce poplatek nevrací, protože práce byla vykonána.
  • Cyklus přes rostoucí kolekci může funkci navždy znemožnit; nech uživatele vyzvedávat.
Proč se v blockchainu měří provádění v krocích a ne v čase?

Protože čas se na různých strojích liší, takže by uzly došly k různým závěrům o tom, jestli transakce prošla. Počet vykonaných instrukcí je naopak deterministický a všem vyjde stejně. Každá instrukce má pevnou cenu a odesílatel předem stanoví limit, kolik jich zaplatí.

Proč je zápis do úložiště tak drahý?

Protože uloženou hodnotu musí trvale držet a synchronizovat každý plný uzel v síti, zatímco výpočet proběhne jednou a zmizí. Cena tedy odráží dlouhodobé břemeno pro celou síť, ne náklad jednoho provedení. Za uvolnění úložiště se proto část gasu vrací.

Proč je lepší nechat uživatele vyzvednout si prostředky, než je rozesílat cyklem?

Protože cena cyklu roste s počtem příjemců a jednou překročí limit na blok, čímž se funkce stane trvale neproveditelnou a prostředky mohou zůstat zamčené. Při vyzvedávání platí každý uživatel za svou transakci sám, cena je konstantní a odpadá i celá třída chyb spojených s voláním cizích adres.