Julkinen testi: Ratkaisu yksityisyyteen ja skaalautumiseen Ethereumissa

Blokcheyn on innovatiivinen tekniikka, joka lupaa parantaa monia ihmisen elämän alueita. Se siirtää todellisia prosesseja ja tuotteita digitaaliseen tilaan, varmistaa rahoitustapahtumien nopeuden ja luotettavuuden, alentaa niiden kustannuksia ja mahdollistaa myös nykyaikaisten DAPP-sovellusten luomisen älykkäillä sopimuksilla hajautetuissa verkoissa.

Ottaen huomioon lohkoketjun monet edut ja monipuoliset sovellukset, voi tuntua yllättävältä, että tämä lupaava teknologia ei ole vielä päässyt kaikille toimialalle. Ongelmana on, että nykyaikaisista hajautetuista lohkoketjuista puuttuu skaalautuvuus. Ethereum käsittelee noin 20 tapahtumaa sekunnissa, mikä ei riitä vastaamaan nykypäivän dynaamisten yritysten tarpeita. Samaan aikaan lohkoketjuteknologiaa käyttävät yritykset epäröivät luopua Ethereumista sen korkean suojan hakkerointia ja verkkovikoja vastaan.

Varmistaakseen hajautuksen, turvallisuuden ja skaalautuvuuden lohkoketjussa, mikä ratkaisee Scalability Trilemman, kehitystiimi Mahdollista loi Plasma Cash, tytäryhtiöketju, joka koostuu älysopimuksesta ja yksityisestä Node.js-pohjaisesta verkosta, joka siirtää tilansa ajoittain juuriketjuun (Ethereum).

Julkinen testi: Ratkaisu yksityisyyteen ja skaalautumiseen Ethereumissa

Keskeiset prosessit Plasma Cashissa

1. Käyttäjä kutsuu älykästä sopimustoimintoa "talletus" ja siirtää siihen ETH-määrän, jonka hän haluaa tallettaa Plasma Cash -tokeniin. Älykäs sopimustoiminto luo tunnuksen ja luo siitä tapahtuman.

2. Älykkäisiin sopimustapahtumiin tilatut Plasma Cash -solmut vastaanottavat tapahtuman talletuksen luomisesta ja lisäävät tapahtuman tunnuksen luomisesta pooliin.

3. Ajoittain erityiset Plasma Cash -solmut ottavat kaikki tapahtumat poolista (jopa 1 miljoonaa) ja muodostavat niistä lohkon, laskevat Merkle-puun ja vastaavasti hashin. Tämä lohko lähetetään muille solmuille tarkistettavaksi. Solmut tarkistavat, onko Merkle-hash kelvollinen ja ovatko tapahtumat kelvollisia (esimerkiksi onko tunnuksen lähettäjä sen omistaja). Lohkon vahvistamisen jälkeen solmu kutsuu älysopimuksen `submitBlock`-funktiota, joka tallentaa lohkonumeron ja Merkle-hajasteen reunaketjuun. Älykäs sopimus luo tapahtuman, joka ilmaisee lohkon onnistuneen lisäyksen. Tapahtumat poistetaan poolista.

4. Solmut, jotka vastaanottavat lohkon lähetystapahtuman, alkavat soveltaa lohkoon lisättyjä tapahtumia.

5. Jossain vaiheessa tunnuksen omistaja (tai ei-omistaja) haluaa nostaa sen Plasma Cashista. Tätä varten hän kutsuu `startExit`-funktiota ja välittää siihen tiedot tunnuksen kahdesta viimeisestä tapahtumasta, jotka vahvistavat, että hän on tunnuksen omistaja. Älykäs sopimus käyttää Merkle-hashia, joka tarkistaa tapahtumien olemassaolon lohkoissa ja lähettää tokenin nostettavaksi, joka tapahtuu kahden viikon kuluttua.

6. Jos tunnuksen nostotoiminto tapahtui rikkomuksella (token on käytetty nostoprosessin alkamisen jälkeen tai se oli jo jonkun muun hallussa ennen nostoa), tunnuksen omistaja voi kumota noston kahden viikon kuluessa.

Julkinen testi: Ratkaisu yksityisyyteen ja skaalautumiseen Ethereumissa

Yksityisyys saavutetaan kahdella tavalla

1. Juuriketju ei tiedä mitään tapahtumista, jotka luodaan ja välitetään aliketjussa. Tiedot siitä, kuka talletti ja nosti ETH:n Plasma Cashista, pysyy julkisena.

2. Aliketju sallii anonyymit tapahtumat zk-SNARK:ien avulla.

Teknologiapino

  • NodeJS
  • Redis
  • Etherium
  • soild

Testaus

Plasma Cashia kehitettäessä testasimme järjestelmän nopeutta ja saimme seuraavat tulokset:

  • pooliin lisätään jopa 35 000 tapahtumaa sekunnissa;
  • lohkoon voidaan tallentaa jopa 1 000 000 tapahtumaa.

Testit suoritettiin seuraavilla kolmella palvelimella:

1. Intel Core i7-6700 Quad-Core Skylake sis. NVMe SSD - 512 Gt, 64 Gt DDR4 RAM-muistia
3 validoivaa Plasma Cash -solmua nostettiin.

2. AMD Ryzen 7 1700X Octa-Core "Summit Ridge" (Zen), SATA SSD – 500 Gt, 64 Gt DDR4 RAM
Ropsten testnet ETH -solmu nostettiin.
3 validoivaa Plasma Cash -solmua nostettiin.

3. Intel Core i9-9900K kahdeksanytiminen sis. NVMe SSD - 1 Tt, 64 Gt DDR4 RAM-muistia
1 Plasma Cash -lähetyssolmu nostettiin.
3 validoivaa Plasma Cash -solmua nostettiin.
Käynnistettiin testi tapahtumien lisäämiseksi Plasma Cash -verkostoon.

Yhteensä: 10 Plasma Cash -solmua yksityisessä verkossa.

Testi 1

Rajoitus on miljoona tapahtumaa lohkoa kohden. Siksi miljoona tapahtumaa jakautuu 1 lohkoon (koska järjestelmä onnistuu ottamaan osan tapahtumista ja lähettämään niitä lähetyksen aikana).


Alkutila: viimeinen lohko #7; Tietokantaan on tallennettu miljoona tapahtumaa ja tokenia.

00:00 — tapahtuman luomisskriptin alku
01:37 - 1 miljoona tapahtumaa luotiin ja lähetys solmuun aloitettiin
01:46 — lähetyssolmu otti 240 8 tapahtumaa poolista ja lomakkeet lohko #320. Näemme myös, että 10 XNUMX tapahtumaa lisätään pooliin XNUMX sekunnissa
01:58 — lohko #8 allekirjoitetaan ja lähetetään tarkistettavaksi
02:03 — lohko #8 vahvistetaan ja älysopimuksen submitBlock-toiminto kutsutaan Merkle-hajautus- ja lohkonumerolla
02:10 — esittelyskripti valmistui, ja se lähetti miljoona tapahtumaa 1 sekunnissa
02:33 - solmut alkoivat vastaanottaa tietoa, että lohko #8 lisättiin juuriketjuun, ja alkoivat suorittaa 240 XNUMX tapahtumaa
02:40 - 240 8 tapahtumaa poistettiin poolista, jotka ovat jo lohkossa #XNUMX
02:56 — lähetyssolmu otti loput 760 9 tapahtumaa poolista ja alkoi laskea Merkle-tiivistettä ja allekirjoituslohkoa #XNUMX
03:20 - kaikki solmut sisältävät miljoona 1 240 tapahtumaa ja tokenia
03:35 — lohko #9 allekirjoitetaan ja lähetetään tarkistettavaksi muille solmuille
03:41 - verkkovirhe
04:40 — lohkon #9 vahvistuksen odottaminen aikakatkaistiin
04:54 — lähetyssolmu otti loput 760 9 tapahtumaa poolista ja alkoi laskea Merkle-tiivistettä ja allekirjoituslohkoa #XNUMX
05:32 — lohko #9 allekirjoitetaan ja lähetetään tarkistettavaksi muille solmuille
05:53 — lohko #9 vahvistetaan ja lähetetään juuriketjuun
06:17 - solmut alkoivat saada tietoa, että lohko #9 lisättiin juuriketjuun ja alkoivat suorittaa 760 XNUMX tapahtumaa
06:47 — pooli on tyhjennetty tapahtumat, jotka ovat lohkossa #9
09:06 - kaikki solmut sisältävät 2 miljoonaa tapahtumaa ja tokenia

Testi 2

Raja on 350 3 per lohko. Tämän seurauksena meillä on XNUMX lohkoa.


Alkutila: viimeinen lohko #9; Tietokantaan on tallennettu 2 miljoonaa tapahtumaa ja tokenia

00:00 — tapahtuman luomisskripti on jo käynnistetty
00:44 - 1 miljoona tapahtumaa luotiin ja lähetys solmuun aloitettiin
00:56 — lähetyssolmu otti 320 10 tapahtumaa poolista ja lomakkeet lohko #320. Näemme myös, että 10 XNUMX tapahtumaa lisätään pooliin XNUMX sekunnissa
01:12 — lohko #10 allekirjoitetaan ja lähetetään muille solmuille tarkistettavaksi
01:18 — esittelyskripti valmistui, ja se lähetti miljoona tapahtumaa 1 sekunnissa
01:20 — lohko #10 vahvistetaan ja lähetetään juuriketjuun
01:51 - kaikki solmut saivat juuriketjulta tiedon, että lohko #10 lisättiin ja alkavat käyttää 320 XNUMX tapahtumaa
02:01 - pooli on tyhjennetty 320 10 tapahtumalle, jotka lisättiin lohkoon #XNUMX
02:15 — lähetyssolmu otti 350 11 tapahtumaa poolista ja lomakelohko #XNUMX
02:34 — lohko #11 allekirjoitetaan ja lähetetään muille solmuille tarkistettavaksi
02:51 — lohko #11 vahvistetaan ja lähetetään juuriketjuun
02:55 — viimeinen solmu suoritti tapahtumat lohkosta #10
10:59 — tapahtuma lohkon #9 lähettämisellä kesti hyvin kauan juuriketjussa, mutta se saatiin päätökseen ja kaikki solmut saivat tiedon siitä ja alkoivat suorittaa 350 XNUMX tapahtumaa
11:05 - pooli on tyhjennetty 320 11 tapahtumalle, jotka lisättiin lohkoon #XNUMX
12:10 - kaikki solmut sisältävät miljoona 1 670 tapahtumaa ja tokenia
12:17 — lähetyssolmu otti 330 12 tapahtumaa poolista ja lomakelohko #XNUMX
12:32 — lohko #12 allekirjoitetaan ja lähetetään muille solmuille tarkistettavaksi
12:39 — lohko #12 vahvistetaan ja lähetetään juuriketjuun
13:44 - kaikki solmut saivat juuriketjulta tiedon, että lohko #12 lisättiin ja alkavat käyttää 330 XNUMX tapahtumaa
14:50 - kaikki solmut sisältävät 2 miljoonaa tapahtumaa ja tokenia

Testi 3

Ensimmäisessä ja toisessa palvelimessa yksi vahvistava solmu korvattiin lähettävällä solmulla.


Alkutila: viimeinen lohko #84; 0 tapahtumaa ja tokeneja tallennettu tietokantaan

00:00 — 3 skriptiä on käynnistetty, jotka luovat ja lähettävät kukin miljoona tapahtumaa
01:38 — 1 miljoona tapahtumaa luotiin ja lähetys lähetyssolmuun #3 aloitettiin
01:50 — lähetyssolmu #3 otti 330 85 tapahtumaa poolista ja lomakelohkon #21 (f350). Näemme myös, että 10 XNUMX tapahtumaa lisätään pooliin XNUMX sekunnissa
01:53 — 1 miljoona tapahtumaa luotiin ja lähetys lähetyssolmuun #1 aloitettiin
01:50 — lähetyssolmu #3 otti 330 85 tapahtumaa poolista ja lomakelohkon #21 (f350). Näemme myös, että 10 XNUMX tapahtumaa lisätään pooliin XNUMX sekunnissa
02:01 — lähetyssolmu #1 otti 250 85 tapahtumaa poolista ja lomakelohko #65 (XNUMXe)
02:06 — lohko #85 (f21) allekirjoitetaan ja lähetetään muille solmuille tarkistettavaksi
02:08 — palvelimen #3 demo-skripti, joka lähetti miljoona tapahtumaa 1 sekunnissa, valmistui
02:14 — lohko #85 (f21) vahvistetaan ja lähetetään juuriketjuun
02:19 — lohko #85 (65e) allekirjoitetaan ja lähetetään muille solmuille tarkistettavaksi
02:22 — 1 miljoona tapahtumaa luotiin ja lähetys lähetyssolmuun #2 aloitettiin
02:27 — lohko #85 (65e) validoitu ja lähetetty juuriketjuun
02:29 — lähetyssolmu #2 otti 111855 tapahtumaa poolista ja lomakelohkosta #85 (256).
02:36 — lohko #85 (256) allekirjoitetaan ja lähetetään muille solmuille tarkistettavaksi
02:36 — palvelimen #1 demo-skripti, joka lähetti miljoona tapahtumaa 1 sekunnissa, valmistui
02:38 — lohko #85 (256) validoidaan ja lähetetään juuriketjuun
03:08 — palvelin #2 komentosarja valmistui, joka lähetti miljoona tapahtumaa 1 sekunnissa
03:38 - kaikki solmut saivat juuriketjulta tiedon, että lohkot #85 (f21), #86(65e), #87(256) lisättiin ja alkoivat soveltaa 330k, 250k, 111855 tapahtumia
03:49 - pooli tyhjennettiin 330 tk, 250 111855, 85 21 tapahtumalla, jotka lisättiin lohkoihin #86 (f65), #87(256e), #XNUMX(XNUMX)
03:59 — lähetyssolmu #1 otti 888145 88 tapahtumaa poolista ja lomakelohko #214 (2), lähetyssolmu #750 otti 88 50 tapahtumaa poolista ja lomakelohko #3 (670a), lähetyssolmu #88 otti 3 XNUMX tapahtumaa allas ja lomakelohko #XNUMX (dXNUMXb)
04:44 — lohko #88 (d3b) allekirjoitetaan ja lähetetään muille solmuille tarkistettavaksi
04:58 — lohko #88 (214) allekirjoitetaan ja lähetetään muille solmuille tarkistettavaksi
05:11 — lohko #88 (50a) allekirjoitetaan ja lähetetään muille solmuille tarkistettavaksi
05:11 — lohko #85 (d3b) validoidaan ja lähetetään juuriketjuun
05:36 — lohko #85 (214) validoidaan ja lähetetään juuriketjuun
05:43 - kaikki solmut saivat juuriketjulta tiedon, että lohkot #88 (d3b), #89(214) on lisätty ja alkavat käyttää 670k, 750k tapahtumia
06:50 — tietoliikennehäiriön vuoksi lohkoa #85 (50a) ei vahvistettu
06:55 — lähetyssolmu #2 otti 888145 tapahtumaa poolista ja lomakelohko #90 (50a)
08:14 — lohko #90 (50a) allekirjoitetaan ja lähetetään muille solmuille tarkistettavaksi
09:04 — lohko #90 (50a) validoidaan ja lähetetään juuriketjuun
11:23 - kaikki solmut saivat juuriketjulta tiedon, että lohko #90 (50a) lisättiin, ja alkavat soveltaa 888145-tapahtumia. Samaan aikaan palvelin #3 on jo soveltanut tapahtumia lohkoista #88 (d3b), #89(214)
12:11 - kaikki altaat ovat tyhjiä
13:41 — kaikki palvelimen #3 solmut sisältävät 3 miljoonaa tapahtumaa ja tokenia
14:35 — kaikki palvelimen #1 solmut sisältävät 3 miljoonaa tapahtumaa ja tokenia
19:24 — kaikki palvelimen #2 solmut sisältävät 3 miljoonaa tapahtumaa ja tokenia

Esteet

Plasma Cashin kehittämisen aikana törmäsimme seuraaviin ongelmiin, joita ratkaisimme asteittain ja olemme ratkaisemassa:

1. Ristiriita järjestelmän eri toimintojen vuorovaikutuksessa. Esimerkiksi toiminto tapahtumien lisäämiseksi pooliin esti lohkojen lähettämisen ja vahvistamisen ja päinvastoin, mikä johti nopeuden laskuun.

2. Ei ollut heti selvää, kuinka suuri määrä tapahtumia lähetetään samalla kun tiedonsiirtokustannukset minimoidaan.

3. Ei ollut selvää, miten ja minne tietoja säilytetään korkeiden tulosten saavuttamiseksi.

4. Ei ollut selvää, miten solmujen välinen verkko järjestetään, koska miljoonan tapahtuman lohkon koko vie noin 1 MB.

5. Yksisäikeisessä tilassa työskentely katkaisee solmujen välisen yhteyden pitkien laskutoimitusten yhteydessä (esimerkiksi Merkle-puun rakentaminen ja sen hashin laskeminen).

Miten me selvisimme tämän kaiken kanssa?

Plasma Cash -solmun ensimmäinen versio oli eräänlainen yhdistelmä, joka pystyi tekemään kaiken samanaikaisesti: hyväksymään tapahtumia, lähettämään ja validoimaan lohkoja sekä tarjoamaan API:n tietojen käyttöä varten. Koska NodeJS on natiivisäikeinen, raskas Merkle-puun laskentatoiminto esti tapahtuman lisäystoiminnon. Näimme kaksi vaihtoehtoa tämän ongelman ratkaisemiseksi:

1. Käynnistä useita NodeJS-prosesseja, joista jokainen suorittaa tiettyjä toimintoja.

2. Käytä worker_threads-funktiota ja siirrä koodin osan suoritus säikeisiin.

Tämän seurauksena käytimme molempia vaihtoehtoja samanaikaisesti: jaoimme loogisesti yhden solmun 3 osaan, jotka voivat toimia erikseen, mutta samalla synkronisesti

1. Lähetyssolmu, joka hyväksyy tapahtumat pooliin ja luo lohkoja.

2. Vahvistussolmu, joka tarkistaa solmujen kelpoisuuden.

3. API-solmu – tarjoaa API:n tietojen käyttöä varten.

Tässä tapauksessa voit muodostaa yhteyden kuhunkin solmuun unix-liitännän kautta käyttämällä cli:tä.

Siirsimme raskaat toiminnot, kuten Merkle-puun laskemisen, omaan säikeeseen.

Näin olemme saaneet kaikkien Plasma Cash -toimintojen normaalin toiminnan samanaikaisesti ja ilman vikoja.

Kun järjestelmä oli toiminnassa, aloimme testata nopeutta ja valitettavasti saimme epätyydyttäviä tuloksia: 5 000 tapahtumaa sekunnissa ja jopa 50 000 tapahtumaa lohkoa kohti. Minun piti selvittää, mikä oli toteutettu väärin.

Aluksi aloimme testata Plasma Cash -kommunikaatiomekanismia saadaksemme selville järjestelmän huippukyvyn. Kirjoitimme aiemmin, että Plasma Cash -solmu tarjoaa unix-liitäntärajapinnan. Aluksi se oli tekstipohjainen. json-objektit lähetettiin JSON.parse()- ja JSON.stringify()-komennoilla.

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

Mittasimme tällaisten kohteiden siirtonopeuden ja löysimme ~ 130k sekunnissa. Yritimme korvata json-työskentelyn vakiotoiminnot, mutta suorituskyky ei parantunut. V8-moottorin on oltava hyvin optimoitu näitä toimintoja varten.

Työskentelimme tapahtumien, tokenien ja lohkojen kanssa luokkien kautta. Tällaisia ​​luokkia luotaessa suorituskyky putosi 2 kertaa, mikä osoittaa, että OOP ei sovi meille. Minun piti kirjoittaa kaikki uudelleen puhtaasti toiminnalliseen lähestymistapaan.

Tallennus tietokantaan

Alun perin Redis valittiin tietojen varastointiin yhdeksi tuottavimmista ratkaisuista, joka täyttää vaatimukset: avainarvojen tallennus, työskentely hash-taulukoiden, sarjojen kanssa. Julkaisimme uudelleendis-benchmarkin ja saimme ~80 1 operaatiota sekunnissa XNUMX liukuhihnatilassa.

Korkean suorituskyvyn takaamiseksi viritimme Redisin hienommin:

  • Unix-pistorasiayhteys on muodostettu.
  • Poistimme tilan tallennuksen levylle (luotettavuuden vuoksi voit määrittää replikan ja tallentaa levylle erillisessä Redisissä).

Redisissä pooli on hash-taulukko, koska meidän on voitava hakea kaikki tapahtumat yhdellä kyselyllä ja poistaa tapahtumat yksitellen. Yritimme käyttää tavallista listaa, mutta se on hitaampaa, kun koko listaa puretaan.

Normaalia NodeJS:ää käytettäessä Redis-kirjastot saavuttivat 18 9 tapahtumaa sekunnissa. Nopeus putosi XNUMX kertaa.

Koska benchmark osoitti meille, että mahdollisuudet olivat selvästi viisi kertaa suuremmat, aloimme optimoida. Vaihdoimme kirjaston iorediksi ja saimme suorituskyvyn 5 25 sekunnissa. Lisäsimme tapahtumat yksitellen "hset"-komennolla. Joten loimme paljon kyselyitä Redisissä. Syntyi ajatus yhdistää tapahtumat eriksi ja lähettää ne yhdellä komennolla "hmset". Tulos on 32k sekunnissa.

Useista syistä, joita kuvaamme alla, käsittelemme dataa käyttämällä "Buffer"-toimintoa, ja kuten käy ilmi, jos muunnat sen tekstiksi (`buffer.toString('hex')`) ennen kirjoittamista, voit saada lisää esitys. Näin nopeus nousi 35 kilometriin sekunnissa. Tällä hetkellä päätimme keskeyttää lisäoptimoinnin.

Meidän piti vaihtaa binääriprotokollaan, koska:

1. Järjestelmä laskee usein tiivisteitä, allekirjoituksia jne. ja tätä varten se tarvitsee dataa puskurissa.

2. Palvelujen välillä lähetettäessä binääridata painaa vähemmän kuin teksti. Esimerkiksi lähetettäessä lohko, jossa on miljoona tapahtumaa, tekstin tiedot voivat viedä yli 1 megatavua.

3. Jatkuva tietojen muuntaminen vaikuttaa suorituskykyyn.

Siksi otimme perustaksi oman binaariprotokollamme tietojen tallentamiseen ja lähettämiseen, joka on kehitetty upean "binääritietokirjaston" pohjalta.

Tuloksena saimme seuraavat tietorakenteet:

— Kauppa

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

-Lohko

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

Tavallisilla komennoilla `BD.encode(block, Protocol).slice();` ja `BD.decode(buffer, Protocol)` muunnetaan tiedot puskuriksi, joka voidaan tallentaa Redisiin tai lähettää eteenpäin toiseen solmuun ja hakea tiedot takaisin.

Meillä on myös 2 binaariprotokollaa tiedonsiirtoon palveluiden välillä:

— Protokolla vuorovaikutukseen Plasma Noden kanssa unix-liitännän kautta

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

jos:

  • `Tyyppi` — suoritettava toiminto, esimerkiksi 1 — sendTransaction, 2 — getTransaction;
  • `hyötykuorma` — tiedot, jotka on välitettävä asianmukaiselle toiminnolle;
  • `messageId' — viestin tunnus, jotta vastaus voidaan tunnistaa.

— Protokolla solmujen välistä vuorovaikutusta varten

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

jos:

  • `koodi` — viestikoodi, esimerkiksi 6 — PREPARE_NEW_BLOCK, 7 — BLOCK_VALID, 8 — BLOCK_COMMIT;
  • `versioprotokolla` — protokollaversio, koska verkkoon voidaan nostaa eri versioita omaavia solmuja ja ne voivat toimia eri tavalla;
  • `seq` — viestin tunniste;
  • `countChunk` и `chunkNumber` välttämätön suurten viestien jakamiseen;
  • "pituus". и `hyötykuorma` pituus ja itse tiedot.

Koska kirjoitimme tiedot valmiiksi, lopullinen järjestelmä on paljon nopeampi kuin Ethereumin "rlp"-kirjasto. Valitettavasti emme ole vielä voineet kieltäytyä siitä, koska älysopimus on viimeisteltävä, mitä aiomme tehdä tulevaisuudessa.

Jos onnistuisimme saavuttamaan nopeuden 35 000 liiketoimia sekunnissa, meidän on myös käsiteltävä ne optimaalisessa ajassa. Koska likimääräinen lohkon muodostusaika kestää 30 sekuntia, meidän on sisällytettävä lohkoon 1 000 000 tapahtumia, mikä tarkoittaa enemmän lähettämistä 100 MB dataa.

Aluksi käytimme `ethereumjs-devp2p`-kirjastoa kommunikointiin solmujen välillä, mutta se ei pystynyt käsittelemään niin paljon dataa. Tämän seurauksena käytimme "ws"-kirjastoa ja määritimme binääritietojen lähettämisen websocketin kautta. Tietenkin kohtasimme ongelmia myös lähetettäessä suuria datapaketteja, mutta jaoimme ne osiin ja nyt nämä ongelmat ovat poissa.

Myös Merkle-puun muodostaminen ja hashin laskeminen 1 000 000 liiketoimet edellyttävät noin 10 sekuntia jatkuvaa laskutoimitusta. Tänä aikana yhteys kaikkiin solmuihin onnistuu katkeamaan. Tämä laskelma päätettiin siirtää erilliseen säikeeseen.

Päätelmät:

Itse asiassa havaintomme eivät ole uusia, mutta jostain syystä monet asiantuntijat unohtavat ne kehittäessään.

  • Funktionaalisen ohjelmoinnin käyttäminen olio-ohjelmoinnin sijaan parantaa tuottavuutta.
  • Monoliitti on huonompi kuin palveluarkkitehtuuri tuottavalle NodeJS-järjestelmälle.
  • "worker_threads"-argumentin käyttäminen raskaaseen laskentaan parantaa järjestelmän reagointikykyä, etenkin kun käsitellään i/o-toimintoja.
  • unix socket on vakaampi ja nopeampi kuin http-pyynnöt.
  • Jos sinun on siirrettävä nopeasti suuria tietoja verkon yli, on parempi käyttää websocketteja ja lähettää binääridataa, joka on jaettu paloiksi, jotka voidaan välittää eteenpäin, jos ne eivät tule perille, ja yhdistää sitten yhdeksi viestiksi.

Kutsumme sinut käymään GitHub projekti: https://github.com/opporty-com/Plasma-Cash/tree/new-version

Artikkelin on kirjoittanut Alexander Nashivan, vanhempi kehittäjä Clever Solution Inc.

Lähde: will.com

Lisää kommentti