🇸🇰 Výzvy pre Cardano developerov

Výzvy pre Cardano developerov

Pre vývojárov môže byť ťažké naplno využiť model UTxO, pretože musia brať do úvahy paralelizáciu. Cardano neumožňuje udržiavať jeden globálny stav aplikácie v on-chain časti inteligentného kontraktu. Každý UTxO môže predstavovať časť stavu aplikácie a môže byť spracovaný nezávisle a paralelne. To teoreticky umožňuje vysokú priepustnosť a škálovateľnosť, ale aplikácia sa musí vysporiadať so zložitosťami súvisiacimi so správou súbežných transakcií. Akým výzvam čelia vývojári na Cardano?

Keď je paralelizácia jednoduchá

V modeli eUTxO (Extended Unspent Transaction Output) môže byť každý UTxO spracovaný nezávisle a paralelne. Výdaj UTxO nezávisí od žiadneho globálneho stavu Cardana. Ak sú splnené podmienky utrácania, zo vstupného UTxO (alebo viacerých vstupných UTxO) sa prostredníctvom transakcie vytvorí jedno alebo viac výstupných UTxO. Vstupný(é) UTxO musí(ú) byť úplne spotrebovaný(é). Výstupné UTxO musia mať rovnakú (alebo menšiu) hodnotu ako vstupné UTxO.

Ak Alica pošle Bobovi 100 ADA, výdaj UTxO závisí len od Alicinho svedka. Ak sto ďalších používateľov pošle podobnú transakciu, použije sa 100 ďalších jedinečných vstupných UTxO. Každý odosielateľ transakcie je vlastníkom vstupného UTxO. Medzi transakciami a vstupnými UTxO neexistuje žiadna závislosť.

Medzi transakciami a vstupnými UTxO neexistuje závislosť, pretože všetci odosielatelia sú na sebe nezávislí. Urobili svoje vlastné nezávislé rozhodnutie poslať 100 ADA. Všetkých 100 transakcií môže byť vložených do toho istého bloku a budú vyhodnotené ako platné.

Transakcia spotrebuje jeden alebo viac UTxO ako vstupy a vytvorí jeden alebo viac nových UTxO ako výstupy. Toto jednoduché pravidlo platí tak pre prenos hodnoty medzi Alicou a Bobom, ako aj v prípade aplikácií, ako uvidíte neskôr.

Na obrázku vidíte 3 identické transakcie. Pri 100 transakciách by to vyzeralo rovnako. Nenechajte sa zmiasť tým, že odosielateľom je vždy Alica a príjemcom Bob. Zakaždým je to iná Alica a iný Bob. Obrázok má demonštrovať skutočnosť, že medzi odosielateľmi transakcií nie je potrebná žiadna synchronizácia. Ak sú transakcie platné, nemôžu zlyhať a všetky sa dostanú do blockchainu.

Význam obrázka si možno uvedomíte neskôr, keď si vysvetlíme, ako DEX funguje.

Sieť Cardano môže overovať transakcie v ľubovoľnom poradí, pretože transakcie sú na sebe nezávislé. To je výhoda z hľadiska priepustnosti siete, pretože konsenzus nie je závislý od postupného spracovania.

Ako vytvoriť paralelnú aplikáciu?

V ideálnom prípade by mali vývojári aplikácií vytvoriť takú logiku inteligentného kontraktu, ktorá sa z hľadiska paralelizácie správa podobne, ako keď 100 odosielateľov (Alices) odošle transakciu. To je však takmer nemožné.

Objasníme si to na príklade DEX, ktorý využíva pooly likvidity.

Bazén likvidity je naplnený viacerými transakciami, ktoré produkujú výstupné UTxO. Tieto UTxO predstavujú tokeny v poole likvidity. S každým novo pridaným blokom do účtovnej knihy sa zloženie UTxO v poole likvidity môže zmeniť.

Na obrázku vidíte bazén likvidity s dvojicou tokenov X a Y. V bazéne likvidity je niekoľko UTxO s tokeny X a Y. V ďalšom bloku Alice, Bob a Carol vložili do bazéna likvidity nové UTxO s tokenom X a Dave, Eve a Frank vložili niekoľko UTxO s tokenom Y. Keďže nedošlo k výmene, z bazéna neboli odstránené žiadne UTxO.

Na uskutočnenie swapu musí DEX spotrebovať UTxO (alebo viac UTxO) z fondu likvidity ako vstup pre každý typ tokenu. Tieto UTxO musia byť úplne spotrebované. Ak si swap nevyžaduje všetky tokeny UTxO, potom sa zvyšné tokeny musia vrátiť do poolu likvidity ako nové UTxO.

V prípade DEX prebieha súčasne mnoho operácií. Používatelia posielajú tokeny (poskytovatelia likvidity) do poolov likvidity. Poskytovatelia sú odosielatelia a DEX je príjemca. Zároveň môžu iní používatelia posielať žiadosti o výmenu. Sú to odosielatelia, ktorí dávajú tokenov X do DEX a chcú získať tokenov Y. Alebo naopak.

Žiadosť o swap môže v krátkom čase poslať viac účastníkov. Tieto swapy sa môžu týkať jedného fondu likvidity. Medzi účastníkmi teda existuje vzájomná závislosť.

Je tiež dobré objasniť, čo presne je DEX. Komplexné inteligentné kontrakty v Cardano (ako DEX) sa skladajú z dvoch častí: logiky on-chain, ktorá sa vykonáva na blockchaine, a logiky off-chain, ktorá sa vykonáva na serveroch (alebo v lokálnych peňaženkách).

Na obrázku môžete vidieť DEX, ktorý sa skladá z on-chain a off-chain logiky.

Zatiaľ čo vykonávanie on-chain logiky je prirodzene decentralizované, keďže prebieha v sieti Cardano, za decentralizáciu off-chain logiky DEX je zodpovedný tím. Časť DEX mimo reťazca nie je (nemala by byť) zložená len z jedného agenta, ale z viacerých agentov.

V prípade DEX sa títo agenti nazývajú batchers. Sú zodpovední za vykonávanie výmen. Batcheri vytvárajú transakcie, ktoré spĺňajú podmienky čerpania UTxO v poole likvidity a prevádzajú aktíva v pomere, ktorý požadovali obaja účastníci swapu.

Cardano neumožňuje udržiavať jednotný globálny stav aplikácie v on-chain časti smart kontraktu. Je to však technicky možné.

Ak by vývojári uložili celý stav DApp do jedného UTXO, v podstate by vytvorili globálny stav podobný tomu, ktorý existuje v modeli Ethereum založenom na účtoch. To by mohlo obmedziť súbežnosť a priepustnosť vašej DApp. Tento prístup by plne nevyužil výhody modelu EUTxO.

V on-chain časti DEX predstavujú stav aplikácie UTxO a súvisiace dáta. Stav je preto distribuovaný naprieč UTxOs. Ak má mať DEX jednotný globálny stav aplikácie, musí sa udržiavať mimo reťazca v rámci dávkovačov.

Na obrázku vidíte fond likvidity s tokeny X a Y a 3 batchermi. Globálny stav aplikácie a synchronizácia stavu medzi batchermi sú vyznačené modrou farbou. Stav aplikácie pozostáva z údajov on-chain, čo sú dáta spojené s UTxOs, a zo stavu aplikácie off-chain udržiavaného batchermi (agentmi). Batchery navzájom komunikujú s cieľom synchronizovať jednotný globálny stav aplikácie.

Je to potrebné, pretože batchery (agenti) pristupujú k rovnakému zdroju, a tým je fond likvidity. Potrebujú používať vstupné UTxO z fondu likvidity (na vykonanie výmeny) a môže sa stať, že dvaja (alebo viacerí) agenti budú chcieť používať rovnaké UTxO. Môže nastať problém s konfliktom.

Teraz je čas pripomenúť si prvý obrázok v článku. Keď 100 odosielateľov predložilo transakciu, nemohli si navzájom konkurovať o to isté UTxO, pretože každý odosielateľ používal svoje vlastné UTxO. UTxO v poole likvidity sú zdieľaným zdrojom, t. j. zdrojom, ku ktorému majú prístup viacerí agenti.

Vo všeobecnosti sa kontingencia vzťahuje na scenár, keď sa viacero vlákien alebo procesov (v našom prípade agentov) snaží pristupovať k tomu istému zdroju takým spôsobom, že aspoň jeden z nich beží pomalšie, ako keby ostatné nebežali.

V našom prípade existuje riziko, že dvaja agenti vytvoria transakciu, v ktorej použijú rovnaký vstupný UTxO z fondu likvidity. V takom prípade Cardano prijme iba jednu transakciu. Druhá z nich zlyhá.

Na obrázku môžete vidieť, že batcher 1 a batcher 3 sa pokúšajú použiť rovnaké UTxO s tokenom X. Došlo ku kontentácii. Batcheri sú zrejme zle synchronizovaní a navzájom nevedia o svojom zámere použiť toto konkrétne UTxO. Ak sa vytvoria 2 výmenné transakcie, jedna bude úspešná a druhá zlyhá.

Cieľom DEX je umožniť súbežné vykonávanie swapov, t. j. aby jednotliví agenti mohli konštruovať transakcie súčasne a aby pri výbere UTxO nedochádzalo ku kontingencii.

Aby sa zabránilo zlyhaniu transakcií, musí existovať komunikácia mimo reťazca medzi agentmi alebo iná forma synchronizácie. Inými slovami, agenti musia udržiavať konzistentný globálny stav DEX.

Jednotliví agenti si musia nejakým spôsobom rezervovať UTxO v poole, aby ten istý UTxO nepoužil iný agent. Prípadne to môže fungovať tak, že v rámci každého nasledujúceho bloku (20 sekúnd) všetky transakcie skonštruuje jeden (náhodne vybraný) agent. Hoci je tento prístup decentralizovaný, je menej súbežný.

Na obrázku vidíte, že batcher 1 a batcher 3 si na výmeny vybrali UTxO s tokeny X a Y exkluzívnym spôsobom, takže nedošlo k žiadnej kontaminácii. Swapy 1 a 2 prebiehajú súbežne. Nedošlo k žiadnej kontaminácii, pretože všetky batchery navzájom synchronizovali globálny stav.

Všimnite si, že token X má presne 2x väčšiu trhovú hodnotu ako token Y a zhodou okolností boli v poole likvidity vhodné UTxO na párovanie. Výmena 1 spotrebuje 100 tokenov X a 50 tokenov Y. Swap 2 spotrebuje 200 tokenov X a 100 tokenov Y. Ak by v poole nebol UTxO so 100 X tokeny, druhým najvhodnejším by bol UTxO so 114 X tokeny. To znamená, že 14 X tokenov by sa muselo vrátiť do fondu likvidity ako nový UTxO.

Jednou z ďalších výziev, ktorej sa v článku nebudeme ďalej venovať, je vhodný výber UTxO pre swapy. Pri Ethereu to nie je problém, pretože sa v podstate aktualizujú len zostatky na účtoch.

O probléme je možné uvažovať aj úplne iným spôsobom ako pomocou poolu likvidity. Namiesto umiestnenia UTxO do jedného poolu je možné prepojiť jednotlivých kandidátov na swap. Kvôli zjednodušeniu sa však v tomto článku držme bazénov likvidity.

Návrh DEX na Cardano, ktorý dokáže paralelne spracovávať UTxOs pri zachovaní decentralizácie, zahŕňa riešenie problému súbežnosti. To je jedna z výziev pre vývojárov.

V článku sme ukázali jedno z možných riešení, t. j. použitie komponentov mimo reťazca a na reťazci. Komponentu off-chain možno použiť na správne vytvorenie transakcií na interakciu s kódom on-chain. Korektnosť je zabezpečená prostredníctvom off-chain komunikácie umožňujúcej synchronizáciu globálneho stavu aplikácie.

Jedným z ďalších možných prístupov je vytvorenie algoritmu, ktorý poskytuje používateľom exkluzívny prístup na odoslanie požadovanej akcie. Algoritmus môže následne zlúčiť všetky akcie dohromady, pričom rešpektuje časovanie a spravodlivosť.

Vývojári môžu udržiavať jeden stav v on-chain časti aplikácie alebo ho rozdeliť medzi viacero UTxO. Mať jeden stav v časti on-chain je jednoduché, pretože je jednoduchšie udržiavať konzistenciu. Všetky časti aplikácie pracujú s rovnakými údajmi. Rozdelenie stavu on-chain do viacerých UTxoS môže zvýšiť súbežnosť, ale prináša so sebou niekoľko problémov. Správa viacerých UTxOs zvyšuje zložitosť logiky inteligentných kontraktov. Je potrebné zabezpečiť určitú formu synchronizácie, ktorá zabezpečí korektnosť (zamedzenie spornosti).

Jadro problému spočíva v dosiahnutí paralelizácie v decentralizovanom prostredí.

Aplikačná logika je vždy prepojená s UTxOs. Každý UTxO predstavuje nezávislú časť stavu, ktorú možno spracovať paralelne. Ako sme vysvetlili v článku, je to možné len vtedy, ak je implementovaná nejaká spoľahlivá forma synchronizácie.

Ak by existoval len jeden dávkovač alebo agent mimo reťazca, mohol by spravovať stav DEX a pripravovať transakcie bez toho, aby sa musel starať o problémy so súbežnosťou. To by potenciálne mohlo viesť k rýchlejšiemu spracovaniu transakcií a vyššej priepustnosti.

Tento prístup by však v podstate centralizoval časť DEX mimo reťazca, čo je v rozpore so zásadou decentralizácie. Výzvou je preto dosiahnuť decentralizáciu mimo reťazca a zároveň zachovať vysoký výkon a vyhnúť sa problémom so súbežnosťou.

Vývojári Etherea tiež čelia výzvam

Ethereum používa model založený na účtoch a inteligentné kontrakty majú globálny stav, ktorý sa aktualizuje transakciami. Globálny stav je kód (funkcie) a údaje (stav), ktoré sa nachádzajú na konkrétnej adrese v blockchaine Ethereum.

Globálny stav DEX by mohol predstavovať aktuálny stav knihy objednávok vrátane všetkých otvorených objednávok na nákup a predaj. Keď sa zadá nová swapová transakcia, predstavuje potenciálnu zmenu tohto globálneho stavu. Táto zmena sa však stane akceptovanou až po zaradení transakcie do bloku a jej overení sieťou.

Transakcie v Ethereu sa spracúvajú postupne, jedna po druhej. To znamená, že vo svete Ethereum neexistuje súbežnosť, a teda ani problémy so súbežnosťou. Toto sekvenčné spracovanie zjednodušuje návrh DEX na Ethereum, pokiaľ ide o súbežnosť a paralelizmus, pretože vývojári sa nemusia zaoberať zložitosťou správy súbežných transakcií.

Toto sekvenčné overovanie však nedokáže využiť súbežnosť. Paralelné vykonávanie transakcií by nebolo bezpečné, pretože medzi kontraktmi môžu existovať závislosti. Ak jedna zmluva závisí od výsledkov inej zmluvy, potom tieto zmluvy musí každý validátor vykonať v rovnakom poradí.

Poradie transakcií v rámci bloku určujú validátory. Môžu sa rozhodnúť zoradiť transakcie na základe faktorov, ako je cena GAS, nonce a čas prvého zobrazenia. Preto hoci DEX môže vytvoriť frontu mnohých swapov, nemôže si byť istý, v akom poradí sa tieto swapy vykonajú.

Táto neistota môže viesť k situáciám, keď transakcie zlyhajú v dôsledku pretekov, keď rôzne transakcie súťažia o spotrebu rovnakej likvidity. Na riešenie tejto situácie niektoré DEX implementujú mechanizmy, ako sú tolerancia sklzu a termíny transakcií, aby zvýšili pravdepodobnosť úspešného vykonania transakcií.

Podmienka pretekov môže nastať, keď sa viacero používateľov pokúsi vymeniť tokeny v rovnakom čase. Povedzme napríklad, že dvaja používatelia chcú obaja vymeniť ETH za USDT a v poole likvidity je dostatok USDT len na to, aby sa uskutočnila jedna z výmen. Obaja používatelia predložia svoje swapové transakcie približne v rovnakom čase. Validátori Etherea rozhodnú o poradí, v akom budú tieto transakcie zahrnuté do bloku.

Ak bude transakcia používateľa A zaradená ako prvá, jeho swap prejde a v poole nezostane dostatok USDT pre swap používateľa B. Keď sa sieť Ethereum pokúsi spracovať transakciu používateľa B, zlyhá, pretože nemôže splniť swap.

Výsledok závisí od relatívneho načasovania dvoch alebo viacerých operácií (swapov). Aj keď Ethereum spracúva transakcie sekvenčne, k pretekom môže dôjsť aj vtedy, keď viaceré transakcie závisia od zdieľaného zdroja (ako napríklad bazén likvidity v DEX) a sú odoslané približne v rovnakom čase.

Všimnite si, že race condition môže nastať aj vtedy, ak je pool likvidity spravovaný len jedným DEX. Je to preto, že stav pretekov nie je spôsobený samotným DEX, ale povahou spracovania transakcií.

Inými slovami, aplikácie na Ethereum môžu preferovať určité poradie, v ktorom by sa mali transakcie spracovať, ale nie je to pod ich vlastnou kontrolou. V prípade Cardano sa transakcie spracúvajú podľa zásady “kto prv príde, ten prv melie”. Je však potrebné spomenúť, že pooly sa týmto pravidlom nemusia riadiť a neexistuje mechanizmus, ktorý by pooly nútil správne vyberať transakcie z mem-poolu.

Poďme si v krátkosti porovnať výzvy pre vývojárov na oboch platformách.

Pri vytváraní DEX alebo akejkoľvek inej decentralizovanej aplikácie na Cardano je jednou z výziev správa a synchronizácia častí stavu vo viacerých UTXO a agentoch. To umožňuje vyššiu priepustnosť a škálovateľnosť, ale zároveň prináša ďalšie zložitosti súvisiace so správou súbežných transakcií.

Aplikácia môže spravovať a aktualizovať svoj stav mimo reťazca a potom pravidelne odovzdávať stav do blockchainu. Tento prístup môže pomôcť znížiť zaťaženie blockchainu a zvýšiť rýchlosť transakcií. Synchronizácia mimo reťazca môže navyše uľahčiť aj paralelné vykonávanie transakcií v reťazci. DEX môže paralelne pripraviť viacero transakcií a potom ich odoslať do blockchainu na vykonanie.

Rýchla synchronizácia mimo reťazca môže potenciálne viesť k vysokej škálovateľnosti a paralelnosti v reťazci. Vývojári sa snažia dosiahnuť maximálnu možnú paralelizáciu prostredníctvom synchronizácie.

Tým sa líši od modelu Etherea založeného na účtoch, kde je stav celej aplikácie uložený v jednom globálnom stave. Globálny stav môže obsahovať všetky potrebné údaje pre DEX a mení sa prostredníctvom transakcií. Keďže Ethereum spracováva transakcie (volania) sekvenčne, vývojári sa vôbec nemusia starať o súbežnosť.

Problémom však je, že určitú formu paralelizmu predstavuje správanie používateľov, ktorí sa môžu pokúsiť spotrebovať rovnakú likviditu v DEX na Ethereum. V podstate bojujú o jeden zdroj podobne ako batcheri, ktorí môžu chcieť spotrebovať rovnaké UTxO.

Vývojári Ethereum DEX nedokážu úplne zabrániť pretekovým podmienkam súvisiacim s pokusmi viacerých používateľov spotrebovať rovnakú likviditu. Stav poolu likvidity (t. j. koľko likvidity je k dispozícii) je určený transakciami, ktoré boli zahrnuté do blockchainu. Používatelia v reálnom čase nevedia, či ich transakcie budú úspešné, pretože Ethereum spracováva transakcie sekvenčne a o poradí rozhodujú validátory.

Vývojári sa môžu pokúsiť vytvoriť nejaký mechanizmus, ktorý by používateľom zabránil odoslať transakciu, ktorá má vysokú pravdepodobnosť neúspechu. Je to však veľmi náročná úloha.

Všimnite si, že Cardano sa na rozdiel od Etherea správa deterministicky.

Záver

Na plné využitie modelu UTxO a paralelizácie je potrebné vylepšiť Ouroboros Proof-of-Stake. Sieť Cardano musí byť schopná validovať a predbežne schvaľovať veľký počet transakcií naraz. Ak by sa raz za 20 sekúnd vložilo do bloku niekoľko desiatok transakcií, nezáleží na tom, že je možné ich spracovať paralelne. Škálovateľnosť by bola stále relatívne nízka. Vstupné endorsery prinesú potrebné zlepšenie konsenzu PoS, v ktorom model UTxO zažiari podstatne viac.


Pôvodný článok: Challenges for Cardano Developers | Cardano Explorer (cexplorer.io)