Nyilvános teszt: Megoldás az adatvédelemhez és a méretezhetőséghez az Ethereumon

Blockchain egy innovatív technológia, amely az emberi élet számos területén javítani fog. Valódi folyamatokat és termékeket helyez át a digitális térbe, biztosítja a pénzügyi tranzakciók gyorsaságát és megbízhatóságát, csökkenti azok költségeit, valamint lehetővé teszi modern DAPP alkalmazások létrehozását intelligens szerződések segítségével decentralizált hálózatokban.

Tekintettel a blokklánc számos előnyére és sokféle alkalmazására, meglepőnek tűnhet, hogy ez az ígéretes technológia még nem jutott el minden iparágba. A probléma az, hogy a modern decentralizált blokkláncok nem skálázhatók. Az Ethereum körülbelül 20 tranzakciót dolgoz fel másodpercenként, ami nem elég a mai dinamikus üzletek igényeinek kielégítésére. Ugyanakkor a blokklánc technológiát használó cégek tétováznak az Ethereum feladásától, mivel magas fokú védelmet nyújt a hackelés és a hálózati hibák ellen.

A decentralizáció, a biztonság és a skálázhatóság biztosítása érdekében a blokkláncban, ezzel megoldva a Scalability Trilemma-t, a fejlesztőcsapat Lehetőség létrehozta a Plasma Cash-t, egy intelligens szerződésből és egy Node.js alapú magánhálózatból álló leányláncot, amely időszakonként átadja állapotát a gyökérláncnak (Ethereum).

Nyilvános teszt: Megoldás az adatvédelemhez és a méretezhetőséghez az Ethereumon

A Plasma Cash kulcsfontosságú folyamatai

1. A felhasználó az intelligens szerződés függvényt "befizetés"-nek hívja, és átadja abba az ETH összegét, amelyet a Plasma Cash tokenbe szeretne befizetni. Az intelligens szerződés funkció létrehoz egy tokent, és eseményt generál róla.

2. Az intelligens szerződéses eseményekre előfizetett Plasma Cash csomópontok eseményt kapnak a letét létrehozásáról, és hozzáadnak egy tranzakciót a token létrehozásáról a készlethez.

3. Időnként a speciális Plasma Cash csomópontok minden tranzakciót (legfeljebb 1 milliót) vesznek a készletből, és blokkot képeznek belőlük, kiszámítják a Merkle-fát és ennek megfelelően a hash-t. Ezt a blokkot elküldi más csomópontoknak ellenőrzésre. A csomópontok ellenőrzik, hogy a Merkle hash érvényes-e, és hogy a tranzakciók érvényesek-e (például, hogy a token feladója a tulajdonosa). A blokk ellenőrzése után a csomópont meghívja az intelligens szerződés "submitBlock" függvényét, amely elmenti a blokkszámot és a Merkle-kivonatot az élláncba. Az intelligens szerződés egy eseményt generál, amely jelzi egy blokk sikeres hozzáadását. A tranzakciókat eltávolítják a készletből.

4. A blokkküldési eseményt fogadó csomópontok elkezdik alkalmazni a blokkhoz hozzáadott tranzakciókat.

5. Egy bizonyos ponton a token tulajdonosa (vagy nem tulajdonosa) ki akarja venni azt a Plasma Cash-ből. Ehhez meghívja a `startExit` függvényt, átadva neki a token utolsó 2 tranzakciójáról szóló információkat, amelyek megerősítik, hogy ő a token tulajdonosa. Az intelligens szerződés a Merkle hash segítségével ellenőrzi a tranzakciók meglétét a blokkban, és elküldi a tokent visszavonásra, ami két héten belül megtörténik.

6. Ha a token-kivonási művelet szabálysértésekkel történt (a token a visszavonási eljárás megkezdése után került elköltésre, vagy a token a visszavonás előtt már valaki másé volt), a token tulajdonosa két héten belül megcáfolhatja a visszavonást.

Nyilvános teszt: Megoldás az adatvédelemhez és a méretezhetőséghez az Ethereumon

Az adatvédelem kétféleképpen érhető el

1. A gyökérlánc semmit sem tud az utódláncon belül generált és továbbított tranzakciókról. Az ETH Plasma Cash-ből történő letétbe helyezésére és visszavonására vonatkozó információk továbbra is nyilvánosak.

2. A gyermeklánc lehetővé teszi a névtelen tranzakciókat a zk-SNARK használatával.

Technológiai verem

  • NodeJS
  • Feleinek
  • Éterium
  • Talaj

tesztelés

A Plasma Cash fejlesztése során teszteltük a rendszer sebességét, és a következő eredményeket kaptuk:

  • másodpercenként akár 35 000 tranzakció is hozzáadódik a készlethez;
  • egy blokkban akár 1 000 000 tranzakció is tárolható.

A teszteket a következő 3 szerveren végezték el:

1. Intel Core i7-6700 négymagos Skylake NVMe SSD – 512 GB, 64 GB DDR4 RAM
3 validáló Plasma Cash csomópont került felállításra.

2. AMD Ryzen 7 1700X nyolcmagos „Summit Ridge” (Zen), SATA SSD – 500 GB, 64 GB DDR4 RAM
A Ropsten testnet ETH csomópont fel lett emelve.
3 validáló Plasma Cash csomópont került felállításra.

3. Intel Core i9-9900K nyolcmagos NVMe SSD – 1 TB, 64 GB DDR4 RAM
1 Plasma Cash benyújtási csomópont megtörtént.
3 validáló Plasma Cash csomópont került felállításra.
Tesztet indítottak a Plasma Cash hálózathoz történő tranzakciók hozzáadására.

Összesen: 10 Plasma Cash csomópont egy privát hálózatban.

1. teszt

Blokonként 1 millió tranzakció van korlátozva. Emiatt 1 millió tranzakció 2 blokkra esik (mivel a rendszer képes a tranzakciók egy részét felvenni és küldés közben elküldeni).


Kezdeti állapot: utolsó blokk #7; 1 millió tranzakció és token van tárolva az adatbázisban.

00:00 — a tranzakciógeneráló szkript kezdete
01:37 - 1 millió tranzakció jött létre, és megkezdődött a küldés a csomópontra
01:46 — A benyújtási csomópont 240 8 tranzakciót vett át a készletből, és a 320. számú űrlapblokkot nyomtatta. Azt is látjuk, hogy 10 másodperc alatt XNUMX XNUMX tranzakció kerül a készletbe
01:58 — A 8-as blokk aláírása megtörtént és ellenőrzésre elküldve
02:03 — a 8-as blokk érvényesítése megtörténik, és az intelligens szerződés "submitBlock" funkciója meghívásra kerül a Merkle-kivonattal és blokkszámmal
02:10 — befejeződött a demó szkript, amely 1 másodperc alatt 32 millió tranzakciót küldött
02:33 - a csomópontok információkat kaptak arról, hogy a 8-as blokk hozzáadásra került a gyökérlánchoz, és 240 XNUMX tranzakciót kezdtek végrehajtani
02:40 - 240 8 tranzakciót eltávolítottak a készletből, amelyek már a XNUMX-as blokkban vannak
02:56 – A benyújtó csomópont kivette a fennmaradó 760 9 tranzakciót a készletből, és elkezdte kiszámítani a Merkle-kivonatot és a XNUMX-es aláírási blokkot
03:20 - minden csomópont 1 millió 240 XNUMX tranzakciót és tokent tartalmaz
03:35 — A 9-es blokk aláírása megtörténik, és ellenőrzésre elküldi más csomópontoknak
03:41 - hálózati hiba történt
04:40 — a 9. blokk érvényesítésének várakozása lejárt
04:54 – A benyújtó csomópont kivette a fennmaradó 760 9 tranzakciót a készletből, és elkezdte kiszámítani a Merkle-kivonatot és a XNUMX-es aláírási blokkot
05:32 — A 9-es blokk aláírása megtörténik, és ellenőrzésre elküldi más csomópontoknak
05:53 — a 9-es blokk érvényesítése és elküldése a gyökérláncnak
06:17 - a csomópontok elkezdtek információt kapni arról, hogy a 9-es blokkot hozzáadták a gyökérlánchoz, és 760 XNUMX tranzakciót kezdtek végrehajtani
06:47 — a pool törölte a 9. blokkban lévő tranzakciókat
09:06 - minden csomópont 2 millió tranzakciót és tokent tartalmaz

2. teszt

Blokonként 350 3 limit van. Ennek eredményeként XNUMX blokkunk van.


Kezdeti állapot: utolsó blokk #9; 2 millió tranzakció és token tárolódik az adatbázisban

00:00 — a tranzakciógeneráló szkript már elindult
00:44 - 1 millió tranzakció jött létre, és megkezdődött a küldés a csomópontra
00:56 — A benyújtási csomópont 320 10 tranzakciót vett át a készletből, és a 320. számú űrlapblokkot nyomtatta. Azt is látjuk, hogy 10 másodperc alatt XNUMX XNUMX tranzakció kerül a készletbe
01:12 — A 10-es blokk aláírása megtörténik és elküldésre kerül a többi csomópontnak ellenőrzésre
01:18 — befejeződött a demó szkript, amely 1 másodperc alatt 34 millió tranzakciót küldött
01:20 — a 10-es blokk érvényesítése és elküldése a gyökérláncnak
01:51 - minden csomópont információt kapott a gyökérlánctól, hogy a 10-es blokk hozzáadásra került, és elkezdik alkalmazni a 320 XNUMX tranzakciót
02:01 - a pool 320 10 tranzakciót törölt, amelyek a XNUMX. blokkhoz lettek hozzáadva
02:15 — A benyújtási csomópont 350 11 tranzakciót vett át a készletből, és űrlapblokk #XNUMX
02:34 — A 11-es blokk aláírása megtörténik és elküldésre kerül a többi csomópontnak ellenőrzésre
02:51 — a 11-es blokk érvényesítése és elküldése a gyökérláncnak
02:55 — az utolsó csomópont befejezte a tranzakciókat a 10. blokkból
10:59 — a 9. blokk beküldésével történt tranzakció nagyon sokáig tartott a gyökérláncban, de befejeződött, és minden csomópont kapott róla információt, és elkezdett 350 XNUMX tranzakciót végrehajtani.
11:05 - a pool 320 11 tranzakciót törölt, amelyek a XNUMX. blokkhoz lettek hozzáadva
12:10 – minden csomópont 1 millió 670 XNUMX tranzakciót és tokent tartalmaz
12:17 — A benyújtási csomópont 330 12 tranzakciót vett át a készletből, és űrlapblokk #XNUMX
12:32 — A 12-es blokk aláírása megtörténik és elküldésre kerül a többi csomópontnak ellenőrzésre
12:39 — a 12-es blokk érvényesítése és elküldése a gyökérláncnak
13:44 - minden csomópont információt kapott a gyökérlánctól, hogy a 12-es blokk hozzáadásra került, és elkezdik alkalmazni a 330 XNUMX tranzakciót
14:50 - minden csomópont 2 millió tranzakciót és tokent tartalmaz

3. teszt

Az első és a második szerveren az egyik érvényesítő csomópontot egy beküldő csomópont váltotta fel.


Kezdeti állapot: utolsó blokk # 84; 0 tranzakció és token mentve az adatbázisban

00:00 – 3 szkript indult, amelyek egyenként 1 millió tranzakciót generálnak és küldenek
01:38 – 1 millió tranzakció jött létre, és megkezdődött a küldés a #3
01:50 — A 3. elküldési csomópont 330 85 tranzakciót vett át a készletből, és a 21. számú űrlapblokkot (f350) készítette. Azt is látjuk, hogy 10 másodperc alatt XNUMX XNUMX tranzakció kerül a készletbe
01:53 – 1 millió tranzakció jött létre, és megkezdődött a küldés a #1
01:50 — A 3. elküldési csomópont 330 85 tranzakciót vett át a készletből, és a 21. számú űrlapblokkot (f350) készítette. Azt is látjuk, hogy 10 másodperc alatt XNUMX XNUMX tranzakció kerül a készletbe
02:01 — Az 1. beküldési csomópont 250 85 tranzakciót vett át a készletből, és a 65. számú űrlapblokkot (XNUMXe)
02:06 — a 85-ös blokk (f21) aláírásra kerül és elküldésre kerül a többi csomópontnak érvényesítés céljából
02:08 — a 3-as szerver bemutató szkriptje, amely 1 másodperc alatt 30 millió tranzakciót küldött, befejezte a működését
02:14 — a 85-ös blokk (f21) érvényesítése megtörténik, és elküldésre kerül a gyökérláncnak
02:19 — a #85 (65e) blokk aláírása megtörténik és elküldésre kerül a többi csomópontnak ellenőrzésre
02:22 – 1 millió tranzakció jött létre, és megkezdődött a küldés a #2
02:27 — #85 (65e) blokk érvényesítve és elküldve a gyökérláncnak
02:29 — A 2. elküldési csomópont 111855 tranzakciót vett át a készletből, és a 85-ös űrlapblokkot (256).
02:36 — a 85-ös blokk (256) aláírásra kerül és elküldésre kerül más csomópontokhoz érvényesítés céljából
02:36 — a 1-as szerver bemutató szkriptje, amely 1 másodperc alatt 42.5 millió tranzakciót küldött, befejezte a működését
02:38 — a #85 (256) blokk érvényesítése megtörténik, és elküldésre kerül a gyökérláncnak
03:08 — A 2. szerver szkriptje elkészült, amely 1 másodperc alatt 47 millió tranzakciót küldött
03:38 - minden csomópont információt kapott a gyökérlánctól, hogy a #85 (f21), #86(65e), #87(256) blokkok hozzáadásra kerültek, és elkezdték alkalmazni a 330k, 250k, 111855 tranzakciókat
03:49 - a készletet 330 250, 111855 85, 21 86 tranzakciónál törölték, amelyeket hozzáadtak a 65. (f87), #256(XNUMXe), #XNUMX(XNUMX) blokkhoz.
03:59 — Az 1. beküldési csomópont 888145 88 tranzakciót vett a készletből, és a 214 (2) űrlapblokk, a 750. elküldési csomópont 88 50 tranzakciót vett a készletből és a 3. űrlapblokk (670a), a 88. elküldési csomópont 3 XNUMX tranzakciót vett a medence és a XNUMX-as űrlapblokk (dXNUMXb)
04:44 — a 88-as blokk (d3b) aláírásra kerül és elküldésre kerül a többi csomópontnak ellenőrzésre
04:58 — a 88-ös blokk (214) aláírásra kerül és elküldésre kerül más csomópontokhoz érvényesítés céljából
05:11 — a 88-as blokk (50a) aláírásra kerül és elküldésre kerül a többi csomópontnak ellenőrzésre
05:11 — a 85-ös blokk (d3b) érvényesítése megtörténik, és elküldésre kerül a gyökérláncnak
05:36 — a #85 (214) blokk érvényesítése megtörténik, és elküldésre kerül a gyökérláncnak
05:43 - minden csomópont információt kapott a gyökérlánctól, hogy a #88 (d3b), #89(214) blokkok hozzáadásra kerültek, és elkezdik alkalmazni a 670k, 750k tranzakciókat
06:50 — kommunikációs hiba miatt a #85. blokk (50a) nem lett érvényesítve
06:55 — a 2. elküldési csomópont 888145 tranzakciót vett át a készletből, és a 90. űrlapblokk (50a)
08:14 — a 90-as blokk (50a) aláírásra kerül és elküldésre kerül a többi csomópontnak ellenőrzésre
09:04 — a #90 (50a) blokk érvényesítése és elküldése a gyökérláncnak
11:23 – minden csomópont információt kapott a gyökérlánctól, hogy a #90 (50a) blokk hozzáadásra került, és elkezdik alkalmazni a 888145 tranzakciókat. Ugyanakkor a 3-as szerver már alkalmazta a 88-as (d3b), a 89-es (214-es) blokkokból származó tranzakciókat.
12:11 - minden medence üres
13:41 — a 3. szerver összes csomópontja 3 millió tranzakciót és tokent tartalmaz
14:35 — a 1. szerver összes csomópontja 3 millió tranzakciót és tokent tartalmaz
19:24 — a 2. szerver összes csomópontja 3 millió tranzakciót és tokent tartalmaz

Akadályok

A Plasma Cash fejlesztése során a következő problémákkal találkoztunk, amelyeket fokozatosan megoldottunk és megoldunk:

1. Konfliktus a különböző rendszerfunkciók kölcsönhatásában. Például a tranzakciók készlethez való hozzáadásának funkciója blokkolta a blokkok beküldésének és érvényesítésének munkáját, és fordítva, ami a sebesség csökkenéséhez vezetett.

2. Nem volt azonnal világos, hogyan lehet nagy számú tranzakciót küldeni az adatátviteli költségek minimalizálása mellett.

3. Nem volt világos, hogyan és hol kell tárolni az adatokat a magas eredmények elérése érdekében.

4. Nem volt világos, hogyan kell hálózatot szervezni a csomópontok között, mivel egy 1 millió tranzakciós blokk mérete körülbelül 100 MB-ot foglal el.

5. Az egyszálú üzemmódban végzett munka megszakítja a csomópontok közötti kapcsolatot, ha hosszú számítások történnek (például Merkle-fa felépítése és hash kiszámítása).

Hogyan kezeltük mindezt?

A Plasma Cash csomópont első verziója egyfajta kombájn volt, amely mindent egyszerre tudott: tranzakciókat fogadni, blokkokat küldeni és érvényesíteni, valamint API-t biztosítani az adatok eléréséhez. Mivel a NodeJS natívan egyszálú, a nehéz Merkle-fa számítási függvény blokkolta a tranzakció hozzáadása funkciót. Két lehetőséget láttunk a probléma megoldására:

1. Indítson el több NodeJS-folyamatot, amelyek mindegyike meghatározott funkciókat lát el.

2. Használja a worker_threads parancsot, és helyezze át a kód egy részének végrehajtását szálakba.

Ennek eredményeként mindkét opciót egyszerre használtuk: logikailag 3 részre osztottuk az egyik csomópontot, amelyek külön-külön, de ugyanakkor szinkronban is működhetnek.

1. Beküldési csomópont, amely elfogadja a tranzakciókat a készletbe, és blokkokat hoz létre.

2. Egy érvényesítő csomópont, amely ellenőrzi a csomópontok érvényességét.

3. API csomópont – API-t biztosít az adatok eléréséhez.

Ebben az esetben az egyes csomópontokhoz egy unix socketen keresztül csatlakozhat a cli használatával.

A nehéz műveleteket, például a Merkle-fa kiszámítását külön szálba helyeztük át.

Ezzel elértük az összes Plasma Cash funkció egyidejű és hibamentes működését.

Miután a rendszer működőképes volt, megkezdtük a sebesség tesztelését, és sajnos nem kielégítő eredményeket kaptunk: 5 tranzakció másodpercenként és akár 000 50 tranzakció blokkonként. Rá kellett jönnöm, hogy mit valósítottam meg rosszul.

Kezdetben elkezdtük tesztelni a Plasma Cash kommunikációs mechanizmusát, hogy megtudjuk a rendszer csúcsteljesítményét. Korábban írtuk, hogy a Plasma Cash csomópont egy unix socket interfészt biztosít. Kezdetben szövegalapú volt. A json objektumok a „JSON.parse()” és a „JSON.stringify()” használatával lettek elküldve.

```json
{
  "action": "sendTransaction",
  "payload":{
    "prevHash": "0x8a88cc4217745fd0b4eb161f6923235da10593be66b841d47da86b9cd95d93e0",
    "prevBlock": 41,
    "tokenId": "57570139642005649136210751546585740989890521125187435281313126554130572876445",
    "newOwner": "0x200eabe5b26e547446ae5821622892291632d4f4",
    "type": "pay",
    "data": "",
    "signature": "0xd1107d0c6df15e01e168e631a386363c72206cb75b233f8f3cf883134854967e1cd9b3306cc5c0ce58f0a7397ae9b2487501b56695fe3a3c90ec0f61c7ea4a721c"
  }
}
```

Megmértük az ilyen objektumok átviteli sebességét, és ~ 130 ezer másodpercet találtunk. Megpróbáltuk lecserélni a szabványos funkciókat a json használatához, de a teljesítmény nem javult. A V8-as motort jól optimalizálni kell ezekhez a műveletekhez.

Az osztályokon keresztül tranzakciókkal, tokenekkel és blokkokkal dolgoztunk. Az ilyen osztályok létrehozásakor a teljesítmény 2-szeresére esett, ami azt jelzi, hogy az OOP nem megfelelő számunkra. Mindent át kellett írnom egy tisztán funkcionális megközelítésre.

Rögzítés az adatbázisban

Kezdetben a Redis-t választották adattárolásra, mint az egyik legproduktívabb megoldást, amely kielégíti a követelményeinket: kulcsérték tárolás, hash táblákkal, készletekkel való munka. Elindítottuk a redis-benchmarkot, és másodpercenként ~80 1 műveletet kaptunk XNUMX folyamatban.

A nagy teljesítmény érdekében a Redist finomabban hangoltuk:

  • Létrejött a unix socket kapcsolat.
  • Letiltottuk az állapot lemezre mentését (a megbízhatóság érdekében beállíthat egy replikát és menthet lemezre egy külön Redisben).

A Redisben a készlet egy hash tábla, mert képesnek kell lennünk az összes tranzakció lekérésére egy lekérdezésben, és egyenként törölnünk kell a tranzakciókat. Próbáltunk egy normál listát használni, de az lassabb a teljes lista kirakásakor.

A szabványos NodeJS használatakor a Redis-könyvtárak másodpercenként 18 9 tranzakciót értek el. A sebesség XNUMX-szeresére csökkent.

Mivel a benchmark azt mutatta, hogy a lehetőségek egyértelműen ötször nagyobbak, elkezdtünk optimalizálni. A könyvtárat ioredisre cseréltük, és 5 25 másodpercenkénti teljesítményt kaptunk. A tranzakciókat egyenként adtuk hozzá a "hset" paranccsal. Ezért sok lekérdezést generáltunk a Redisben. Felmerült az ötlet, hogy a tranzakciókat kötegekbe vonják össze, és egyetlen "hmset" paranccsal küldjék el. Az eredmény 32 ezer másodpercenként.

Több okból is, amelyeket alább ismertetünk, a `Buffer` használatával dolgozunk az adatokkal, és mint kiderült, ha szöveggé alakítja (`buffer.toString('hex')`) írás előtt, további információkat kaphat teljesítmény. Így a sebesség 35k/s-ra nőtt. Jelenleg úgy döntöttünk, hogy felfüggesztjük a további optimalizálást.

Bináris protokollra kellett váltanunk, mert:

1. A rendszer gyakran számít kivonatokat, aláírásokat stb., és ehhez adatokra van szüksége a `Bufferben.

2. Szolgáltatások közötti küldéskor a bináris adatok súlya kisebb, mint a szöveg. Például egy 1 millió tranzakciót tartalmazó blokk küldésekor a szövegben szereplő adatok több mint 300 megabájtot foglalhatnak el.

3. Az adatok folyamatos átalakítása befolyásolja a teljesítményt.

Ezért az adatok tárolására és továbbítására szolgáló saját bináris protokollunkat vettük alapul, amelyet a csodálatos "bináris adat" könyvtár alapján fejlesztettünk ki.

Ennek eredményeként a következő adatstruktúrákat kaptuk:

-Tranzakció

  ```json
  {
    prevHash: BD.types.buffer(20),
    prevBlock: BD.types.uint24le,
    tokenId: BD.types.string(null),
    type: BD.types.uint8,
    newOwner: BD.types.buffer(20),
    dataLength: BD.types.uint24le,
    data: BD.types.buffer(({current}) => current.dataLength),
    signature: BD.types.buffer(65),
    hash: BD.types.buffer(32),
    blockNumber: BD.types.uint24le,
    timestamp: BD.types.uint48le,
  }
  ```

— Token

  ```json
  {
    id: BD.types.string(null),
    owner: BD.types.buffer(20),
    block: BD.types.uint24le,
    amount: BD.types.string(null),
  }
  ```

-Blokk

  ```json
  {
    number: BD.types.uint24le,
    merkleRootHash: BD.types.buffer(32),
    signature: BD.types.buffer(65),
    countTx: BD.types.uint24le,
    transactions: BD.types.array(Transaction.Protocol, ({current}) => current.countTx),
    timestamp: BD.types.uint48le,
  }
  ```

A szokásos "BD.encode(block, Protocol).slice();" és "BD.decode(buffer, Protocol)" parancsokkal az adatokat "Buffer"-be alakítjuk, hogy a Redisben mentsük el, vagy továbbítsuk egy másik csomópontba és lekérjük a vissza az adatokat.

Két bináris protokollunk is van a szolgáltatások közötti adatátvitelhez:

— Protokoll a Plasma Node-dal való interakcióhoz unix aljzaton keresztül

  ```json
  {
    type: BD.types.uint8,
    messageId: BD.types.uint24le,
    error: BD.types.uint8,
    length: BD.types.uint24le,
    payload: BD.types.buffer(({node}) => node.length)
  }
  ```

ahol:

  • `típus` — a végrehajtandó művelet, például 1 — sendTransaction, 2 — getTransaction;
  • `hasznos teher` — adatok, amelyeket át kell adni a megfelelő funkciónak;
  • `messageId` — üzenetazonosító, hogy a válasz azonosítható legyen.

— A csomópontok közötti interakció protokollja

  ```json
  {
    code: BD.types.uint8,
    versionProtocol: BD.types.uint24le,
    seq: BD.types.uint8,
    countChunk: BD.types.uint24le,
    chunkNumber: BD.types.uint24le,
    length: BD.types.uint24le,
    payload: BD.types.buffer(({node}) => node.length)
  }
  ```

ahol:

  • "kód". — üzenetkód, például 6 — PREPARE_NEW_BLOCK, 7 — BLOCK_VALID, 8 — BLOCK_COMMIT;
  • `versionProtocol` — protokoll verzió, mivel különböző verziójú csomópontok hozhatók létre a hálózaton, és eltérően működhetnek;
  • `seq` — üzenetazonosító;
  • `countChunk` и `chunkNumber' nagy üzenetek felosztásához szükséges;
  • "hosszúság". и `hasznos teher` hossza és magát az adatot.

Mivel előre begépeltük az adatokat, a végső rendszer sokkal gyorsabb, mint az Ethereum `rlp` könyvtára. Sajnos még nem tudtuk visszautasítani, hiszen szükséges az okosszerződés véglegesítése, amit a jövőben tervezünk.

Ha sikerült elérni a sebességet 35 000 tranzakciókat másodpercenként, ezeket is az optimális időben kell feldolgoznunk. Mivel a hozzávetőleges blokkképzési idő 30 másodpercet vesz igénybe, bele kell számítanunk a blokkba +1 000 000 XNUMX tranzakciókat, ami azt jelenti, hogy többet kell küldeni 100 MB adat.

Kezdetben az "ethereumjs-devp2p" könyvtárat használtuk a csomópontok közötti kommunikációhoz, de ez nem tudott annyi adatot kezelni. Ennek eredményeként a "ws" könyvtárat használtuk, és beállítottuk a bináris adatok websocketen keresztüli küldését. Természetesen a nagy adatcsomagok küldésekor is találkoztunk problémákkal, de ezeket darabokra osztottuk, és ezek a problémák megszűntek.

Merkle-fa kialakítása és a hash kiszámítása is +1 000 000 XNUMX tranzakciókhoz kb 10 másodpercnyi folyamatos számítás. Ez idő alatt az összes csomóponttal megszakad a kapcsolat. Úgy döntöttek, hogy ezt a számítást egy külön szálba helyezik át.

Következtetések:

Valójában megállapításaink nem új keletűek, de valamiért sok szakértő megfeledkezik róluk a fejlesztés során.

  • Az objektum-orientált programozás helyett a funkcionális programozás használata javítja a termelékenységet.
  • A monolit rosszabb, mint egy produktív NodeJS rendszer szolgáltatási architektúrája.
  • A "worker_threads" használata nehéz számításokhoz javítja a rendszer válaszkészségét, különösen i/o műveletek esetén.
  • A unix socket stabilabb és gyorsabb, mint a http kérések.
  • Ha nagy mennyiségű adatot kell gyorsan átvinni a hálózaton, célszerűbb websocketeket használni, és bináris adatokat küldeni, darabokra bontva, amelyeket továbbíthatunk, ha nem érkeznek meg, majd egy üzenetbe egyesítjük.

Meghívjuk, hogy látogassa meg GitHub projekt: https://github.com/opporty-com/Plasma-Cash/tree/new-version

A cikk társírója volt Alexander Nashivan, vezető fejlesztő Clever Solution Inc.

Forrás: will.com

Hozzászólás