Олон нийтийн тест: Ethereum дээрх нууцлал ба өргөтгөх боломжийн шийдэл

Блокчейн хүний ​​амьдралын олон салбарыг сайжруулах амлалт өгсөн шинэлэг технологи юм. Энэ нь бодит үйл явц, бүтээгдэхүүнийг дижитал орон зайд шилжүүлж, санхүүгийн гүйлгээний хурд, найдвартай байдлыг хангаж, зардлыг бууруулж, төвлөрсөн бус сүлжээнд ухаалаг гэрээ ашиглан орчин үеийн DAPP програмуудыг бий болгох боломжийг олгодог.

Блокчэйний олон давуу тал, олон төрлийн хэрэглээг харгалзан үзвэл энэхүү ирээдүйтэй технологи нь салбар бүрт нэвтэрч чадаагүй байгаа нь гайхмаар санагдаж магадгүй юм. Асуудал нь орчин үеийн төвлөрсөн бус блокчэйн нь өргөтгөх чадваргүйд оршино. Ethereum нь секундэд 20 орчим гүйлгээг боловсруулдаг бөгөөд энэ нь өнөөгийн динамик бизнесийн хэрэгцээг хангахад хангалтгүй юм. Үүний зэрэгцээ блокчэйн технологийг ашигладаг компаниуд Ethereum-ийг хакердах, сүлжээний доголдлоос хамгаалах өндөр хамгаалалттай тул орхихдоо эргэлзэж байна.

Блокчейн дэх төвлөрлийг сааруулах, аюулгүй байдал, өргөтгөх чадварыг хангахын тулд хөгжүүлэлтийн баг "Scalability Trilemma"-г шийдэж байна. Боломж Node.js дээр суурилсан ухаалаг гэрээ болон хувийн сүлжээнээс бүрдэх Plasma Cash хэмээх охин компаний сүлжээг үүсгэсэн бөгөөд энэ нь өөрийн төлөвийг үе үе эх ​​хэлхээнд (Ethereum) шилжүүлдэг.

Олон нийтийн тест: Ethereum дээрх нууцлал ба өргөтгөх боломжийн шийдэл

Плазма бэлэн мөнгөний гол үйл явц

1. Хэрэглэгч ухаалаг гэрээний функцийг `deposit` гэж нэрлээд Plasma Cash жетон руу байршуулахыг хүссэн ETH-ийн хэмжээгээ шилжүүлдэг. Ухаалаг гэрээний функц нь жетон үүсгэж, энэ тухай үйл явдлыг үүсгэдэг.

2. Ухаалаг гэрээний арга хэмжээнд бүртгүүлсэн Plasma Cash зангилаа нь хадгаламж үүсгэх тухай үйл явдлыг хүлээн авч, цөөрөмд жетон үүсгэх тухай гүйлгээг нэмнэ.

3. Үе үе тусгай Plasma Cash зангилаанууд бүх гүйлгээг цөөрмөөс (1 сая хүртэл) авч, тэдгээрээс блок үүсгэж, Merkle модыг тооцоолж, үүний дагуу хэшийг тооцдог. Энэ блокыг баталгаажуулахын тулд бусад зангилаа руу илгээдэг. Зангилаанууд нь Merkle хэш хүчинтэй эсэх, гүйлгээнүүд хүчинтэй эсэхийг шалгадаг (жишээлбэл, жетон илгээгч нь түүний эзэмшигч эсэх). Блокыг баталгаажуулсны дараа зангилаа ухаалаг гэрээний `submitBlock` функцийг дууддаг бөгөөд энэ нь блокийн дугаар болон Merkle хэшийг захын хэлхээнд хадгалдаг. Ухаалаг гэрээ нь блок амжилттай нэмэгдсэнийг харуулсан үйл явдлыг үүсгэдэг. Гүйлгээг цөөрмөөс хасдаг.

4. Блок илгээх үйл явдлыг хүлээн авсан зангилаанууд блокт нэмсэн гүйлгээг хэрэгжүүлж эхэлдэг.

5. Хэзээ нэгэн цагт жетон эзэмшигч (эсвэл эзэмшигч бус) үүнийг Plasma Cash-аас авахыг хүсдэг. Үүнийг хийхийн тулд тэрээр "startExit" функцийг дуудаж, жетон дээрх сүүлийн 2 гүйлгээний талаарх мэдээллийг дамжуулж, энэ нь түүнийг жетон эзэмшигч гэдгийг баталгаажуулдаг. Merkle хэш ашиглан ухаалаг гэрээ нь блокууд дахь гүйлгээ байгаа эсэхийг шалгаж, хоёр долоо хоногийн дараа гарах жетоныг буцааж авахаар илгээдэг.

6. Хэрэв жетоныг буцаан авах ажиллагаа зөрчилтэй гарсан бол (татан авах үйл ажиллагаа эхэлсний дараа жетоныг зарцуулсан эсвэл татан авалтаас өмнө токеныг аль хэдийн өөр хүнийх байсан) жетон эзэмшигч нь хоёр долоо хоногийн дотор татан авалтыг няцаах боломжтой.

Олон нийтийн тест: Ethereum дээрх нууцлал ба өргөтгөх боломжийн шийдэл

Нууцлалыг хоёр аргаар олж авдаг

1. Үндсэн хэлхээ нь хүүхдийн гинжин хэлхээнд үүсгэгдэж, дамжуулагдсан гүйлгээний талаар юу ч мэдэхгүй. Plasma Cash-аас ETH байршуулж, хэн татсан талаарх мэдээлэл олон нийтэд нээлттэй хэвээр байна.

2. Хүүхдийн сүлжээ нь zk-SNARKs ашиглан нэргүй гүйлгээ хийх боломжийг олгодог.

Технологийн стек

  • NodeJS
  • Redis
  • Этериум
  • Хөрс

Тест хийх

Plasma Cash-ийг хөгжүүлэх явцад бид системийн хурдыг туршиж үзээд дараах үр дүнг авсан.

  • усан санд секундэд 35 хүртэлх гүйлгээ нэмэгддэг;
  • блокт 1 хүртэлх гүйлгээг хадгалах боломжтой.

Туршилтыг дараах 3 сервер дээр хийсэн.

1. Intel Core i7-6700 Quad-Core Skylake incl. NVMe SSD – 512 ГБ, 64 ГБ DDR4 RAM
Баталгаажуулах 3 Plasma Cash зангилаа босгосон.

2. AMD Ryzen 7 1700X Octa-Core “Summit Ridge” (Zen), SATA SSD – 500 ГБ, 64 ГБ DDR4 RAM
Ropsten testnet ETH зангилаа босгосон.
Баталгаажуулах 3 Plasma Cash зангилаа босгосон.

3. Intel Core i9-9900K Octa-Core орно. NVMe SSD – 1 TB, 64 GB DDR4 RAM
1 Plasma Cash илгээх зангилаа босгосон.
Баталгаажуулах 3 Plasma Cash зангилаа босгосон.
Plasma Cash сүлжээнд гүйлгээ нэмэх туршилтыг эхлүүлсэн.

Нийт: Хувийн сүлжээнд 10 Plasma Cash зангилаа.

Туршилт 1

Блок бүрт 1 сая гүйлгээ хийх хязгаар бий. Тиймээс 1 сая гүйлгээ нь 2 блокт хуваагддаг (систем нь гүйлгээний нэг хэсгийг авч, илгээж байх үед илгээх боломжтой байдаг).


Анхны төлөв: сүүлчийн блок №7; Мэдээллийн санд 1 сая гүйлгээ, жетон хадгалагддаг.

00:00 - гүйлгээ үүсгэх скрипт эхлэх
01:37 - 1 сая гүйлгээ бий болж, зангилаа руу илгээж эхлэв
01:46 — submit node нь цөөрмөөс 240 мянган гүйлгээг авч, №8 блокийг бүрдүүлж байна. Мөн 320 секундын дотор 10 мянган гүйлгээ нэмэгдэж байгааг бид харж байна
01:58 — №8 блокт гарын үсэг зурж баталгаажуулахаар илгээв
02:03 — №8 блок баталгаажсан бөгөөд ухаалаг гэрээний `submitBlock` функцийг Merkle хэш болон блокийн дугаараар дууддаг.
02:10 - 1 секундын дотор 32 сая гүйлгээ илгээсэн демо скрипт ажиллаж дууссан.
02:33 - зангилаанууд эх гинжин хэлхээнд №8 блок нэмэгдсэн гэсэн мэдээллийг хүлээн авч, 240 мянган гүйлгээ хийж эхлэв.
02:40 - 240-р блокт байгаа 8 мянган гүйлгээг цөөрмөөс хассан
02:56 — submit node нь цөөрмөөс үлдсэн 760k гүйлгээг авч, Merkle hash болон signing block #9-ийг тооцоолж эхлэв.
03:20 - бүх зангилаа нь 1 сая 240к гүйлгээ, жетон агуулдаг
03:35 — блок №9 гарын үсэг зурж, бусад зангилаа руу баталгаажуулахаар илгээв
03:41 - сүлжээний алдаа гарлаа
04:40 — №9 блокийн баталгаажуулалтыг хүлээж байх хугацаа дууссан
04:54 — submit node нь цөөрмөөс үлдсэн 760k гүйлгээг авч, Merkle hash болон signing block #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 — submit node нь цөөрмөөс 320 мянган гүйлгээг авч, №10 блокийг бүрдүүлж байна. Мөн 320 секундын дотор 10 мянган гүйлгээ нэмэгдэж байгааг бид харж байна
01:12 — №10 блокт гарын үсэг зурж баталгаажуулахын тулд бусад зангилаа руу илгээсэн
01:18 - 1 секундын дотор 34 сая гүйлгээ илгээсэн демо скрипт ажиллаж дууссан.
01:20 — №10 блокыг баталгаажуулж, үндсэн хэлхээнд илгээв
01:51 - бүх зангилаа 10-р блок нэмэгдсэн гэсэн үндсэн сүлжээнээс мэдээлэл хүлээн авч, 320 мянган гүйлгээг ашиглаж эхэлсэн.
02:01 - 320-р блок дээр нэмсэн 10 мянган гүйлгээг цөөрөм арилгасан.
02:15 — submit node нь усан сангаас 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 — submit зангилаа нь сангаас 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 (65e) гарын үсэг зурж баталгаажуулахын тулд бусад зангилаа руу илгээсэн.
02:22 — 1 сая гүйлгээ хийгдэж, 2-р зангилаанд илгээж эхлэв
02:27 - блок №85 (65e) баталгаажуулж, үндсэн хэлхээнд илгээсэн
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 — submit зангилаа #1 нь бассейнаас 888145 гүйлгээ хийсэн ба 88 (214) блок, submit #2 нь бассейнаас 750 мянган гүйлгээ хийсэн ба 88 (50а) блокоос, submit #3 дугаар блокоос 670 мянган гүйлгээ хийсэн. усан сан ба маягтын блок №88 (d3b)
04:44 - блок №88 (d3b) гарын үсэг зурж баталгаажуулахын тулд бусад зангилаа руу илгээсэн.
04:58 - блок №88 (214) гарын үсэг зурж, баталгаажуулахын тулд бусад зангилаа руу илгээсэн.
05:11 - блок №88 (50a) гарын үсэг зурж баталгаажуулахын тулд бусад зангилаа руу илгээсэн.
05:11 — блок №85 (d3b) баталгаажуулж, үндсэн хэлхээ рүү илгээгдсэн
05:36 — блок №85 (214) баталгаажсан ба үндсэн хэлхээ рүү илгээгдсэн
05:43 - бүх зангилаа 88 (d3b), №89(214) блокуудыг нэмж, 670к, 750к гүйлгээг ашиглаж эхэлсэн тухай эх хэлхээнээс мэдээлэл хүлээн авсан.
06:50 — холбоо тасарсны улмаас №85 (50а) блок баталгаажуулаагүй
06:55 — илгээх зангилаа №2 нь цөөрмөөс 888145 гүйлгээг авч, 90-р блок (50a) маягтаас авсан.
08:14 - блок №90 (50a) гарын үсэг зурж баталгаажуулахын тулд бусад зангилаа руу илгээсэн.
09:04 — блок №90 (50a) баталгаажсан ба үндсэн хэлхээ рүү илгээгдсэн
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-г ашиглаад кодын нэг хэсгийн гүйцэтгэлийг thread руу шилжүүлнэ.

Үүний үр дүнд бид хоёр сонголтыг нэгэн зэрэг ашигласан: бид логикоор нэг зангилааг тусад нь ажиллах боломжтой, гэхдээ нэгэн зэрэг синхроноор 3 хэсэгт хуваасан.

1. Цөөрөмд гүйлгээг хүлээн авч, блок үүсгэдэг илгээх зангилаа.

2. Зангилааны хүчинтэй байдлыг шалгадаг баталгаажуулах зангилаа.

3. API зангилаа - өгөгдөлд хандах API өгдөг.

Энэ тохиолдолд та cli ашиглан unix залгуураар зангилаа бүртэй холбогдож болно.

Бид Merkle модыг тооцоолох гэх мэт хүнд үйлдлүүдийг тусдаа утас руу шилжүүлсэн.

Ийнхүү бид Plasma Cash-ийн бүх функцийг нэгэн зэрэг, доголдолгүй хэвийн ажиллуулж чадсан.

Систем ажиллаж эхэлмэгц бид хурдыг туршиж эхэлсэн бөгөөд харамсалтай нь хангалтгүй үр дүн авсан: секундэд 5 гүйлгээ, блок тутамд 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-ийг өгөгдөл хадгалахад зориулж бидний шаардлагыг хангасан хамгийн бүтээмжтэй шийдлүүдийн нэг болгон сонгосон: түлхүүр-утга хадгалах, хэш хүснэгт, багцтай ажиллах. Бид redis-benchmark-ийг эхлүүлж, 80 дамжуулах горимд секундэд ~1 мянган үйлдэл хийсэн.

Өндөр гүйцэтгэлтэй байхын тулд бид Redis-ийг илүү нарийн тохируулсан:

  • Unix сокет холболт үүсгэгдсэн.
  • Бид төлөвийг дискэнд хадгалахыг идэвхгүй болгосон (найдвартай байхын тулд та хуулбарыг тохируулж, диск рүү тусдаа Redis-д хадгалах боломжтой).

Redis-д сан нь хэш хүснэгт юм, учир нь бид бүх гүйлгээг нэг асуулгад авч, гүйлгээг нэг нэгээр нь устгах чадвартай байх ёстой. Бид ердийн жагсаалтыг ашиглахыг оролдсон боловч жагсаалтыг бүхэлд нь буулгахад удаашралтай байна.

Стандарт NodeJS ашиглах үед Redis номын сангууд секундэд 18 мянган гүйлгээний гүйцэтгэлтэй болсон. Хурд 9 дахин буурсан.

Жишиг боломжууд 5 дахин их байгааг харуулсан тул бид оновчтой болгож эхэлсэн. Бид номын санг ioredis болгож өөрчилсөн бөгөөд секундэд 25к гүйцэтгэлтэй болсон. Бид `hset` командыг ашиглан гүйлгээг нэг нэгээр нь нэмсэн. Тиймээс бид Redis дээр маш олон асуулга үүсгэж байсан. Гүйлгээг багц болгон нэгтгэж, нэг "hmset" командаар илгээх санаа гарч ирэв. Үр дүн нь секундэд 32к байна.

Доор тайлбарлах хэд хэдэн шалтгааны улмаас бид `Buffer` ашиглан өгөгдөлтэй ажилладаг бөгөөд хэрэв та үүнийг бичихээсээ өмнө текст (`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-д хадгалах эсвэл өөр зангилаа руу дамжуулах, сэргээх зорилгоор `Buffer` болгон хувиргадаг. өгөгдлийг буцааж өгөх.

Мөн бид үйлчилгээ хооронд өгөгдөл дамжуулах 2 хоёртын протоколтой:

— Unix залгуураар дамжуулан Plasma Node-тэй харилцах протокол

  ```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` - мессежийн id, ингэснээр хариултыг тодорхойлох боломжтой.

— Зангилаа хоорондын харилцан үйлчлэлийн протокол

  ```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 — ШИНЭ_БЛОК БЭЛТГЭХ, 7 — БЛОК_ХҮЧТЭЙ, 8 — БЛОК_COMMIT;
  • `хувилбар Протокол` - протоколын хувилбар, учир нь өөр өөр хувилбар бүхий зангилаанууд нь сүлжээнд тавигдах бөгөөд тэдгээр нь өөр өөрөөр ажиллах боломжтой;
  • `seq` - мессеж танигч;
  • `Chunk тоолох` и `хэсэгний дугаар` том мессежийг хуваахад шаардлагатай;
  • 'урт' и `ачаалал` урт ба өгөгдөл өөрөө.

Бид өгөгдлийг урьдчилан бичсэн тул эцсийн систем нь Ethereum-ийн `rlp` номын сангаас хамаагүй хурдан юм. Харамсалтай нь цаашид хийхээр төлөвлөж буй ухаалаг гэрээг эцэслэх шаардлагатай байгаа тул одоохондоо татгалзаж чадаагүй байна.

Хэрэв бид хурдаа гаргаж чадсан бол 35 000 секундэд гүйлгээ хийдэг бол бид тэдгээрийг оновчтой хугацаанд боловсруулах хэрэгтэй. Ойролцоогоор блок үүсгэх хугацаа 30 секунд үргэлжилдэг тул бид блокт оруулах хэрэгтэй 1 000 000 гүйлгээ, энэ нь илүү их илгээх гэсэн үг юм 100 МБ өгөгдөл.

Эхэндээ бид `ethereumjs-devp2p` номын санг зангилаа хооронд харилцахдаа ашигладаг байсан ч энэ нь тийм ч их мэдээлэлтэй ажиллах боломжгүй байв. Үүний үр дүнд бид `ws` номын санг ашиглаж, вэбсокетээр хоёртын өгөгдөл илгээх тохиргоог хийсэн. Мэдээжийн хэрэг, бид том өгөгдлийн пакетуудыг илгээх үед асуудалтай тулгарсан, гэхдээ бид тэдгээрийг хэсэг болгон хувааж, одоо эдгээр асуудлууд алга болсон.

Мөн Merkle модыг үүсгэж, хэшийг тооцоолох 1 000 000 гүйлгээний талаар шаарддаг 10 секундын тасралтгүй тооцоолол. Энэ хугацаанд бүх зангилаатай холболт тасардаг. Энэ тооцоог тусдаа сэдэв рүү шилжүүлэхээр шийдсэн.

Дүгнэлт:

Үнэн хэрэгтээ бидний олж мэдсэн зүйл бол шинэ зүйл биш, гэхдээ зарим шалтгааны улмаас олон мэргэжилтнүүд хөгжлийн явцад үүнийг мартдаг.

  • Объект хандалтат програмчлалын оронд функциональ програмчлалыг ашиглах нь бүтээмжийг сайжруулдаг.
  • Цул нь бүтээмжтэй NodeJS системийн үйлчилгээний архитектураас муу юм.
  • Хүнд тооцоололд `worker_threads`-ийг ашиглах нь системийн хариу үйлдлийг сайжруулдаг, ялангуяа оролт гаралтын үйлдлүүдтэй харьцах үед.
  • unix сокет нь http хүсэлтээс илүү тогтвортой бөгөөд хурдан байдаг.
  • Хэрэв та сүлжээгээр их хэмжээний өгөгдлийг хурдан дамжуулах шаардлагатай бол websockets ашиглаж, хоёртын өгөгдлийг илгээж, хэсэг болгон хувааж, ирэхгүй бол дамжуулж, дараа нь нэг мессеж болгон нэгтгэх нь дээр.

Таныг зочлохыг урьж байна GitHub төсөл: https://github.com/opporty-com/Plasma-Cash/tree/new-version

Нийтлэлийг хамтран бичсэн Александр Нашиван, ахлах хөгжүүлэгч Clever Solution Inc.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх