🇨🇿 Výzvy pro Cardano vývojáře

Pro vývojáře může být obtížné plně využít výhod modelu UTxO, protože musí myslet na paralelizaci. Cardano neumožňuje udržovat jediný stav globální aplikace v on-chain části chytré smlouvy. Každý UTxO může představovat část stavu aplikace a může být zpracován nezávisle a paralelně. To teoreticky umožňuje vysokou propustnost a škálovatelnost, ale aplikace se musí vypořádat se složitostmi souvisejícími se správou souběžných transakcí. Jakým výzvám čelí vývojáři na Cardano?

Když je paralelizace snadná

V modelu Extended Unspent Transaction Output (eUTxO) může být každý UTxO zpracován nezávisle a paralelně. Utracení UTxO není závislé na žádném globálním Cardano stavu. Pokud jsou splněny podmínky útraty, vytvoří se prostřednictvím transakce ze vstupních UTxO (nebo více vstupních UTxO) jeden nebo více výstupních UTxO. Vstupní UTxO(s) musí být zcela spotřebován. Výstupní UTxO(s) musí mít stejnou (nebo menší) hodnotu jako vstupní UTxO(s).

Pokud Alice pošle 100 ADA Bobovi, útrata UTxO závisí pouze na Alice’s Witness. Pokud sto dalších uživatelů odešle podobnou transakci, použije se 100 dalších unikátních vstupních UTxO. Každý odesílatel transakce je vlastníkem vstupního UTxO. Mezi transakcemi a vstupními UTxO neexistuje žádná závislost.

Mezi transakcemi a vstupními UTxO neexistuje žádná závislost, protože všichni odesílatelé jsou na sobě nezávislí. Učinili své vlastní nezávislé rozhodnutí poslat 100 ADA. Všech 100 transakcí lze vložit do stejného bloku a budou vyhodnoceny jako platné.

Transakce spotřebuje jedno nebo více UTxO jako vstupy a vytvoří jedno nebo více nových UTxO jako výstupy. Toto jednoduché pravidlo platí jak pro převod hodnoty mezi Alicí a Bobem, tak i v případě aplikací, jak uvidíte později.

Na obrázku vidíte 3 stejné transakce. Při 100 transakcích by to vypadalo stejně. Nenechte se zmást tím, že odesílatelem je vždy Alice a příjemcem Bob. Pokaždé je to jiná Alice a jiný Bob. Obrázek má dnemonstorvat fakt, že není nutná synchronizace mezi odesílateli transakcí. Pokud jsou transakce validní, nemohou selhat a všechny se dostanou do blockchainu.

Význam obrázku si možná uvědomíte až zpětně poté co vysvětlíme jak funguje DEX.

Síť Cardano může ověřovat transakce v libovolném pořadí, protože transakce jsou na sobě nezávislé. To je výhoda z hlediska propustnosti sítě, protože konsenzus není závislý na sekvenčním zpracování.

Jak vytvořit paralelní aplikaci?

V ideálním případě by vývojáři aplikací měli vytvořit takovou logiku smart kontraktu, která se bude z hlediska paralelizace chovat podobně, jako když 100 odesílatelů (Alices) odešle transakci. To je však téměř nemožné.

Ujasněme si to na příkladu DEX, který využívá pooly likvidity.

Pool likvidity je naplněn několika transakcemi, které produkují výstupní UTxO. Tyto UTxO představují tokeny v poolu likvidity. S každým nově připojeným blokem do hlavní knihy se může složení UTxO v poolu likvidity změnit.

Na obrázku vidíte pool likvidity s párem tokenů X a Y. V poolu likvidity je několik UTxO s tokeny X a Y. V dalším bloku Alice, Bob a Carol vložili nové UTxO s tokenem X do pool likvidity a Dave, Eve a Frank vložili nějaké UTxO s tokenem Y. Protože nedošlo k žádné výměně, nebyly z poolu odstraněny žádné UTxO.

Pro provedení swapu musí DEX spotřebovat UTxO (nebo více UTxO) z poolu likvidity jako vstup pro každý typ tokenu. Tyto UTxO musí být zcela utraceny. Pokud swap nevyžaduje všechny tokeny v UTxO, musí být zbývající tokeny vráceny do poolu likvidity jako nový UTxO.

V případě DEX probíhá mnoho operací současně. Uživatelé posílají tokeny (poskytovatelé likvidity) do poolů likvidity. Poskytovatelé jsou odesílatelé a DEX je příjemce. Zároveň mohou ostatní uživatelé zasílat požadavky na swapy. Jsou to odesílatelé, kteří dávají X token DEX a chtějí získat Y token. Nebo naopak.

Více účastníků může podat žádost o výměnu během krátké doby. Tyto swapy se mohou týkat jednoho poolu likvidity. Mezi účastníky tedy existuje vzájemná závislost.

Je také dobré si ujasnit, co přesně DEX je. Komplexní smart kontrakty v Cardano (jako DEX) se skládají ze dvou částí: on-chain logiky, která se spouští na blockchainu, a off-chain logiky, která se spouští na serverech (nebo v místních peněženkách).

Na obrázku můžete vidět DEX, který se skládá z on-chain a off-chain logiky.

Zatímco provádění on-chain logiky je přirozeně decentralizované, protože probíhá v síti Cardano, tým je zodpovědný za decentralizaci off-chain logiky DEX. Část off-chain DEX není složena (neměla by být) pouze z jednoho agenta, ale z několika agentů.

V případě DEX se těmto agentům říká batchers. Jsou zodpovědní za provádění swapů. Batchers vytvářejí transakce splňující podmínky útraty UTxO v likviditním poolu a převádějí aktiva v poměru, který oba účastníci swapu požadovali.

Cardano neumožňuje udržovat jednotný stav globální aplikace v on-chain části smart kontraktu. Technicky to ale možné je.

Pokud by vývojáři uložili celý stav DApp do jediného UTXO, v podstatě by vytvořili globální stav podobný tomu, který existuje v modelu založeném na účtu Ethereum. To by mohlo omezit souběžnost a propustnost vaší DApp. Tento přístup by plně nevyužil výhody modelu EUTxO.

V on-chain části DEX představují stav aplikace UTxO a související Datum. Stav je tedy distribuován napříč UTxO. Pokud má mít DEX jednotný stav globální aplikace, musí být udržován mimo řetězec mezi batchers.

Na obrázku můžete vidět pool likvidity s tokeny X a Y a 3 dávkovači. Globální stav aplikace a synchronizace stavu mezi dávkovači jsou označeny modře. Stav aplikace se skládá z dat v řetězci, což jsou Datum spojené s UTxO a stav aplikace mimo řetězec udržovaný batchers (agenty). Batchers spolu komunikují, aby synchronizovaly jednotný globální stav aplikace.

To je nezbytné, protože batchers (agenti) přistupují ke stejnému zdroji a tím je pool likvidity. Potřebují použít vstupní UTxO z poolu likvidity (k provedení swapu) a může se stát, že dva (nebo více) agenti chtějí použít stejné UTxO. Může nastat problém sporu (contention).

Nyní je čas vzpomenout si na první obrázek v článku. Když 100 odesílatelů submitovalo transakci, nemohli se navzájem přetahovat o stejné UTxO, neboť každý odesílatel použil vlastní UTxO. UTxOs v liquidity poolu je sdílený zdroj, tedy zdroj ke kterému přistupuje více agentů.

Spor se obecně týká scénáře, kdy se více vláken nebo procesů (v našem případě agentů) pokouší o přístup ke stejnému prostředku takovým způsobem, že alespoň jeden z nich běží pomaleji, než kdyby ostatní neběžely.

V našem případě existuje riziko, že dva agenti zkonstruují transakci, ve které použijí stejný vstup UTxO z poolu likvidity. V tomto případě bude Cardanem akceptována pouze jedna transakce. Druhá selže.

Na obrázku můžete vidět, že batcher 1 a batcher 3 se pokoušejí použít stejné UTxO s tokenem X. Došlo ke sporu. Batcheři jsou zjevně špatně synchronizováni a navzájem neznají záměr použít tento konkrétní UTxO. Pokud jsou vytvořeny 2 swapové transakce, jedna bude úspěšná a druhá selže.

Cílem DEX je umožnit souběžné provádění swapů, tj. aby jednotliví agenti mohli vytvářet transakce současně a při výběru UTxO nedocházelo ke sporům.

Aby se zabránilo selhání transakcí, musí mezi agenty existovat mimořetězová komunikace nebo nějaká jiná forma synchronizace. Jinými slovy, agenti musí udržovat konzistentní globální stav DEX.

Jednotliví agenti si musí nějakým způsobem rezervovat UTxO v poolu, aby stejný UTxO nepoužil jiný agent. Případně to může fungovat tak, že v každém dalším bloku (20 sekund) budou všechny transakce konstruovány jediným (náhodně zvoleným) agentem. Přestože je tento přístup decentralizovaný, je méně souběžný.

Na obrázku můžete vidět, že batcher 1 a batcher 3 zvolili UTxO s tokeny X a Y pro swapy výhradně, takže k žádnému sporu nedošlo. Swap 1 a 2 běží souběžně. Nedošlo k žádnému sporu, protože všichni batcheři synchronizují globální stav mezi sebou.

Všimněte si, že token X má přesně 2x tržní hodnotu tokenu Y a shodou okolností byly v poolu likvidity vhodné UTxO pro spárování. Swap 1 spotřebuje 100 X tokenů a 50 Y tokenů. Swap 2 spotřebuje 200 X tokenů a 100 Y tokenů. Pokud by ve poolu nebylo UTxO se 100 X tokeny, druhý nejvhodnější by byl UTxO se 114 X tokeny. To znamená, že 14 X tokenů by muselo být vráceno zpět do poolu likvidity jako nový UTxO.

Jednou z dalších výzev, které se v článku dále nebudeme věnovat, je vhodný výběr UTxO pro swapy. U Ethereum to není problém, neboť se v podstatě jen aktualizují balance na účtech.

O problému je možné uvažovat i zcela jinak než pomocí poolu likvidity. Namísto umístění UTxO do jednoho poolu je možné propojit jednotlivé kandidáty na swap. Pro zjednodušení však v tomto článku zůstaňme u poolů likvidity.

Návrh DEX na Cardano, který dokáže zpracovávat UTxO paralelně při zachování decentralizace, zahrnuje řešení problému souběžnosti. To je jedna z výzev pro vývojáře.

V článku jsme si ukázali jedno z možných řešení, tedy použití off-chain a on-chain komponent. Komponenta off-chain může být použita ke správnému vytváření transakcí pro interakci s on-chain kódem. Korektnost je zajištěna off-chain komunikací umožňující synchronizaci globálního stavu aplikace.

Jedním z dalších možných přístupů je vytvoření algoritmu, který uživatelům poskytuje exkluzivní přístup k odeslání požadované akce. Algoritmus může následně sloučit všechny akce dohromady s ohledem na načasování a spravedlnost.

Vývojáři mohou udržovat jeden stav v on-chain části aplikace nebo jej rozdělit na více UTxO. Mít jeden stav on-chain je snadné, protože je snazší udržet konzistenci. Všechny části aplikace pracují se stejnými daty. Rozdělení stavu on-chain na více UTxoS může zvýšit souběžnost, ale přichází s několika problémy. Správa více UTxO zvyšuje složitost logiky inteligentních smluv. Je nutné zajistit nějakou formu synchronizace, která zajistí správnost (vyhnutí se sporům).

Jádro problému spočívá v dosažení paralelizace v decentralizovaném prostředí.

Aplikační logika je vždy spojena s UTxO. Každý UTxO představuje nezávislou část stavu, kterou lze zpracovávat paralelně. Jak jsme vysvětlili v článku, je to možné pouze v případě implementace nějaké spolehlivé formy synchronizace.

Pokud by existoval pouze jeden batcher nebo off-chain agent, mohl by spravovat stav DEX a připravovat transakce, aniž by se musel starat o problémy se souběžností. To by mohlo potenciálně vést k rychlejšímu zpracování transakcí a vyšší propustnosti.

Tento přístup by však v podstatě centralizoval off-chain část DEX, což je v rozporu s principem decentralizace. Výzvou proto je dosáhnout decentralizace mimo řetězec a zároveň zachovat vysoký výkon a vyhnout se problémům se souběžností.

Vývojáři Ethereum také čelí výzvám

Ethereum používá model založený na účtu a smart kontrakty mají globální stav, který je aktualizován transakcemi. Globální stav je kód (funkcí) a dat (stav), která sídlí na konkrétní adrese na blockchainu Ethereum.

Globální stav DEXu by mohl představovat aktuální stav knihy objednávek, včetně všech otevřených objednávek k nákupu a prodeji. Když je odeslána nová swapová transakce, představuje potenciální změnu tohoto globálního stavu. Tato změna se však stane přijatou až poté, co je transakce zahrnuta do bloku a ověřena sítí.

Transakce v Ethereu jsou zpracovávány postupně, jedna po druhé. To znamená, že ve světě Ethereum neexistuje žádná souběžnost, tudíž žádné problémy se souběžností. Toto sekvenční zpracování usnadňuje navrhování DEX na Ethereu, pokud jde o souběžnost a paralelismus, protože vývojáři se nemusí zabývat složitostí správy souběžných transakcí.

Toto sekvenční ověření však nedokáže využít souběžnost. Souběžné provádění transakcí by bylo nebezpečné, protože mezi smlouvami mohou existovat závislosti. Pokud jedna smlouva závisí na výsledcích druhé, pak tyto smlouvy musí provést každý validátor ve stejném pořadí.

Pořadí transakcí v rámci bloku určují validátoři. Mohou si vybrat řazení transakcí na základě faktorů, jako je cena GAS, nonce a první spatření. Proto, zatímco DEX může vytvořit frontu mnoha swapů, nemůže si být jistý, v jakém pořadí budou tyto swapy provedeny.

Tato nejistota může vést k situacím, kdy transakce selžou kvůli vzájemné soutěži (race condition), kdy různé transakce soutěží o spotřebování stejné likvidity. Aby se to vyřešilo, některé DEXy implementují mechanismy, jako je tolerance skluzu a termíny transakcí, aby se zvýšila pravděpodobnost úspěšného provedení transakcí.

Spor může nastat, když se více uživatelů pokusí vyměnit tokeny současně. Řekněme například, že oba uživatelé chtějí vyměnit ETH za USDT a v poolu likvidity je pouze dostatek USDT na to, aby mohl projít jeden ze swapů. Oba uživatelé zadávají své swapové transakce zhruba ve stejnou dobu. Validátoři Etherea rozhodnou o pořadí, ve kterém budou tyto transakce zahrnuty do bloku.

Pokud bude transakce uživatele A zahrnuta jako první, jeho swap projde a ve poolu nezbude dostatek USDT pro swap uživatele B. Když se síť Ethereum pokusí zpracovat transakci uživatele B, selže, protože nemůže provést swap.

Výsledek závisí na relativním načasování dvou nebo více operací (swapů). I když Ethereum zpracovává transakce sekvenčně, stále mohou nastat podmínky závodu, když více transakcí závisí na sdíleném zdroji (jako je pool likvidity v DEX) a jsou odeslány přibližně ve stejnou dobu.

Všimněte si, že konflikt může nastat, i když je pool likvidity spravován pouze jedním DEX. Důvodem je, že spor není způsoben samotným DEXem, ale povahou zpracování transakcí.

Jinými slovy, aplikace na Ethereu mohou preferovat nějaké pořadí, ve kterém by měly být transakce zpracovávány, ale to není pod jejich vlastní kontrolou. V případě Cardano jsou transakce zpracovávány podle zásady „kdo dřív přijde, je dřív na řadě“. Je však nutné zmínit, že pooly se tímto pravidlem řídit nemusí a neexistuje žádný mechanismus, který by pool donutil správně vybírat transakce z mem-poolu.

Pojďme si krátce porovnat výzvy pro vývojáře na obou platformách.

Při budování DEX nebo jakékoli jiné decentralizované aplikace na Cardano je jedním z problémů správa a synchronizace částí stavu napříč více UTXO a agenty. To umožňuje vyšší propustnost a škálovatelnost, ale také přináší další složitosti související se správou souběžných transakcí.

Aplikace může spravovat a aktualizovat svůj stav off-chain a pak pravidelně odesílat stav do blockchainu. Tento přístup může pomoci snížit zatížení blockchainu a zvýšit rychlost transakcí. Synchronizace mimo řetězec může navíc usnadnit paralelní provádění transakcí v řetězci. DEX dokáže připravit více transakcí paralelně a poté je odeslat do blockchainu k provedení.

Rychlá off-chain synchronizace může potenciálně vést k vysoké škálovatelnosti a paralelismu v řetězci. Vývojáři se snaží dosáhnout maximální možné paralelizace skrze synchronizaci.

Tím se liší od modelu založeného na účtu Ethereum, kde je stav celé aplikace uložen v jediném globálním stavu. Globální stav může obsahovat všechna potřebná data pro DEX a změny prostřednictvím transakcí. Vzhledem k tomu, že Ethereum zpracovává transakce (calls) sekvenčně, nemusí se vývojáři vůbec bát souběžnosti.

Problémem však je, že určitou formu paralelismu představuje chování uživatelů, kteří se mohou snažit spotřebovat stejnou likviditu v DEX na Ethereu. V podstatě bojují o jeden zdroj podobně jako batcheři, kteří mohou chtít spotřebovávat stejné UTxO.

Vývojáři Ethereum DEX nemohou zcela zabránit race conditions souvisejícím s tím, že se více uživatelů pokouší spotřebovat stejnou likviditu. Stav poolu likvidity (tj. kolik likvidity je k dispozici) je určen transakcemi, které byly zahrnuty do blockchainu. Uživatelé v reálném čase nevědí, zda jejich transakce budou úspěšné, protože Ethereum zpracovává transakce postupně a o pořadí rozhodují validátoři.

Vývojáři se mohou pokusit vytvořit nějaký mechanismus, který uživatelům zabrání v odeslání transakce, která má vysokou šanci na selhání. To je však velmi obtížný úkol.

Všimněte si, že Cardano se chová deterministicky narozdíl od Ethereum.

Závěr

Pro plné využití UTxO modelu a paralelizace je nutné vylepšit Ouroboros Proof-of-Stake. Síť Cardano musí být schopna ověřit a předem schválit velké množství transakcí najednou. Pokud bylo do bloku vloženo několik desítek transakcí jednou za 20 sekund, nevadí, že je lze zpracovávat paralelně. Škálovatelnost by byla stále relativně nízká. Input Endorsers přinesou potřebné vylepšení PoS konsensu, ve kterém model UTxO zazáří výrazně více.

Článek připravili Cardanians s podporou Cexplorer.

Přečtěte si celý článek: https://cexplorer.io/article/challenges-for-cardano-developers