Viešasis testas: Ethereum privatumo ir mastelio sprendimas

„Blockchain“ yra novatoriška technologija, kuri žada pagerinti daugelį žmogaus gyvenimo sričių. Jis perkelia realius procesus ir produktus į skaitmeninę erdvę, užtikrina finansinių operacijų greitį ir patikimumą, mažina jų savikainą, taip pat leidžia kurti modernias DAPP programas naudojant išmaniąsias sutartis decentralizuotuose tinkluose.

Atsižvelgiant į daugybę „blockchain“ pranašumų ir įvairių pritaikymų, gali atrodyti, kad stebina, kad ši daug žadanti technologija dar nepateko į visas pramonės šakas. Problema ta, kad šiuolaikinėms decentralizuotoms blokų grandinėms trūksta mastelio. „Ethereum“ apdoroja apie 20 operacijų per sekundę, o to nepakanka norint patenkinti šių dienų dinamiško verslo poreikius. Tuo pačiu metu „blockchain“ technologiją naudojančios įmonės nesiryžta atsisakyti „Ethereum“ dėl aukšto lygio apsaugos nuo įsilaužimo ir tinklo gedimų.

Norėdami užtikrinti blokų grandinės decentralizavimą, saugumą ir mastelį, taip išspręsdami Scalability Trilemma, kūrėjų komanda Galimybė sukūrė Plasma Cash – antrinę grandinę, susidedančią iš išmaniosios sutarties ir privataus tinklo, paremto Node.js, kuris periodiškai perduoda savo būseną šakninei grandinei (Ethereum).

Viešasis testas: Ethereum privatumo ir mastelio sprendimas

Pagrindiniai „Plasma Cash“ procesai

1. Vartotojas išmaniosios sutarties funkciją vadina „depozitas“, pervesdamas į ją ETH sumą, kurią jis nori įnešti į „Plasma Cash“ žetoną. Išmaniosios sutarties funkcija sukuria prieigos raktą ir sugeneruoja apie jį įvykį.

2. „Plasma Cash“ mazgai, užsiprenumeravę išmaniųjų sutarties įvykius, gauna įvykį apie indėlio sukūrimą ir prideda operaciją apie prieigos rakto sukūrimą į fondą.

3. Periodiškai specialūs Plasma Cash mazgai paima visas operacijas iš fondo (iki 1 mln.) ir sudaro iš jų bloką, apskaičiuoja Merkle medį ir atitinkamai maišą. Šis blokas siunčiamas į kitus mazgus patikrinti. Mazgai patikrina, ar Merkle maiša galioja ir ar galioja operacijos (pavyzdžiui, ar tokeno siuntėjas yra jo savininkas). Patikrinęs bloką, mazgas iškviečia išmaniosios sutarties funkciją „submitBlock“, kuri išsaugo bloko numerį ir Merkle maišą krašto grandinėje. Išmanioji sutartis generuoja įvykį, rodantį sėkmingą bloko pridėjimą. Sandoriai pašalinami iš fondo.

4. Mazgai, kurie gauna bloko pateikimo įvykį, pradeda taikyti operacijas, kurios buvo įtrauktos į bloką.

5. Tam tikru momentu žetono savininkas (arba ne savininkas) nori atsiimti jį iš „Plasma Cash“. Norėdami tai padaryti, jis iškviečia funkciją `startExit`, perduodamas į ją informaciją apie paskutines 2 operacijas su žetonu, kurios patvirtina, kad jis yra žetono savininkas. Išmanioji sutartis, naudodama „Merkle“ maišą, patikrina, ar blokuose yra operacijų, ir išsiunčia žetoną atšaukimui, kuris įvyks po dviejų savaičių.

6. Jei žetono išėmimo operacija įvyko su pažeidimais (žetonas buvo išleistas pradėjus išėmimo procedūrą arba prieš išimant žetoną jau buvo kieno nors kito), žetono savininkas per dvi savaites gali paneigti atėmimą.

Viešasis testas: Ethereum privatumo ir mastelio sprendimas

Privatumas pasiekiamas dviem būdais

1. Šakninė grandinė nieko nežino apie operacijas, kurios generuojamos ir persiunčiamos antrinėje grandinėje. Informacija apie tai, kas įnešė ir išėmė ETH iš „Plasma Cash“, lieka vieša.

2. Antrinė grandinė leidžia atlikti anoniminius sandorius naudojant zk-SNARK.

Technologijų krūva

  • NodeJS
  • Redis
  • Eteris
  • Dirvožemis

Bandymai

Kurdami Plasma Cash išbandėme sistemos greitį ir gavome šiuos rezultatus:

  • į baseiną įtraukiama iki 35 000 operacijų per sekundę;
  • bloke gali būti saugoma iki 1 000 000 operacijų.

Bandymai buvo atlikti šiuose 3 serveriuose:

1. Intel Core i7-6700 Quad-Core Skylake su įsk. NVMe SSD – 512 GB, 64 GB DDR4 RAM
Buvo iškelti 3 patvirtinantys Plasma Cash mazgai.

2. AMD Ryzen 7 1700X aštuonių branduolių „Summit Ridge“ (Zen), SATA SSD – 500 GB, 64 GB DDR4 RAM
Buvo pakeltas Ropsten testnet ETH mazgas.
Buvo iškelti 3 patvirtinantys Plasma Cash mazgai.

3. „Intel Core i9-9900K Octa-Core“ įsk. NVMe SSD – 1 TB, 64 GB DDR4 RAM
Pakeltas 1 Plasma Cash pateikimo mazgas.
Buvo iškelti 3 patvirtinantys Plasma Cash mazgai.
Buvo pradėtas bandymas įtraukti operacijas į „Plasma Cash“ tinklą.

Iš viso: 10 Plasma Cash mazgų privačiame tinkle.

1 testas

Viename bloke yra 1 milijono operacijų limitas. Todėl 1 mln. operacijų patenka į 2 blokus (nes sistema sugeba paimti dalį operacijų ir pateikti, kol jos siunčiamos).


Pradinė būsena: paskutinis blokas #7; Duomenų bazėje saugoma 1 milijonas operacijų ir žetonų.

00:00 — operacijų generavimo scenarijaus pradžia
01:37 – buvo sukurtas 1 milijonas operacijų ir pradėtas siuntimas į mazgą
01:46 — pateikimo mazgas paėmė 240 8 operacijų iš telkinio ir formavo 320 bloką. Taip pat matome, kad per 10 sekundžių į fondą įtraukiama XNUMX XNUMX operacijų
01:58 — 8 blokas pasirašomas ir siunčiamas patvirtinti
02:03 — 8 blokas patvirtinamas ir išmaniosios sutarties funkcija „submitBlock“ iškviečiama su Merkle maiša ir bloko numeriu
02:10 — baigtas veikti demonstracinis scenarijus, kuris išsiuntė 1 milijoną operacijų per 32 sekundes
02:33 - mazgai pradėjo gauti informaciją, kad blokas #8 buvo įtrauktas į šakninę grandinę, ir pradėjo atlikti 240 XNUMX operacijų
02:40 – 240 8 operacijų buvo pašalinta iš telkinio, kurie jau yra XNUMX bloke
02:56 — pateikimo mazgas paėmė likusius 760 9 operacijų iš fondo ir pradėjo skaičiuoti Merkle maišą bei pasirašymo bloką Nr.
03:20 – visuose mazguose yra 1 milijonas 240 XNUMX operacijų ir žetonų
03:35 — blokas #9 pasirašomas ir siunčiamas patvirtinti į kitus mazgus
03:41 – įvyko tinklo klaida
04:40 — baigėsi 9 bloko patvirtinimo laukimo laikas
04:54 — pateikimo mazgas paėmė likusius 760 9 operacijų iš fondo ir pradėjo skaičiuoti Merkle maišą bei pasirašymo bloką Nr.
05:32 — blokas #9 pasirašomas ir siunčiamas patvirtinti į kitus mazgus
05:53 — blokas #9 patvirtinamas ir siunčiamas į šakninę grandinę
06:17 - mazgai pradėjo gauti informaciją, kad blokas #9 buvo įtrauktas į šakninę grandinę ir pradėjo atlikti 760 tūkst.
06:47 — telkinys pašalintas iš operacijų, kurios yra 9 bloke
09:06 – visuose mazguose yra 2 milijonai operacijų ir žetonų

2 testas

Viename bloke yra 350 tūkst. Dėl to turime 3 blokus.


Pradinė būsena: paskutinis blokas #9; Duomenų bazėje saugoma 2 milijonai operacijų ir žetonų

00:00 — operacijų generavimo scenarijus jau paleistas
00:44 – buvo sukurtas 1 milijonas operacijų ir pradėtas siuntimas į mazgą
00:56 — pateikimo mazgas paėmė 320 10 operacijų iš telkinio ir formavo 320 bloką. Taip pat matome, kad per 10 sekundžių į fondą įtraukiama XNUMX XNUMX operacijų
01:12 — blokas #10 pasirašomas ir siunčiamas į kitus mazgus patvirtinti
01:18 — baigtas veikti demonstracinis scenarijus, kuris išsiuntė 1 milijoną operacijų per 34 sekundes
01:20 — blokas #10 patvirtinamas ir siunčiamas į šakninę grandinę
01:51 - visi mazgai gavo informaciją iš šakninės grandinės, kad buvo pridėtas blokas #10 ir pradeda taikyti 320 XNUMX operacijų
02:01 – telkinys pašalintas 320 10 operacijų, kurios buvo įtrauktos į bloką Nr. XNUMX
02:15 — pateikimo mazgas paėmė 350 11 operacijų iš telkinio ir formų blokas Nr. XNUMX
02:34 — blokas #11 pasirašomas ir siunčiamas į kitus mazgus patvirtinti
02:51 — blokas #11 patvirtinamas ir siunčiamas į šakninę grandinę
02:55 — paskutinis mazgas užbaigė operacijas iš bloko #10
10:59 — operacija su bloko Nr. 9 pateikimu užtruko labai ilgai šakninėje grandinėje, tačiau ji buvo baigta ir visi mazgai gavo informaciją apie tai ir pradėjo vykdyti 350 tūkst.
11:05 – telkinys pašalintas 320 11 operacijų, kurios buvo įtrauktos į bloką Nr. XNUMX
12:10 – visuose mazguose yra 1 milijonas 670 XNUMX operacijų ir žetonų
12:17 — pateikimo mazgas paėmė 330 12 operacijų iš telkinio ir formų blokas Nr. XNUMX
12:32 — blokas #12 pasirašomas ir siunčiamas į kitus mazgus patvirtinti
12:39 — blokas #12 patvirtinamas ir siunčiamas į šakninę grandinę
13:44 - visi mazgai gavo informaciją iš šakninės grandinės, kad buvo pridėtas blokas #12 ir pradeda taikyti 330 XNUMX operacijų
14:50 – visuose mazguose yra 2 milijonai operacijų ir žetonų

3 testas

Pirmajame ir antrajame serveriuose vienas patvirtinantis mazgas buvo pakeistas pateikiančiu mazgu.


Pradinė būsena: paskutinis blokas #84; 0 operacijų ir žetonų išsaugota duomenų bazėje

00:00 — paleisti 3 scenarijai, kurie generuoja ir siunčia po 1 mln. operacijų
01:38 — buvo sukurta 1 milijonas operacijų ir pradėtas siuntimas pateikti mazgą Nr. 3
01:50 — pateikimo mazgas #3 paėmė 330 85 operacijų iš telkinio ir formavo 21 bloką (f350). Taip pat matome, kad per 10 sekundžių į fondą įtraukiama XNUMX XNUMX operacijų
01:53 — buvo sukurta 1 milijonas operacijų ir pradėtas siuntimas pateikti mazgą Nr. 1
01:50 — pateikimo mazgas #3 paėmė 330 85 operacijų iš telkinio ir formavo 21 bloką (f350). Taip pat matome, kad per 10 sekundžių į fondą įtraukiama XNUMX XNUMX operacijų
02:01 — pateikimo mazgas #1 paėmė 250 85 operacijų iš telkinio ir formavo 65 bloką (XNUMXe)
02:06 — blokas #85 (f21) pasirašomas ir siunčiamas į kitus mazgus patvirtinti
02:08 — 3 serverio demonstracinis scenarijus, kuris išsiuntė 1 milijoną operacijų per 30 sekundžių, baigė veikti
02:14 — blokas #85 (f21) patvirtinamas ir siunčiamas į šakninę grandinę
02:19 — blokas #85 (65e) pasirašomas ir siunčiamas į kitus mazgus patvirtinti
02:22 — buvo sukurta 1 milijonas operacijų ir pradėtas siuntimas pateikti mazgą Nr. 2
02:27 — blokas #85 (65e) patvirtintas ir išsiųstas į šakninę grandinę
02:29 — pateikti mazgas #2 paėmė 111855 operacijas iš telkinio ir formų bloko Nr. 85 (256).
02:36 — blokas #85 (256) pasirašomas ir siunčiamas į kitus mazgus patvirtinti
02:36 — 1 serverio demonstracinis scenarijus, kuris išsiuntė 1 milijoną operacijų per 42.5 sekundžių, baigė veikti
02:38 — blokas #85 (256) patvirtinamas ir siunčiamas į šakninę grandinę
03:08 — baigtas veikti serverio Nr. 2 scenarijus, kuris išsiuntė 1 mln. operacijų per 47 sekundes
03:38 - visi mazgai gavo informaciją iš šakninės grandinės, kad buvo pridėti blokai #85 (f21), #86(65e), #87(256) ir pradėjo taikyti 330k, 250k, 111855 operacijas.
03:49 - telkinys buvo išvalytas 330 250, 111855 85, 21 86 operacijų, kurios buvo įtrauktos į blokus #65 (f87), #256(XNUMXe), #XNUMX(XNUMX)
03:59 — pateikti mazgas #1 paėmė 888145 88 operacijas iš telkinio ir formų bloko Nr. 214 (2), pateikti mazgas #750 paėmė 88 50 operacijų iš telkinio ir formų bloko Nr. 3 (670a), pateikti mazgas # 88 paėmė 3 XNUMX operacijų iš baseinas ir formų blokas Nr. XNUMX (dXNUMXb)
04:44 — blokas #88 (d3b) pasirašomas ir siunčiamas į kitus mazgus patvirtinti
04:58 — blokas #88 (214) pasirašomas ir siunčiamas į kitus mazgus patvirtinti
05:11 — blokas #88 (50a) pasirašomas ir siunčiamas į kitus mazgus patvirtinti
05:11 — blokas #85 (d3b) patvirtinamas ir siunčiamas į šakninę grandinę
05:36 — blokas #85 (214) patvirtinamas ir siunčiamas į šakninę grandinę
05:43 - visi mazgai gavo informaciją iš šakninės grandinės, kad blokai #88 (d3b), #89(214) buvo pridėti ir pradeda taikyti 670k, 750k operacijas
06:50 — dėl ryšio gedimo blokas #85 (50a) nebuvo patvirtintas
06:55 — pateikimo mazgas #2 paėmė 888145 operacijas iš telkinio ir formų bloko Nr. 90 (50a)
08:14 — blokas #90 (50a) pasirašomas ir siunčiamas į kitus mazgus patvirtinti
09:04 — blokas #90 (50a) patvirtinamas ir siunčiamas į šakninę grandinę
11:23 - visi mazgai gavo informaciją iš šakninės grandinės, kad buvo pridėtas blokas #90 (50a), ir pradeda taikyti 888145 operacijas. Tuo pačiu metu serveris #3 jau pritaikė operacijas iš blokų #88 (d3b), #89(214)
12:11 – visi baseinai tušti
13:41 — visuose 3 serverio mazguose yra 3 milijonai operacijų ir žetonų
14:35 — visuose 1 serverio mazguose yra 3 milijonai operacijų ir žetonų
19:24 — visuose 2 serverio mazguose yra 3 milijonai operacijų ir žetonų

Kliūtys

Kurdami Plasma Cash susidūrėme su šiomis problemomis, kurias palaipsniui sprendėme ir sprendžiame:

1. Įvairių sistemos funkcijų sąveikos konfliktas. Pavyzdžiui, operacijų įtraukimo į fondą funkcija blokavo blokų pateikimo ir patvirtinimo darbą, ir atvirkščiai, todėl sumažėjo greitis.

2. Nebuvo iš karto aišku, kaip išsiųsti daugybę operacijų, sumažinant duomenų perdavimo išlaidas.

3. Nebuvo aišku, kaip ir kur saugoti duomenis, kad būtų pasiekti aukšti rezultatai.

4. Nebuvo aišku, kaip organizuoti tinklą tarp mazgų, nes bloko su 1 milijonu operacijų dydis užima apie 100 MB.

5. Darbas vienos gijos režimu nutraukia ryšį tarp mazgų, kai atliekami ilgi skaičiavimai (pavyzdžiui, statant Merkle medį ir apskaičiuojant jo maišą).

Kaip mes su visa tai susidorojome?

Pirmoji „Plasma Cash“ mazgo versija buvo savotiškas kombainas, galintis daryti viską vienu metu: priimti sandorius, pateikti ir patvirtinti blokus bei suteikti API prieigai prie duomenų. Kadangi NodeJS iš esmės yra vienos gijos, sunki Merkle medžio skaičiavimo funkcija užblokavo operacijos pridėjimo funkciją. Matėme dvi šios problemos sprendimo galimybes:

1. Paleiskite kelis NodeJS procesus, kurių kiekvienas atlieka tam tikras funkcijas.

2. Naudokite worker_threads ir perkelkite dalies kodo vykdymą į gijas.

Dėl to vienu metu naudojome abi parinktis: logiškai padalijome vieną mazgą į 3 dalis, kurios gali veikti atskirai, bet tuo pačiu sinchroniškai.

1. Pateikimo mazgas, kuris priima operacijas į telkinį ir sukuria blokus.

2. Patvirtinantis mazgas, kuris tikrina mazgų galiojimą.

3. API mazgas – suteikia API prieigai prie duomenų.

Tokiu atveju galite prisijungti prie kiekvieno mazgo per unix lizdą naudodami cli.

Sunkias operacijas, tokias kaip Merklės medžio apskaičiavimas, perkėlėme į atskirą giją.

Taip pasiekėme normalų visų Plasma Cash funkcijų veikimą vienu metu ir be gedimų.

Kai sistema pradėjo veikti, pradėjome testuoti greitį ir, deja, gavome nepatenkinamus rezultatus: 5 operacijų per sekundę ir iki 000 50 operacijų bloke. Turėjau išsiaiškinti, kas buvo įgyvendinta neteisingai.

Pirmiausia pradėjome bandyti ryšio su Plasma Cash mechanizmą, kad išsiaiškintume didžiausią sistemos pajėgumą. Anksčiau rašėme, kad „Plasma Cash“ mazgas suteikia „Unix“ lizdo sąsają. Iš pradžių jis buvo pagrįstas tekstu. json objektai buvo išsiųsti naudojant „JSON.parse()“ ir „JSON.stringify()“.

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

Išmatavome tokių objektų perdavimo greitį ir radome ~ 130k per sekundę. Bandėme pakeisti standartines darbo su json funkcijas, tačiau našumas nepagerėjo. V8 variklis turi būti gerai optimizuotas šioms operacijoms.

Mes dirbome su sandoriais, žetonais ir blokais per klases. Kuriant tokias klases našumas sumažėjo 2 kartus, kas rodo, kad OOP mums netinka. Turėjau viską perrašyti į grynai funkcinį požiūrį.

Įrašymas į duomenų bazę

Iš pradžių Redis buvo pasirinktas duomenų saugojimui kaip vienas produktyviausių sprendimų, atitinkančių mūsų reikalavimus: raktų-reikšmių saugojimas, darbas su maišos lentelėmis, rinkiniais. Paleidome pakartotinį etaloną ir gavome ~80 1 operacijų per sekundę XNUMX konvejeriu režimu.

Siekdami didelio našumo, „Redis“ sureguliavome tiksliau:

  • Užmegztas unix lizdo ryšys.
  • Išjungėme būsenos išsaugojimą diske (patikimumo dėlei galite nustatyti kopiją ir įrašyti į diską atskirame Redis).

Redis baseinas yra maišos lentelė, nes turime turėti galimybę gauti visas operacijas vienoje užklausoje ir ištrinti operacijas po vieną. Bandėme naudoti įprastą sąrašą, bet iškraunant visą sąrašą jis veikia lėčiau.

Naudojant standartinį NodeJS, Redis bibliotekos pasiekė 18 9 operacijų per sekundę našumą. Greitis sumažėjo XNUMX kartus.

Kadangi etalonas mums parodė, kad galimybės buvo aiškiai 5 kartus didesnės, pradėjome optimizuoti. Pakeitėme biblioteką į ioredis ir gavome 25 32 našumą per sekundę. Operacijas įtraukėme po vieną naudodami komandą „hset“. Taigi „Redis“ generavome daug užklausų. Kilo idėja sujungti operacijas į paketus ir išsiųsti jas viena komanda `hmset`. Rezultatas yra XNUMX tūkst. per sekundę.

Dėl kelių priežasčių, kurias apibūdinsime toliau, dirbame su duomenimis naudodami „Buferį“ ir, kaip paaiškėja, jei prieš rašydami konvertuosite juos į tekstą („buffer.toString('hex')“), galėsite gauti papildomų spektaklis. Taip greitis buvo padidintas iki 35k per sekundę. Šiuo metu nusprendėme sustabdyti tolesnį optimizavimą.

Turėjome pereiti prie dvejetainio protokolo, nes:

1. Sistema dažnai apskaičiuoja maišą, parašus ir pan., todėl jai reikia duomenų buferyje.

2. Kai siunčiami tarp paslaugų, dvejetainiai duomenys sveria mažiau nei tekstas. Pavyzdžiui, siunčiant bloką su 1 milijonu operacijų, duomenys tekste gali užimti daugiau nei 300 megabaitų.

3. Nuolat keičiami duomenys turi įtakos našumui.

Todėl mes naudojome savo dvejetainį duomenų saugojimo ir perdavimo protokolą, sukurtą nuostabios „dvejetainių duomenų“ bibliotekos pagrindu.

Dėl to gavome tokias duomenų struktūras:

— Sandoris

  ```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,
  }
  ```

– Žetonas

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

– Blokuoti

  ```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,
  }
  ```

Įprastomis komandomis „BD.encode(block, Protocol).slice();“ ir „BD.decode(buffer, Protocol)“ konvertuojame duomenis į „Buferį“, kad būtų galima išsaugoti „Redis“ arba persiųsti į kitą mazgą ir nuskaityti duomenis atgal.

Taip pat turime 2 dvejetainius protokolus duomenų perdavimui tarp paslaugų:

— Sąveikos su plazminiu mazgu per unix lizdą protokolas

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

, jeigu:

  • „tipas“ — veiksmas, kurį reikia atlikti, pavyzdžiui, 1 — sendTransaction, 2 — getTransaction;
  • "naudingoji apkrova". — duomenys, kuriuos reikia perduoti atitinkamai funkcijai;
  • 'messageId' — pranešimo ID, kad būtų galima atpažinti atsakymą.

— Sąveikos tarp mazgų protokolas

  ```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)
  }
  ```

, jeigu:

  • "kodas". — pranešimo kodas, pavyzdžiui, 6 — PREPARE_NEW_BLOCK, 7 — BLOCK_VALID, 8 — BLOCK_COMMIT;
  • „versijos protokolas“. — protokolo versija, nes tinkle gali būti keliami skirtingų versijų mazgai ir jie gali veikti skirtingai;
  • `seq` — pranešimo identifikatorius;
  • `countChunk` и 'chunkNumber' būtina skaidant didelius pranešimus;
  • "ilgis". и "naudingoji apkrova". ilgis ir patys duomenys.

Kadangi duomenis įvedėme iš anksto, galutinė sistema yra daug greitesnė nei Ethereum „rlp“ biblioteka. Deja, kol kas negalime jos atsisakyti, nes būtina užbaigti išmaniąją sutartį, kurią planuojame padaryti ateityje.

Jeigu mums pavyktų pasiekti greitį 35 000 operacijų per sekundę, taip pat turime juos apdoroti optimaliu laiku. Kadangi apytikslis bloko formavimo laikas trunka 30 sekundžių, turime įtraukti į bloką 1 000 000 operacijų, o tai reiškia siųsti daugiau 100 MB duomenų.

Iš pradžių naudojome biblioteką „ethereumjs-devp2p“, kad bendrautume tarp mazgų, tačiau ji negalėjo apdoroti tiek daug duomenų. Dėl to mes panaudojome „ws“ biblioteką ir sukonfigūravome dvejetainių duomenų siuntimą per žiniatinklio lizdą. Žinoma, susidūrėme ir su problemomis siųsdami didelius duomenų paketus, tačiau suskirstėme juos į dalis ir dabar šių problemų nebėra.

Taip pat Merkle medžio formavimas ir maišos apskaičiavimas 1 000 000 sandoriams reikia apie 10 sekundžių nepertraukiamo skaičiavimo. Per šį laiką ryšys su visais mazgais spėja nutrūkti. Šį skaičiavimą buvo nuspręsta perkelti į atskirą giją.

Išvados:

Tiesą sakant, mūsų išvados nėra naujos, tačiau dėl tam tikrų priežasčių daugelis ekspertų juos pamiršta kurdami.

  • Funkcinio programavimo naudojimas vietoj objektinio programavimo pagerina produktyvumą.
  • Monolitas yra blogesnis nei produktyvios NodeJS sistemos paslaugų architektūra.
  • „worker_threads“ naudojimas sunkiam skaičiavimui pagerina sistemos reagavimą, ypač kai atliekamos įvesties/išvesties operacijos.
  • unix lizdas yra stabilesnis ir greitesnis nei http užklausos.
  • Jei reikia greitai perduoti didelius duomenis per tinklą, geriau naudoti žiniatinklio lizdus ir siųsti dvejetainius duomenis, suskirstytus į gabalus, kuriuos galima persiųsti, jei jie neateina, o tada sujungti į vieną pranešimą.

Kviečiame apsilankyti GitHub projektas: https://github.com/opporty-com/Plasma-Cash/tree/new-version

Straipsnį parašė kartu Aleksandras Našivanas, vyresnysis kūrėjas „Clever Solution Inc.

Šaltinis: www.habr.com

Добавить комментарий