Қоғамдық сынақ: Ethereum-да құпиялылық пен масштабтауға арналған шешім

Блоккейн адам өмірінің көптеген салаларын жақсартуға уәде беретін инновациялық технология болып табылады. Ол нақты процестер мен өнімдерді цифрлық кеңістікке тасымалдайды, қаржылық транзакциялардың жылдамдығы мен сенімділігін қамтамасыз етеді, олардың құнын төмендетеді, сонымен қатар орталықтандырылмаған желілерде смарт келісімшарттарды пайдалана отырып, заманауи DAPP қосымшаларын жасауға мүмкіндік береді.

Блокчейннің көптеген артықшылықтары мен әртүрлі қолданбаларын ескере отырып, бұл перспективті технология әлі де барлық салаға енбегені таңқаларлық болып көрінуі мүмкін. Мәселе мынада, қазіргі орталықтандырылмаған блокчейндерде масштабтау мүмкіндігі жоқ. Ethereum секундына шамамен 20 транзакцияны өңдейді, бұл бүгінгі динамикалық бизнестің қажеттіліктерін қанағаттандыру үшін жеткіліксіз. Сонымен қатар, блокчейн технологиясын пайдаланатын компаниялар Ethereum-дан бас тартуға тартынуда, өйткені оның бұзудан және желідегі ақаулардан жоғары қорғаныс дәрежесі.

Блокчейндегі орталықсыздандыруды, қауіпсіздікті және ауқымдылықты қамтамасыз ету, осылайша масштабтау трилеммасын шешу үшін әзірлеу тобы Қолдау Plasma Cash құрылды, ақылды келісім-шарттан және Node.js негізіндегі жеке желіден тұратын еншілес тізбек, ол өз күйін мезгіл-мезгіл түбірлік тізбекке (Ethereum) тасымалдайды.

Қоғамдық сынақ: Ethereum-да құпиялылық пен масштабтауға арналған шешім

Плазмалық кассадағы негізгі процестер

1. Пайдаланушы смарт келісімшарт функциясын «депозит» деп атайды, оған Plasma Cash таңбалауышына енгізгісі келетін ETH сомасын береді. Смарт келісімшарт функциясы таңбалауышты жасайды және ол туралы оқиғаны жасайды.

2. Ақылды келісім-шарт оқиғаларына жазылған Plasma Cash түйіндері депозит жасау туралы оқиғаны алады және пулға таңбалауыш жасау туралы транзакцияны қосады.

3. Мерзімді түрде арнайы Plasma Cash түйіндері пулдан барлық транзакцияларды (1 миллионға дейін) алып, олардан блок құрайды, Merkle ағашын және сәйкесінше хэшті есептейді. Бұл блок тексеру үшін басқа түйіндерге жіберіледі. Түйіндер Merkle хэшінің жарамдылығын және транзакциялардың жарамдылығын тексереді (мысалы, токенді жіберуші оның иесі болып табыла ма). Блокты тексергеннен кейін түйін блок нөмірін және Merkle хэшін жиек тізбегіне сақтайтын смарт келісімшарттың `submitBlock` функциясын шақырады. Смарт келісімшарт блоктың сәтті қосылғанын көрсететін оқиғаны жасайды. Транзакциялар пулдан жойылады.

4. Блокты жіберу оқиғасын алатын түйіндер блокқа қосылған транзакцияларды қолдана бастайды.

5. Белгілі бір сәтте токеннің иесі (немесе иесі емес) оны Plasma Cash-тен алғысы келеді. Ол үшін ол `startExit` функциясын шақырады, оған маркердің иесі екенін растайтын токендегі соңғы 2 транзакция туралы ақпаратты береді. Merkle хэшін пайдалана отырып, смарт келісімшарт блоктардағы транзакциялардың бар-жоғын тексереді және екі аптадан кейін пайда болатын таңбалауышты алу үшін жібереді.

6. Егер токенді алу операциясы бұзушылықтармен орын алса (токен алу процедурасы басталғаннан кейін жұмсалған немесе токен шығаруға дейін басқа біреудікі болса), токен иесі екі апта ішінде алуды жоққа шығара алады.

Қоғамдық сынақ: Ethereum-да құпиялылық пен масштабтауға арналған шешім

Құпиялылыққа екі жолмен қол жеткізіледі

1. Түбірлік тізбек еншілес тізбекте жасалған және қайта жіберілетін транзакциялар туралы ештеңе білмейді. Plasma Cash-тен ETH-ді кім салғаны және алғаны туралы ақпарат ашық күйінде қалады.

2. Еншілес тізбек zk-SNARKs көмегімен анонимді транзакцияларға рұқсат береді.

Технологиялық стек

  • NodeJS
  • Редис
  • Этериум
  • Топырақ

Тестілеу

Plasma Cash әзірлеу барысында біз жүйенің жылдамдығын сынап, келесі нәтижелерге қол жеткіздік:

  • пулға секундына 35 000 транзакцияға дейін қосылады;
  • блокта 1 000 000 транзакцияға дейін сақтауға болады.

Сынақтар келесі 3 серверде жүргізілді:

1. Intel Core i7-6700 Quad-Core Skylake, соның ішінде. NVMe SSD – 512 ГБ, 64 ГБ DDR4 жедел жады
3 тексеруші Plasma Cash түйіндері көтерілді.

2. AMD Ryzen 7 1700X сегіз ядролы «Summit Ridge» (Zen), SATA SSD – 500 ГБ, 64 ГБ DDR4 жедел жады
Ropsten testnet ETH түйіні көтерілді.
3 тексеруші Plasma Cash түйіндері көтерілді.

3. Intel Core i9-9900K Octa-Core, соның ішінде. NVMe SSD – 1 ТБ, 64 ГБ DDR4 жедел жады
1 Plasma Cash жіберу түйіні көтерілді.
3 тексеруші Plasma Cash түйіндері көтерілді.
Plasma Cash желісіне транзакцияларды қосу үшін сынақ іске қосылды.

Барлығы: Жеке желідегі 10 Plasma Cash түйіндері.

Тест 1

Бір блок үшін 1 миллион транзакцияның шегі бар. Осылайша, 1 миллион транзакция 2 блокқа бөлінеді (өйткені жүйе транзакциялардың бір бөлігін қабылдайды және оларды жіберу кезінде жібереді).


Бастапқы күй: соңғы блок №7; Дерекқорда 1 миллион транзакциялар мен токендер сақталады.

00:00 — транзакцияны құру сценарийінің басталуы
01:37 - 1 миллион транзакция жасалып, түйінге жіберу басталды
01:46 — жіберу түйіні пулдан 240 мың транзакцияны қабылдады және №8 блокты қалыптастырады. Сондай-ақ 320 секундта пулға 10 мың транзакция қосылғанын көреміз
01:58 — №8 блокқа қол қойылды және валидацияға жіберілді
02:03 — №8 блок тексерілді және смарт келісімшарттың «жіберуБлок» функциясы Merkle хэшімен және блок нөмірімен шақырылады.
02:10 — 1 секундта 32 миллион транзакция жіберген демо-скрипт жұмыс істеді.
02:33 - түйіндер түбірлік тізбекке №8 блок қосылғаны туралы ақпаратты ала бастады және 240 мың транзакцияны орындай бастады.
02:40 - №240 блокта бар 8 мың транзакция пулдан жойылды
02:56 — жіберу түйіні қалған 760 мың транзакцияны пулдан алып, Merkle хэшін және №9 қол қою блогын есептей бастады.
03:20 - барлық түйіндерде 1 миллион 240к транзакциялар мен белгілер бар
03:35 — №9 блокқа қол қойылды және басқа түйіндерге валидацияға жіберіледі
03:41 - желі қатесі орын алды
04:40 — №9 блокты тексеруді күту уақыты аяқталды
04:54 — жіберу түйіні қалған 760 мың транзакцияны пулдан алып, Merkle хэшін және №9 қол қою блогын есептей бастады.
05:32 — №9 блокқа қол қойылды және басқа түйіндерге валидацияға жіберіледі
05:53 — №9 блок расталды және түбірлік тізбекке жіберілді
06:17 - түйіндер түбірлік тізбекке №9 блок қосылғаны туралы ақпаратты ала бастады және 760 мың транзакцияны орындай бастады.
06:47 — пул №9 блоктағы транзакциялардан тазартылды
09:06 - барлық түйіндерде 2 миллион транзакциялар мен белгілер бар

Тест 2

Бір блок үшін 350 мың шектеу бар. Нәтижесінде бізде 3 блок бар.


Бастапқы күй: соңғы блок №9; Дерекқорда 2 миллион транзакциялар мен токендер сақталады

00:00 — транзакцияны құру сценарийі іске қосылды
00:44 - 1 миллион транзакция жасалып, түйінге жіберу басталды
00:56 — жіберу түйіні пулдан 320 мың транзакцияны қабылдады және №10 блокты қалыптастырады. Сондай-ақ 320 секундта пулға 10 мың транзакция қосылғанын көреміз
01:12 — №10 блокқа қол қойылды және валидация үшін басқа түйіндерге жіберіледі
01:18 — 1 секундта 34 миллион транзакция жіберген демо-скрипт жұмыс істеді.
01:20 — №10 блок валидацияланып, түбірлік тізбекке жіберілді
01:51 - барлық түйіндер №10 блок қосылған түбірлік тізбектен ақпаратты алды және 320 мың транзакцияны қолдана бастайды
02:01 - пул №320 блокқа қосылған 10 мың транзакция үшін тазартылды
02:15 — жіберу түйіні пулдан 350 мың транзакцияны қабылдады және №11 блокты қалыптастырады
02:34 — №11 блокқа қол қойылды және валидация үшін басқа түйіндерге жіберіледі
02:51 — №11 блок валидацияланып, түбірлік тізбекке жіберілді
02:55 — соңғы түйін №10 блоктан транзакцияларды аяқтады
10:59 — №9 блокты беру транзакциясы түбірлік тізбекте өте ұзақ уақытқа созылды, бірақ ол аяқталды және барлық түйіндер бұл туралы ақпарат алды және 350 мың транзакцияны орындай бастады.
11:05 - пул №320 блокқа қосылған 11 мың транзакция үшін тазартылды
12:10 - барлық түйіндерде 1 миллион 670к транзакциялар мен белгілер бар
12:17 — жіберу түйіні пулдан 330 мың транзакцияны қабылдады және №12 блокты қалыптастырады
12:32 — №12 блокқа қол қойылды және валидация үшін басқа түйіндерге жіберіледі
12:39 — №12 блок валидацияланып, түбірлік тізбекке жіберілді
13:44 - барлық түйіндер №12 блок қосылған және 330 мың транзакцияны қолдана бастағаны туралы түбірлік тізбектен ақпарат алды.
14:50 - барлық түйіндерде 2 миллион транзакциялар мен белгілер бар

Тест 3

Бірінші және екінші серверлерде бір тексеру түйіні жіберуші түйінмен ауыстырылды.


Бастапқы күй: соңғы блок №84; Дерекқорда сақталған 0 транзакция және таңбалауыш

00:00 — әрқайсысы 3 миллион транзакция жасайтын және жіберетін 1 сценарий іске қосылды
01:38 — 1 миллион транзакция жасалып, №3 түйінге жіберу басталды
01:50 — жіберу №3 түйін пулдан 330 мың транзакцияны алды және №85 (f21) блогын қалыптастырады. Сондай-ақ 350 секундта пулға 10 мың транзакция қосылғанын көреміз
01:53 — 1 миллион транзакция жасалып, №1 түйінге жіберу басталды
01:50 — жіберу №3 түйін пулдан 330 мың транзакцияны алды және №85 (f21) блогын қалыптастырады. Сондай-ақ 350 секундта пулға 10 мың транзакция қосылғанын көреміз
02:01 — жіберу №1 түйін пулдан 250 мың транзакцияны алды және № 85 (65e) блогын қалыптастырады
02:06 — №85 (f21) блогына қол қойылды және валидация үшін басқа түйіндерге жіберіледі
02:08 — 3 секундта 1 миллион транзакция жіберген №30 сервердің демо-скрипті жұмысын аяқтады.
02:14 — №85 блок (f21) расталды және түбірлік тізбекке жіберілді
02:19 — №85 (65е) блогына қол қойылды және валидация үшін басқа түйіндерге жіберіледі.
02:22 — 1 миллион транзакция жасалып, №2 түйінге жіберу басталды
02:27 — №85 блок (65е) валидацияланып, түбірлік тізбекке жіберілді
02:29 — №2 жіберу түйіні пулдан 111855 транзакцияны қабылдады және №85 (256) блогын қалыптастырады.
02:36 — №85 (256) блогына қол қойылды және валидация үшін басқа түйіндерге жіберіледі.
02:36 — 1 секундта 1 миллион транзакция жіберген №42.5 сервердің демо-скрипті жұмысын аяқтады.
02:38 — №85 блок (256) валидацияланып, түбірлік тізбекке жіберілді
03:08 — 2 секундта 1 миллион транзакция жіберген №47 сервер сценарийі жұмысын аяқтады.
03:38 - барлық түйіндер №85 (f21), №86(65e), №87(256) блоктары қосылған және 330k, 250k, 111855 транзакцияларды қолдана бастаған түбірлік тізбектен ақпарат алды.
03:49 - пул №330 (f250), №111855(85e), №21(86) блоктарына қосылған 65k, 87k, 256 транзакцияларда тазартылды.
03:59 — №1 жіберу түйіні пулдан және №888145 (88) нысандар блогынан 214 2 транзакцияны қабылдады, №750 жіберу түйіні пулдан және №88 (50а) нысандар блогынан 3 мың транзакцияны алды, №670 жіберу түйіні келесіден 88 мың транзакцияны алды. бассейн және пішіндер блогы №3 (dXNUMXb)
04:44 — №88 (d3b) блогына қол қойылды және валидация үшін басқа түйіндерге жіберіледі
04:58 — №88 (214) блогына қол қойылды және валидация үшін басқа түйіндерге жіберіледі.
05:11 — №88 (50а) блогына қол қойылды және валидация үшін басқа түйіндерге жіберіледі.
05:11 — №85 блок (d3b) расталды және түбірлік тізбекке жіберілді
05:36 — №85 блок (214) валидацияланып, түбірлік тізбекке жіберілді
05:43 - барлық түйіндер №88 (d3b), №89(214) блоктары қосылған және 670k, 750k транзакцияларды қолдана бастағаны туралы түбірлік тізбектен ақпарат алды.
06:50 — байланыс ақауына байланысты №85 блок (50а) расталмады
06:55 — №2 жіберу түйіні пулдан 888145 транзакцияны қабылдады және №90 (50а) блогын пішіндер
08:14 — №90 (50а) блогына қол қойылды және валидация үшін басқа түйіндерге жіберіледі.
09:04 — №90 блок (50а) валидацияланды және түбірлік тізбекке жіберілді
11:23 - барлық түйіндер түбірлік тізбектен №90 (50а) блогы қосылғаны туралы ақпаратты алды және 888145 транзакцияны қолдана бастайды. Бұл ретте №3 сервер №88 (d3b), №89(214) блоктарынан транзакцияларды қолданды.
12:11 - барлық бассейндер бос
13:41 — №3 сервердің барлық түйіндерінде 3 миллион транзакциялар мен белгілер бар
14:35 — №1 сервердің барлық түйіндерінде 3 миллион транзакциялар мен белгілер бар
19:24 — №2 сервердің барлық түйіндерінде 3 миллион транзакциялар мен белгілер бар

Кедергілер

Plasma Cash әзірлеу барысында біз бірте-бірте шешіп, шешіп жатқан келесі мәселелерге тап болдық:

1. Әртүрлі жүйе функцияларының өзара әрекеттесуіндегі қақтығыс. Мысалы, пулға транзакцияларды қосу функциясы блоктарды жіберу және тексеру жұмысын бұғаттады және керісінше, бұл жылдамдықтың төмендеуіне әкелді.

2. Деректерді тасымалдау шығындарын азайту кезінде транзакциялардың үлкен санын қалай жіберуге болатыны бірден белгісіз болды.

3. Жоғары нәтижелерге қол жеткізу үшін деректерді қалай және қайда сақтау керектігі түсініксіз болды.

4. Түйіндер арасындағы желіні қалай ұйымдастыру керектігі түсініксіз болды, өйткені 1 миллион транзакциялары бар блоктың өлшемі шамамен 100 МБ құрайды.

5. Бір ағынды режимде жұмыс ұзақ есептеулер орын алған кезде түйіндер арасындағы байланысты үзеді (мысалы, Merkle ағашын құру және оның хэшін есептеу).

Мұның бәрін біз қалай шештік?

Plasma Cash түйінінің бірінші нұсқасы бір уақытта барлығын орындай алатын: транзакцияларды қабылдауға, блоктарды жіберуге және тексеруге және деректерге қол жеткізу үшін API қамтамасыз етуге болатын комбайн түрі болды. NodeJS бір ағынды болғандықтан, ауыр Merkle ағашын есептеу функциясы транзакцияны қосу функциясын блоктады. Біз бұл мәселені шешудің екі нұсқасын көрдік:

1. Әрқайсысы белгілі бір функцияларды орындайтын бірнеше NodeJS процестерін іске қосыңыз.

2. worker_threads пайдаланыңыз және код бөлігінің орындалуын ағындарға жылжытыңыз.

Нәтижесінде біз екі опцияны бір уақытта қолдандық: біз логикалық түрде бір түйінді бөлек жұмыс істей алатын 3 бөлікке бөлдік, бірақ бір уақытта синхронды түрде.

1. Пулға транзакцияларды қабылдайтын және блоктарды жасайтын жіберу түйіні.

2. Түйіндердің жарамдылығын тексеретін тексеру түйіні.

3. API түйіні - деректерге қол жеткізу үшін API ұсынады.

Бұл жағдайда cli көмегімен unix ұясы арқылы әрбір түйінге қосылуға болады.

Біз Merkle ағашын есептеу сияқты ауыр операцияларды бөлек жіпке ауыстырдық.

Осылайша, біз барлық Plasma Cash функцияларының бір уақытта және ақаусыз қалыпты жұмысына қол жеткіздік.

Жүйе жұмыс істегеннен кейін біз жылдамдықты сынай бастадық және өкінішке орай, қанағаттанарлықсыз нәтижелер алдық: секундына 5 000 транзакция және блок үшін 50 000 транзакцияға дейін. Ненің дұрыс орындалмағанын анықтауға тура келді.

Алдымен жүйенің ең жоғары мүмкіндігін білу үшін Plasma Cash-пен байланыс механизмін сынауды бастадық. Біз бұрын Plasma Cash түйіні unix розеткасының интерфейсін қамтамасыз ететінін жазғанбыз. Бастапқыда ол мәтінге негізделген. json нысандары `JSON.parse()` және `JSON.stringify()` арқылы жіберілді.

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

Біз мұндай объектілердің тасымалдау жылдамдығын өлшеп, секундына ~ 130к таптық. Біз json-мен жұмыс істеу үшін стандартты функцияларды ауыстыруға тырыстық, бірақ өнімділік жақсарған жоқ. V8 қозғалтқышы осы операциялар үшін жақсы оңтайландырылған болуы керек.

Біз сабақтар арқылы транзакциялармен, токендермен және блоктармен жұмыс істедік. Мұндай сыныптарды құру кезінде өнімділік 2 есе төмендеді, бұл OOP бізге сәйкес келмейтінін көрсетеді. Мен бәрін таза функционалды көзқарасқа қайта жазуға тура келді.

Мәліметтер базасына жазу

Бастапқыда Redis біздің талаптарымызды қанағаттандыратын ең өнімді шешімдердің бірі ретінде деректерді сақтау үшін таңдалды: кілт-мәнді сақтау, хэш кестелерімен, жиынтықтармен жұмыс. Біз редис-бенчмаркті іске қостық және 80 конвейер режимінде секундына ~ 1 мың операция алдық.

Жоғары өнімділік үшін біз Redis-ті жақсырақ баптадық:

  • Unix ұялы байланысы орнатылды.
  • Біз күйді дискіге сақтауды өшірдік (сенімділік үшін көшірмені орнатуға және дискіге бөлек Redis ішінде сақтауға болады).

Redis-те пул хэш-кесте болып табылады, өйткені біз бір сұраудағы барлық транзакцияларды шығарып, транзакцияларды бір-бірлеп жоюымыз керек. Біз кәдімгі тізімді қолданып көрдік, бірақ бүкіл тізімді түсіргенде ол баяуырақ.

Стандартты NodeJS пайдалану кезінде Redis кітапханалары секундына 18 мың транзакция өнімділігіне қол жеткізді. Жылдамдық 9 есе төмендеді.

Эталон бізге мүмкіндіктердің 5 есе көп екенін көрсеткендіктен, біз оңтайландыруды бастадық. Біз кітапхананы ioredis түріне ауыстырдық және секундына 25к өнімділікке қол жеткіздік. Біз «hset» пәрменін пайдаланып транзакцияларды бір-бірлеп қостық. Сондықтан біз Redis-те көптеген сұрауларды жасадық. Транзакцияларды партияларға біріктіру және оларды бір «hmset» командасымен жіберу идеясы пайда болды. Нәтиже секундына 32 мың.

Төменде сипаттайтын бірнеше себептерге байланысты біз деректермен «Буфер» көмегімен жұмыс істейміз және жазу алдында оны мәтінге (`buffer.toString('hex')) түрлендірсеңіз, қосымша алуға болады. өнімділік. Осылайша, жылдамдық секундына 35 мыңға дейін көтерілді. Қазіргі уақытта біз одан әрі оңтайландыруды тоқтату туралы шешім қабылдадық.

Біз екілік протоколға ауысуға тура келді, себебі:

1. Жүйе көбінесе хэштерді, қолтаңбаларды және т.б. есептейді және ол үшін «Буфердегі» деректер қажет.

2. Қызметтер арасында жіберілген кезде, екілік деректер мәтіннен азырақ. Мысалы, 1 миллион транзакциялары бар блокты жіберу кезінде мәтіндегі деректер 300 мегабайттан астам алуы мүмкін.

3. Деректерді үнемі түрлендіру өнімділікке әсер етеді.

Сондықтан біз тамаша «екілік-деректер» кітапханасының негізінде әзірленген деректерді сақтау және беру үшін өзіміздің екілік протоколымызды негізге алдық.

Нәтижесінде біз келесі деректер құрылымдарын алдық:

— Мәміле

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

— Төкен

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

— Блок

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

Кәдімгі `BD.encode(block, Protocol).slice();` және `BD.decode(buffer, Protocol)` пәрмендерімен біз деректерді Redis жүйесінде сақтау немесе басқа түйінге қайта жіберу және шығарып алу үшін «Буферге» түрлендіреміз. деректер кері.

Сондай-ақ бізде қызметтер арасында деректерді тасымалдауға арналған 2 екілік протоколдар бар:

— Unix ұясы арқылы плазмалық түйінмен өзара әрекеттесу протоколы

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

мұнда:

  • `түр` — орындалатын әрекет, мысалы, 1 — sendTransaction, 2 — getTransaction;
  • `пайдалы жүк` — сәйкес функцияға өтуді қажет ететін деректер;
  • `messageId` — жауапты анықтауға болатын хабарлама идентификаторы.

— Түйіндер арасындағы өзара әрекеттесу протоколы

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

мұнда:

  • `код` — хабарлама коды, мысалы 6 — PREPARE_NEW_BLOCK, 7 — BLOCK_VALID, 8 — BLOCK_COMMIT;
  • `versionProtocol` — протокол нұсқасы, өйткені әртүрлі нұсқалары бар түйіндер желіде көтерілуі мүмкін және олар басқаша жұмыс істей алады;
  • `кезегі` — хабарлама идентификаторы;
  • 'Chunk санау' и `бөлшек саны` үлкен хабарларды бөлу үшін қажет;
  • `ұзындығы` и `пайдалы жүк` ұзындығы және деректердің өзі.

Деректерді алдын ала тергендіктен, соңғы жүйе Ethereum `rlp` кітапханасынан әлдеқайда жылдамырақ. Өкінішке орай, біз одан әлі бас тарта алмадық, өйткені болашақта жасауды жоспарлап отырған смарт келісімшартты аяқтау қажет.

Жылдамдыққа жете білсек 35 000 секундына транзакциялар, біз де оларды оңтайлы уақытта өңдеуіміз керек. Шамамен блокты қалыптастыру уақыты 30 секундты алатындықтан, біз блокқа қосуымыз керек 1 000 000 транзакциялар, бұл көбірек жіберуді білдіреді 100 МБ деректер.

Бастапқыда біз түйіндер арасында байланысу үшін «ethereumjs-devp2p» кітапханасын пайдаландық, бірақ ол соншалықты көп деректерді өңдей алмады. Нәтижесінде біз `ws` кітапханасын қолданып, екілік деректерді websocket арқылы жіберуді конфигурацияладық. Әрине, біз үлкен деректер пакеттерін жіберу кезінде де қиындықтарға тап болдық, бірақ біз оларды бөліктерге бөлдік, енді бұл мәселелер жойылды.

Сондай-ақ Merkle ағашын қалыптастыру және хэшті есептеу 1 000 000 транзакциялар туралы талап етеді 10 үздіксіз есептеу секундтары. Осы уақыт ішінде барлық түйіндермен байланыс үзіледі. Бұл есептеуді бөлек тарауға көшіру туралы шешім қабылданды.

Қорытынды:

Шын мәнінде, біздің қорытындыларымыз жаңа емес, бірақ қандай да бір себептермен көптеген сарапшылар даму кезінде олар туралы ұмытып кетеді.

  • Нысанға бағытталған бағдарламалаудың орнына функционалдық бағдарламалауды пайдалану өнімділікті арттырады.
  • Монолит өнімді NodeJS жүйесі үшін қызмет көрсету архитектурасынан нашар.
  • Күрделі есептеулер үшін `worker_threads` пайдалану жүйенің жауап беру қабілетін жақсартады, әсіресе енгізу/шығару операцияларымен жұмыс істегенде.
  • unix ұясы http сұрауларына қарағанда тұрақты және жылдамырақ.
  • Егер сізге үлкен деректерді желі арқылы жылдам тасымалдау қажет болса, веб-сокеттерді қолданып, екілік деректерді жіберген дұрыс, бөліктерге бөлінген, олар келмеген жағдайда қайта жіберуге болады, содан кейін бір хабарламаға біріктіріледі.

келуге шақырамыз GitHub жоба: https://github.com/opporty-com/Plasma-Cash/tree/new-version

Мақаланы бірлесіп жазған Александр Нашиван, аға әзірлеуші Clever Solution Inc.

Ақпарат көзі: www.habr.com

пікір қалдыру