Hlavní navigace

Bitcoin Script a Ethereum Solidity: něžný úvod do programovacích jazyků

 Autor: Depositphotos
Co je to vlastně programovací jazyk? Vysvětlujeme si trošku netradičně na dvou příkladech z oblasti kryptoměn: bitcoinovém Scriptu a ethereovém Solidity. Tyto dva protipóly totiž ukazují, že jazyk musí často odpovídat konkrétnímu účelu.
Josef Tetek 15. 9. 2020
Doba čtení: 9 minut

Sdílet

Na počátku tohoto článku stála touha dozvědět se, proč vlastně kryptoměny jako Bitcoin a Ethereum potřebují své zvláštní programovací jazyky (jedná se o Script a Solidity). Proč prostě nevyužijí vývojáři některý z již ověřených jazyků? Záhy jsem pochopil, že k pochopení zapotřebí udělat krok zpět a zeptat se na meta otázku: proč vlastně existuje na světě tak velké množství množství programovacích jazyků?

A tato otázka mě přinutila zjistit, k čemu programovací jazyk jako takový vlastně slouží.

Jazyk a duch stroje

Programovací jazyk, stejně jako jazyk přirozený (čeština, angličtina…), slouží k vyjádření myšlenek. Přirozený jazyk má své nuance, synonyma a metafory; programovací jazyk musí být formálnější a používané termíny musí mít jednoznačný význam. Proč? Programovací jazyk je totiž především nástroj, který umožňuje překlenout bariéru mezi člověkem a strojem. A zatímco člověk si může významy a záměry domýšlet z kontextu a předešlé zkušenosti, stroj nic takového neumí. Potřebuje jasné instrukce.

Nejpřekvapivějším zjištěním při studiu programovacích jazyků je, že počítač samotný mu vlastně nerozumí. Nejnižší jednotkou počítače je totiž transistor, který může mít jen dva stavy: zapnutý nebo vypnutý. Tyto dva stavy lze vyjádřit v tzv. binární formě jako 1 a 0. A je to právě tento binární strojový kód, který přímo ovládá transistory v počítači – tomuto jazyku počítač rozumí. A v dávných dobách člověk v jedničkách a nulách skutečně programoval – formou propichování děrných štítků.


Wikipedie

Děrný štítek s výrokem z programovacího jazyka Fortran (konec 50. let).

Programovat tímto způsobem je pochopitelně mentálně náročné a ne příliš efektivní. Pro usnadnění práce si tak programátoři postupně vyvinuli tzv. vyšší jazyky – poskytující vyšší míru abstrakce od strojových jedniček a nul. Programovací jazyk je tudíž především mentální berličkou pro lidskou mysl – a do jazyka stroje je následně překládán:


Icon Library – brain, Icon Library – CPU

Cesta od lidské mysli k počítačovému HW.

Tím se konečně dostáváme k zodpovězení otázky, proč potřebujeme více programovacích jazyků – potřebuje je totiž člověk, nikoli stroj. Zjednodušeně řečeno je stroji jedno, v jakém jazyce člověk pracuje – ke stroji se vždy nakonec dostanou potřebné jedničky a nuly.

V mnoha ohledech je programovací jazyk podobnější spíše nářadí, než jazyku. Potřebujeme-li zatlouct hřebík, vezmeme si k tomu kladivo, potřebujeme-li zašroubovat šroub, vezmeme si šroubovák. Hřebíku a šroubu je v konečném důsledku jedno, jakým způsobem se do dřeva dostanou – a teoreticky můžeme na šroub vzít kladivo a na hřebík vzít šroubovák. Bude to sice pracnější a výsledek nebude moc hezký, ale obojí nakonec do dřeva zatlučeme. Obdobně fungují i programovací jazyky a software, který s nimi vytváříme. Na webové aplikace si vezmeme JavaScript, na vědecké výpočty Python. Proč? Protože jsou k tomuto účelu vymyšleny a dobře mu slouží, stejně jako kladivo na hřebík. Namísto lidské ruky třímající kladivo se zde však potýkáme s lidskou myslí formulující myšlenky ve vhodném programovacím jazyku.

Bitcoin a Script

Programovací jazyk Bitcoinu je Script. Jedná se o záměrně omezený jazyk, který umožňuje v podstatě pouze jednu věc: definovat odemykací podmínky pro bitcoiny spojené s určitou adresou. Transakce v Bitcoinové síti totiž nejsou v principu nic jiného, než neustálé redefinice ohledně toho, jak lze utratit konkrétní bitcoinové transakční výstupy (neboli UTXO = unspent transaction output).

Nejzákladnější odemykací podmínka je taková, kdy jsou bitcoiny na adrese odemknutelné pouze po podpisu privátního klíče, který odpovídá veřejnému klíči, na jehož hash byly bitcoiny původně zaslány. Základním stavebním prvkem Bitcoinu je totiž tzv. asymetrická kryptografie: páry soukromých a veřejných klíčů, kde veřejný klíč (či lépe řečeno hash veřejného klíče) je ekvivalentem adresy k zasílání bitcoinů, a soukromý klíč opravňuje bitcoiny na odpovídajícím veřejném klíči utrácet.


Bitcoin Script definuje odemykací podmínku bitcoinových UTXO. Alice v transakci Bobovi definuje odemykací podmínku takto: transakce jde na adresu odpovídající Bobovu veřejnému klíči (PubKey), což znamená, že tyto bitcoiny může odemknout pouze Bobův odpovídající soukromý klíč (PrivKey).

Při běžných transakcích se uživatel se Scriptem nepotká – odemykací podmínky za něj řeší software ve formě peněženky. Pro uživatele Bitcoinu je nicméně dobré vědět, co vše Script umožňuje: kromě výše uvedených základních transakcí to jsou například multisig transakce (v odemykací podmínce je větší množství soukromých klíčů – vhodné při správě většího množství prostředků s požadavkem na vyšší úroveň bezpečnosti), timelock transakce (v odemykací podmínce je definována výška bloku, po které teprve mohou být bitcoiny utraceny), či hashlock transakce (v odemykací podmínce je definován konkrétní hash, který musí vzejít z hashovací funkce nezveřejněné sady dat, aby bylo možné bitcoiny utratit).

Jak jsme již uvedli, Script je záměrně omezený jazyk a v principu se jedná pouze o jakousi skládačku předdefinovaných instrukcí, tzv. opcodes. Omezenost jazyka nicméně neznamená omezenost Bitcoinu samotného: naopak, Bitcoin to činí bezpečnějším (vývojáři mají menší prostor pro chyby a zranitelnosti) a s pomocí kombinací různých typů transakcí je možné nad Bitcoinem vytvářet vyšší vrstvy, které již umožňují libovolnou logiku. Nad Bitcoinem tak postupně vzniká sada standardů nazvaných LNP/BP (Lightning Network Protocol / Bitcoin Protocol), která má za ambici stát se “internetem hodnoty“, obdobně jako je sada standardů TCP/IP základem internetu dat. Ve větší hloubce koncept LNP/BP vysvětluje známý bitcoiner Giacomo Zucco v článku LNP/BP: A gentle introduction.

Zatímco Bitcoin přistupuje k budování internetu hodnot s pomocí dodatečných vrstev, Ethereum razí opačný přístup a usiluje o vybudování různých finančních služeb přímo na základní blockchainové vrstvě. K tomuto přístupu pak potřebuje jazyk, který je “expresivnější”: umožňuje tvorbu téměř libovolných programů.

Ethereum a Solidity

Z hlediska programování jsou u Etherea podstatné následující charakteristiky:

  • základním prvkem jsou tzv. kontrakty: každá aplikace běžící na Ethereu (například směnárna Uniswap) existuje ve formě kontraktu, se kterým mohou uživatelé interagovat; kontrakty jsou po spuštění neměnné (či by v zájmu decentralizace měly být – ne každý vývojář toto však dodržuje), aktualizace neměnných kontraktů se provádí vytvořením nového kontraktu a následnou dobrovolnou migrací uživatelů;
  • uživatelé interagují s kontrakty pomocí transakcí, které jsou zpoplatněné. Důvodem pro zpoplatněnost transakcí je skutečnost, že změnu v kontraktech může technicky provést pouze těžař, který vynaloží dostatečný výpočetní výkon (tzv. proof of work) a získá tak právo na zařazení nového bloku transakcí na konec blockchainu. Transakční poplatky tak slouží jako odměna těžařům, a zároveň jako prevence spamu v síti;
  • dlouhodobá paměť Etherea, která obsahuje poslední stavy kontraktů, se nazývá state; state sdílí všechny uzly v síti a kdokoli si jej může prohlédnout, vytvořit si kopii, podrobit jej analýze a podobně;

Pokud by vás hlouběji zajímal princip blockchainu a těžby, doporučuji výborné vysvětlení v češtině od Karla Wolfa.

Pro nás je nyní podstatné, že Ethereum přináší nové prvky, které je zapotřebí brát při programování aplikací v potaz – kupříkladu koncept zpoplatnění jakékoli změny v aplikaci je něco, co v jiných oblastech programátor nemusí řešit.

Proč vzniklo Solidity a co řeší?

Programovací jazyk Solidity vznikl v létě 2014, tedy zhruba v době, kdy probíhalo ICO (prvotní prodej tokenů) Etherea. Záměrem bylo vytvořit nástroj pro tvorbu tzv. smart contractů – decentralizovaných aplikací běžících na platformě Ethereum. Solidity má podobný syntax (styl psaní) jako JavaScript, a to s explicitním záměrem usnadnit seznámení s novým jazykem webovým vývojářům (kteří zpravidla mají s JavaScriptem hluboké zkušenosti). Stejně jako JavaScript je Solidity nástroj určený především k psaní webových aplikací – decentralizované aplikace jsou totiž předvojem ambiciózně nazvaného trendu Web 3.0, termínu označujícího protokoly pro “internet hodnot”.

Ethereové aplikace jsou specifické tím, že oproti běžným webovým aplikacím neběží na standardní architektuře serverů, nýbrž na větším počtu tzv. uzlů (nodes).

Jak jsme si ukázali na ilustraci „Od závitů ke křemíku“, v tradičním programovacím jazyku stojí na konci hardwarová architektura (procesor, harddisk, paměť). V Ethereu na konci stojíEthereum Virtual Machine (EVM) – virtuální stroj, který simuluje hardwarové procesy. Vzhledem k tomu, že EVM provozují všechny ethereové uzly, je vhodné, aby exekuovaný kód měl co nejnižší nároky na výpočetní výkon a velikost (v zájmu toho, aby mohlo uzly provozovat co nejvíce lidí a síť byla vskutku decentralizovaná; a také proto, aby v jednom bloku mohlo dojít ke zpracování co největšího počtu požadavků na změnu stavu kontraktů). 

Dalšími požadavky jsou rezistence vůči nekonečným loopům (které by EVM paralyzovaly) a bezpečnost provozovatele uzlu, který koneckonců na svém stroji spouští kód neznámé třetí strany. A konečně kritickým požadavkem je determinismus – výsledek exekuce kódu musí být vždy stejný, ať už jej spouští kdokoli na světě, kupříkladu s jinou implementací ethereového klienta; tím je zajištěn tzv. konsensus v síti – shoda na jednotné verzi historie účetní knihy (jelikož Ethereum, stejně jako Bitcoin, nemá žádného centrální správce, který by o správné verzi rozhodoval ).

Je Solidity bezpečné?

Ačkoli Solidity bylo vytvořeno s ohledem na bezpečnost při převodu hodnot, přesto má svá slabá místa, která postupem času vývojáři objevují – občas ale až poté, co chyba způsobila nemalou finanční ztrátu. Nejznámějším příkladem je tzv. reentrancy attack, exploit využívající konkrétní posloupnosti operací v kontraktu. Lidsky řečeno: pokud kontrakt nejprve zpracovává funkci výběru a až poté ve vnitřním účetnictví aktualizuje stavy, může útočník zavolat funkci vícekrát a dosáhnout toho, že četné výběry se zpracují předtím, než dojde k aktualizaci vnitřního účetnictví.

Útočník tak získá větší množství etheru/tokenů, než jaký by měl mít nárok. Ve větším detailu je reentrancy attack popsán v článku na Medium. Jakkoli je dnes tato zranitelnost očividná, v roce 2016 o ní nikdo nevěděl, a způsobila útok na organizaci The DAO, odkud útočník vysál ethery v hodnotě 50 milionů dolarů. A neopatrní vývojáři na tento exploit mohou doplatit i v roce 2020, jak dokládá nedávný hack služby Lendf.Me.

Dalším velkým exploitem byla chyba v multisig peněžence projektu Parity (multisig = k autorizaci transakcí je zapotřebí větší množství podpisů). V listopadu 2017 prozkoumával začínající vývojář s přezdívkou @devops199 možnosti Parity smart contractů, a omylem využil chyby, která mu umožnila stát se vlastníkem celé multisig peněženky. Následně smazal knihovnu, která definovala funkce peněženky, a tím nenávratně zmrazil prostředky ve výši okolo 150 milionů dolarů.


Parity.io

Před třemi lety ztratila peněženka Parity funkce pro výběr.

Zajímavostí je, že Parity je projektem Gavina Wooda, který je zároveň i jedním z hlavních autorů programovacího jazyka Solidity.

Výše uvedené příklady zranitelností ethereových kontraktů nemusí nutně znamenat, že Solidity není bezpečným jazykem. Vývojáři v rámci Etherea pracují v dosti jiném mentálním kontextu decentralizované sítě, kde jsou funkce a stavy kontraktů veřejné a i sebemenší chyba může být kritická a může být složité ji včas opravit (zatímco hacker má potenciál na vysoký výdělek doslova během pár minut). Sekce má spíše za účel názorně ukázat, že ani specifický jazyk, při jehož tvorbě a následném vývoji pamatovali autoři na jeho bezpečnost, neochrání vývojáře před bugy a skrytými exploity – a to ani samotného tvůrce jazyka!

Za zmínku stojí i skutečnost, že terčem kritiky v kontextu bezpečnosti se stává i samotná Ethereum Virtual Machine. Zkrátka a dobře je nutné počítat s tím, že se zde vývojář pohybuje v mnoha ohledech novém prostředí, jehož zranitelnosti teprve komunita objevuje (často bohužel za cenu ztráty peněz naivních uživatelů).

Poučením je, že při vývoji pro Ethereum (či jinou smart contract platformu) je zapotřebí přistupovat k práci s velkou dávkou pokory a považovat kontrakty za velice náchylné k chybám a napadení. Mimo jiné proto se v posledních letech značně rozvinula praxe profesionálních auditů a penetračních testů – mezi profesionální auditorské týmy patří Open Zeppelin, Trails of Bits, Dapp.org.

Materiály k dalšímu studiu

Bitcoin Script:

KL20-tip-hlasovani

Ethereum Solidity:

A konečně koho by zajímalo programování od samotných počátků, doporučuji edukativní videa kanálu Net Ninja – ideální začátek je HTML+CSS, následovaný sérií Modern Javascript.