Nucleul paralelismului este creșterea eficienței execuției prin executarea pe mai multe căi, iar pentru a realiza execuția pe mai multe căi, blockchain-ul trebuie să efectueze o serie de verificări de conflicte și mecanisme de rollback pentru a se asigura că acestea sunt executate în paralel fără a afecta consistența stării finale și să efectueze anumite îmbunătățiri în baza de date.

Articol scris de: Tia, Techub News

Blockchain-ul, datorită designului său descentralizat, sacrifică eficiența, astfel încât îmbunătățirea vitezei de execuție a fost întotdeauna una dintre problemele urgente de rezolvat. „Stratul de execuție” al blockchain-ului este partea esențială care procesează fiecare tranzacție și o adaugă la lanț. Pentru a accelera capacitatea de procesare, îmbunătățirea stratului de execuție a devenit una dintre strategiile centrale, iar execuția paralelă este o realizare importantă în acest sens.

Blockchain-urile tradiționale tratează de obicei tranzacțiile una câte una, ceea ce limitează semnificativ viteza tranzacțiilor, în special în rețelele aglomerate, ceea ce duce la congestie. Cu toate acestea, prin execuția paralelă, mai multe tranzacții pot fi procesate simultan, crescând astfel semnificativ eficiența execuției și reducând presiunea pe lanț.

Pentru a înțelege mai bine ce este paralelismul, vom începe prin a explica execuția, folosind Ethereum în modul PBS după fuziune ca exemplu, pentru a ilustra ce este execuția și a arăta locul pe care îl ocupă execuția în întreaga viață a tranzacției.

Etapele specifice ale execuției tranzacției

  1. Tranzacția intră în mempool și este filtrată și ordonată: aceasta este etapa de preprocesare după ce tranzacția este trimisă, incluzând interacțiunea între Mempool, Searcher și Builder, completând filtrarea și ordonarea tranzacției.

  2. Builder-ul construiește blocul (dar nu îl execută): Builder-ul aranjează tranzacțiile profitabile într-un bloc pentru a finaliza împachetarea și ordonarea tranzacțiilor.

  3. Proposer-ul validează și trimite blocul: după finalizarea construcției blocului, Builder-ul va trimite propunerea blocului către Proposer. Proposer-ul validează structura blocului și conținutul tranzacției, apoi trimite oficial blocul în rețea pentru a începe execuția.

  4. Execuția tranzacției: după trimiterea blocului, nodurile execută tranzacțiile din bloc una câte una. Aceasta este etapa esențială a actualizării stării, fiecare tranzacție va declanșa apeluri de contracte inteligente, modificări ale soldurilor conturilor sau schimbări de stare.

  5. Martorii atestă: validatorii atestă rezultatul execuției blocului și rădăcina stării, considerându-le ca fiind confirmări finale. Acest lucru asigură autenticitatea și validitatea blocului în stratul de execuție și previne inconsistența.

  6. Sincronizarea stării: fiecare nod va sincroniza rezultatul execuției blocului (de exemplu, soldurile contului, actualizările stării contractului etc.) la starea sa locală; după executarea fiecărei tranzacții, nodul calculează și stochează o nouă rădăcină de stare pentru a fi utilizată ca stare inițială în blocul următor.

Desigur, aceasta este doar sincronizarea stării tranzacțiilor pe baza blocului; pentru a menține starea actualizată pe lanț, de obicei, nodurile vor sincroniza datele bloc cu bloc și vor continua să verifice blocul și starea. Dar pentru a atinge finalitatea sub mecanismul POS, este necesar ca agregatorul să agregheze semnăturile martorilor din fiecare Slot într-o semnătură completă și să o transmită Proposer-ului din Slot-ul următor. De asemenea, validatorii trebuie să confirme starea tuturor blocurilor din acel Epoch bazându-se pe numărul de voturi, formând un punct de verificare temporar al stării consensuale. Atunci când două Epoch-uri consecutive obțin majoritatea sprijinului martorilor, blocul și tranzacțiile vor atinge finalitatea.

Privind întreaga viață a tranzacției, execuția are loc după ce Proposer validează structura blocului și conținutul tranzacției trimise de Builder. Procesul efectiv de execuție necesită procesarea tranzacțiilor una câte una și actualizarea stării conturilor sau contractelor corespunzătoare. După finalizarea execuției tuturor tranzacțiilor, Proposer va calcula un nou rădăcină de stare (rădăcina Merkle), care este un rezumat al rezultatelor execuției tuturor tranzacțiilor din blocul curent și al stării globale finale. Pe scurt, procesul complet de execuție a blocului include o serie de calcule care trebuie finalizate pentru a transforma Ethereum dintr-o stare anterioară într-o stare următoare, de la execuția fiecărei tranzacții până la calculul rădăcinii Merkle.

Execuție secvențială

Ceea ce este opus paralelismului este execuția secvențială, adică modul de execuție care este în prezent mai comun în blockchain. De obicei, tranzacțiile sunt executate treptat, în ordine. Când o tranzacție este finalizată, Ethereum va actualiza starea contului și informațiile relevante (de exemplu, soldul, datele stocate în contract) în arborele de stare al contului, generând un nou hash de stare a contului. După ce toate arborele de stare ale contului sunt actualizate, se va forma un nod rădăcină al arborelui de stare cunoscut sub numele de rădăcina Merkle de stare. După finalizarea rădăcinii Merkle de stare, rădăcinii Merkle de tranzacție și rădăcinii Merkle de recepție, capul blocului va efectua un calcul hash, generând hash-ul blocului.

În această privință, ordinea de execuție a tranzacției este crucială. Deoarece arborele Merkle este un arbore binar de valori hash, valorile rădăcinii Merkle formate în ordini diferite vor fi diferite.

Execuție paralelă

Într-un mediu de execuție paralel, nodurile vor încerca să proceseze tranzacțiile din bloc în paralel. Acestea nu vor fi executate una câte una în ordine, ci vor fi alocate pe diferite „căi de execuție”, permițându-le să execute simultan. Prin execuția paralelă, sistemul poate gestiona mai eficient tranzacțiile din bloc, crescând capacitatea de procesare.

După finalizarea execuției tuturor tranzacțiilor, nodul va rezuma rezultatul execuției (adică actualizările stării influențate de tranzacții), formând un nou statut al blocului. Această stare va fi adăugată la blockchain, reprezentând cea mai recentă stare globală de pe lanț.

Conflict de stare

Deoarece paralelismul poate gestiona tranzacțiile pe căi diferite în același timp, un mare obstacol al paralelismului este conflictul de stare. Aceasta înseamnă că pot exista mai multe tranzacții care efectuează operațiuni de citire sau scriere asupra aceleași părți de date (stare) din blockchain în aceeași perioadă de timp. Dacă o astfel de situație nu este gestionată corespunzător, rezultatul execuției va fi incert. Deoarece ordinea actualizării stării este diferită, rezultatul final al calculului va fi diferit. De exemplu,

Să presupunem că există două tranzacții, tranzacția A și tranzacția B, care încearcă să actualizeze soldul aceluiași cont:

  • Tranzacție A: Crește soldul contului cu 10.

  • Tranzacție B: Crește soldul contului cu 20.

Soldul inițial al contului este de 100.

Dacă executăm în serie, rezultatul ordinii de execuție este determinat:

1. Executați mai întâi tranzacția A, apoi tranzacția B:

  • Soldul contului crește mai întâi cu 10, ajungând la 110.

  • Apoi crește cu 20, ajungând în final la 130.

2. Executați mai întâi tranzacția B, apoi tranzacția A:

  • Soldul contului crește mai întâi cu 20, ajungând la 120.

  • Apoi crește cu 10, ajungând în final la 130.

În aceste două ordini, soldul final este de 130, deoarece sistemul asigură consistența ordinii de execuție a tranzacției.

Dar în mediu de execuție paralel, tranzacția A și tranzacția B ar putea citi simultan soldul inițial de 100 și să efectueze calculele proprii:

  1. Tranzacția A a citit un sold de 100, iar după calcul, a actualizat soldul la 110.

  2. Tranzacția B a citit, de asemenea, un sold de 100, iar după calcul, a actualizat soldul la 120.

În acest caz, datorită execuției simultane a tranzacțiilor, soldul final este actualizat doar la 120, nu la 130, deoarece operațiile tranzacției A și B „acoperă” rezultatul celuilalt, generând un conflict de stare.

Aceste tipuri de probleme cu conflictele de stare sunt adesea denumite „suprapunerea datelor”, adică atunci când tranzacțiile încearcă să modifice simultan aceleași date, acestea pot acoperi rezultatele de calcul ale celuilalt, ducând la o stare finală incorectă. O altă problemă care poate rezulta din conflictul de stare este imposibilitatea de a garanta ordinea execuției. Deoarece mai multe tranzacții finalizează operațiunile în perioade diferite, se pot produce ordini diferite de execuție. Ordini diferite pot duce la rezultate diferite de calcul, făcând rezultatul incert.

Pentru a evita această incertitudine, sistemele de execuție paralelă de pe blockchain introduc de obicei unele mecanisme de verificare a conflictelor și rollback, sau analizează în avans dependențele tranzacțiilor pentru a se asigura că acestea sunt executate în paralel fără a afecta consistența finală a stării.

Paralelism optimist vs. paralelism determinist

Există două metode de abordare a problemei posibile a conflictelor de stare: paralelismul determinist și paralelismul optimist. Aceste două modele au compromisuri în ceea ce privește eficiența și complexitatea designului.

Paralelismul determinist necesită declararea prealabilă a accesului la stare, validatorii sau sequencerii vor verifica accesul declarat la stare în timpul ordonării tranzacțiilor. Dacă există mai multe tranzacții care încearcă să scrie la aceeași stare, aceste tranzacții vor fi marcate ca fiind în conflict, evitând execuția simultană. Diferitele lanțuri implementează forme diferite de declarare prealabilă a stării, dar în general includ următoarele moduri:

  • Prin constrângerea specificațiilor contractelor: dezvoltatorii specifică direct domeniul de acces la stare în contractele inteligente. De exemplu, transferul de token-uri ERC-20 necesită acces la câmpurile de sold ale expeditorului și destinatarului.

  • Prin declararea datelor structurate ale tranzacției: adăugând câmpuri speciale în tranzacție pentru a marca accesul la stare.

  • Prin analiza compilatorului: compilatoarele limbajelor de înalt nivel pot analiza static codul contractului și pot genera automat un set de acces la stare.

  • Prin impunerea declarației prin intermediul cadrului: anumite cadre cer dezvoltatorilor să specifice explicit stările de acces necesare atunci când apelează funcții.

Paralelismul optimist va procesa tranzacțiile optimist mai întâi, iar atunci când apar conflicte, tranzacțiile afectate vor fi re-executate în ordine. Pentru a evita cât mai mult posibil apariția conflictelor, nucleul designului paralelismului optimist este de a face estimări rapide și ipoteze asupra stării folosind date istorice, analize statice etc. Asta înseamnă că sistemul, fără a verifica complet, presupune că anumite operațiuni sau actualizări de stare sunt valide, încercând să evite așteptarea tuturor proceselor de verificare pentru a îmbunătăți astfel performanța și capacitatea de procesare.

Deși paralelismul optimist poate evita cât mai mult posibil apariția conflictelor prin estimări rapide și ipoteze asupra stării, vor exista în continuare unele provocări inevitabile, în special atunci când sunt implicate execuții de contracte sau tranzacții între lanțuri. Dacă conflictele apar frecvent, re-executarea poate încetini semnificativ performanța sistemului și crește consumul de resurse de calcul.

Paralelismul determinist evită conflictele posibile prin verificarea dependențelor stării înainte de tranzacție pentru a evita situațiile de conflict care ar putea apărea în paralelismul optimist, dar deoarece este necesar să se declare cu exactitate dependențele stării înainte de trimiterea tranzacției, acest lucru impune cerințe mai mari dezvoltatorilor, crescând astfel complexitatea implementării.

Dilema paralelismului EVM

A aborda conflictul de stare nu se limitează doar la determinism și optimist; în procesul de realizare a paralelismului, este necesar să se ia în considerare și arhitectura bazei de date a blockchain-ului. Problema conflictului de stare în paralel este deosebit de dificilă în EVM-ul sub arhitectura Merkle Tree. Arborele Merkle este o structură de hash pe niveluri; după fiecare modificare a datelor de stare de către o tranzacție, hash-ul rădăcinii arborelui Merkle trebuie de asemenea actualizat. Acest proces de actualizare este recursiv, calculând de la nodurile frunzelor în sus, până la nodul rădăcină. Deoarece hash-ul este ireversibil, adică devine posibil să se calculeze nivelul superior abia după ce modificările de la nivelul inferior sunt finalizate, această caracteristică face actualizarea paralelă dificilă.

Dacă două tranzacții sunt executate în paralel și accesează aceeași stare (de exemplu, soldul contului), va apărea un conflict de noduri în arborele Merkle. Iar soluționarea acestui conflict necesită, de obicei, mecanisme suplimentare de gestionare a tranzacțiilor pentru a asigura consistența valorii hash a rădăcinii în mai multe ramuri. Acest lucru nu este ușor de realizat pentru EVM, deoarece trebuie să facă compromisuri între paralelizare și consistența stării.

Soluții de paralelism non-EVM

Solana

Spre deosebire de arborele global de stare al Ethereum, Solana a adoptat un model de cont. Fiecare cont este un spațiu de stocare independent, stocat în registru, evitând astfel problemele de conflict de cale.

Solana este un sistem de paralelism determinist. În Solana, fiecare tranzacție trebuie să declare explicit conturile pe care le va accesa și permisiunile necesare (doar citire sau citire/scriere) în momentul trimiterii. Acest design permite nodurilor blockchain să analizeze în avans resursele pe care fiecare tranzacție trebuie să le acceseze înainte de execuție. Deoarece tranzacțiile au declarat anterior toate relațiile de dependență ale conturilor, nodurile pot determina ce tranzacții vor accesa aceleași conturi și care tranzacții pot fi executate în siguranță în paralel, realizând astfel programarea inteligentă pentru a evita conflictele, stabilind astfel baza pentru programarea paralelă.

Deoarece fiecare tranzacție a declarat înainte de execuție conturile și permisiunile necesare, Solana poate verifica dacă există relații de dependență între tranzacții (modelul Sealevel). Dacă tranzacțiile nu împărtășesc conturi de citire și scriere, sistemul le poate aloca pe diferite procesoare pentru a fi executate în paralel.

Aptos

Designul execuției paralele al Aptos este diferit de Ethereum, având unele inovații cheie în arhitectură și mecanisme, reflectate în modelul de cont și stocarea stării.

Ethereum trebuie să actualizeze frecvent arborele său global de stare (MPT) atunci când execută tranzacții. Toate conturile și stările contractelor sunt stocate într-un arbore de stare partajat, orice tranzacție trebuie să acceseze și să actualizeze o parte din acest arbore de stare. Pe de altă parte, Aptos a împărțit conturile în unități de stare independente, fiecare obiect fiind o pereche cheie-valoare independentă, iar obiectele pot exista independent, fără a se influența reciproc, asociindu-se doar atunci când există relații de referință clare. Obiectele nu au căi comune în arbore, evitând competiția de blocare, permițându-le să funcționeze complet în paralel.

Structura de date de bază a Aptos este Jellyfish Merkle Tree. Starea fiecărui obiect este stocată în cele din urmă în JMT, ca un pereche cheie-valoare independentă. Spre deosebire de MPT-ul Ethereum, Jellyfish Merkle Tree are o structură complet binară, care simplifică calea de stocare și calea de interogare a nodurilor, reducând semnificativ timpul de validare. De asemenea, fiecare cont are o poziție fixă în arbore, iar nodurile din arbore sunt stocate independent, permițând actualizări și căutări paralele pentru mai multe conturi.

Aptos este un sistem optimist în paralel, care nu necesită furnizarea prealabilă a tuturor relațiilor de dependență ale conturilor. În acest scop, Aptos folosește Block-STM, care utilizează un ordin de tranzacție presetat pentru a estima dependențele, reducând astfel numărul de opriri.

EVM paralel

Comparativ cu paralelismul non-EVM, paralelismul EVM se confruntă cu dificultăți tehnice mai mari în gestionarea dependențelor stării, verificării conflictelor, gestionării gazului și mecanismelor de rollback. Pentru a înțelege mai bine acest lucru, putem face referire la cum unele proiecte EVM paralele (cum ar fi Sui, Monad, Canto) rezolvă aceste probleme.

Sui

Sui, la fel ca Aptos, folosește un model de obiect pentru a gestiona starea, adoptând fiecare obiect (de exemplu, statul contului, statul contractului inteligent) ca o resursă independentă, aceste obiecte fiind distinse prin identificatori unici. Când tranzacțiile implică obiecte diferite, acestea pot fi procesate în paralel, deoarece ele operează asupra unor stări diferite, fără a genera conflicte directe.

Deși Sui folosește un model de obiect pentru a gestiona starea, arhitectura Sui, pentru a fi compatibilă cu EVM, folosește un strat suplimentar de adaptare sau mecanisme abstracte pentru a conecta modelul de obiect la modelul de cont EVM.

În Sui, programarea tranzacțiilor utilizează o strategie de paralelism optimist, presupunând că nu există conflicte între tranzacții. Dacă apar conflicte, sistemul va folosi mecanismul de rollback pentru a restaura starea.

Sui a folosit un model de obiect și tehnici de izolare a stării, reușind să evite eficient problemele de dependență a stării. Fiecare obiect este un resursă independentă, tranzacții diferite pot fi executate în paralel, crescând astfel capacitatea de procesare și eficiența. Dar compromisul acestei metode este complexitatea modelului de obiect și costul mecanismului de rollback. Dacă apar conflicte între tranzacții, este necesar să se revină la o parte din stare, ceea ce va crește povara sistemului și ar putea afecta eficiența procesării paralele. Comparativ cu sistemele de paralelism non-EVM (cum ar fi Solana), Sui necesită mai multe resurse de calcul și stocare pentru a menține o paralelism eficient.

Monad

La fel ca Sui, Monad adoptă și el o abordare optimistă în paralel. Totuși, optimizarea în paralel a Monad va face predicții asupra unor tranzacții care au relații de dependență înainte de a le executa efectiv, iar predicțiile sunt realizate în principal prin analizorul de cod static al Monad. Predicția necesită acces la stare, iar modul în care baza de date Ethereum stochează starea face ca accesul la stare să fie foarte dificil. Pentru a face procesul de citire a stării mai eficient în paralel, Monad a refăcut și baza de date.

Arborele de stare Monad este împărțit pe regiuni, fiecare regiune întreținând propriul subarbore de stare. La actualizare, este nevoie să se modifice doar fragmentele relevante, fără a reconstruie întregul arbore de stare. Folosind un tabel de indexare a stării, se poate localiza rapid starea din regiune, reducând interacțiunile între regiuni.

Concluzie

Nucleul paralelismului este creșterea eficienței execuției prin executarea pe mai multe căi, iar pentru a realiza execuția pe mai multe căi, blockchain-ul trebuie să efectueze o serie de verificări de conflicte și mecanisme de rollback pentru a se asigura că acestea sunt executate în paralel fără a afecta consistența stării finale și să efectueze anumite îmbunătățiri în baza de date.

Desigur, îmbunătățirea eficienței stratului de execuție nu se limitează la paralelism; optimizările din etapa de execuție pot fi realizate și prin reducerea operațiunilor de citire/scriere necesare pentru o tranzacție în baza de date. Îmbunătățirea vitezei întregului lanț implică o gamă mai largă de aspecte, inclusiv îmbunătățirea eficienței stratului de consens.

Fiecare tehnologie are condițiile sale specifice de limitare. Paralelismul este doar una dintre modalitățile de a crește eficiența; decizia finală de a utiliza această tehnologie trebuie să ia în considerare dacă este prietenoasă cu dezvoltatorii, dacă poate fi realizată fără a sacrifica descentralizarea, etc. Stiva tehnologică nu trebuie să fie neapărat mai mare pentru a fi mai bună; cel puțin, în cazul Ethereum, paralelismul nu este atât de atrăgător. Dacă privim pur din perspectiva creșterii eficienței, adăugarea paralelismului la Ethereum nu este soluția optimă, fie din considerente de simplitate, fie din perspectiva foaiei de parcurs centrată pe Rollup a Ethereum.