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
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.
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:
A cikk társírója volt Alexander Nashivan, vezető fejlesztő
Forrás: will.com