{"id":38856,"date":"2019-10-31T22:26:22","date_gmt":"2019-10-31T19:26:22","guid":{"rendered":"https:\/\/prohoster.info\/blog\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume\/"},"modified":"2019-10-31T22:26:22","modified_gmt":"2019-10-31T19:26:22","slug":"publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume","title":{"rendered":"Publiczny test: rozwi\u0105zanie dla prywatno\u015bci i skalowalno\u015bci w Ethereum","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><b>Blockchain<\/b> \u2014 innowacyjna technologia, obiecuj\u0105ca popraw\u0119 wielu dziedzin \u017cycia ludzkiego. Przenosi rzeczywiste procesy i produkty do przestrzeni cyfrowej, zapewniaj\u0105c szybko\u015b\u0107 i niezawodno\u015b\u0107 operacji finansowych, obni\u017caj\u0105c ich koszt, a tak\u017ce pozwala na tworzenie nowoczesnych aplikacji DAPP przy u\u017cyciu inteligentnych kontrakt\u00f3w w zdecentralizowanych sieciach.<\/p>\n<p>Bior\u0105c pod uwag\u0119 liczne zalety i r\u00f3\u017cnorodno\u015b\u0107 zastosowa\u0144 blockchaina, mo\u017ce wydawa\u0107 si\u0119 dziwne, \u017ce ta obiecuj\u0105ca technologia jeszcze nie przenikn\u0119\u0142a do wszystkich bran\u017c. Problemem jest to, \u017ce nowoczesne zdecentralizowane blockchainy brakuje skalowalno\u015bci. Ethereum obs\u0142uguje oko\u0142o 20 transakcji na sekund\u0119, co jest niewystarczaj\u0105ce, aby zaspokoi\u0107 potrzeby dynamicznego wsp\u00f3\u0142czesnego biznesu. Jednocze\u015bnie firmy korzystaj\u0105ce z technologii blockchain nie decyduj\u0105 si\u0119 na rezygnacj\u0119 z Ethereum ze wzgl\u0119du na jego wysoki poziom ochrony przed w\u0142amaniami i awariami sieci.<\/p>\n<p>Aby zapewni\u0107 decentralizacj\u0119, bezpiecze\u0144stwo i skalowalno\u015b\u0107 w blockchainie, rozwi\u0105zuj\u0105c w ten spos\u00f3b Trilemm\u0119 Skalowalno\u015bci, zesp\u00f3\u0142 programist\u00f3w <noindex><a rel=\"nofollow\" href=\"https:\/\/opporty.com\/\">Opporty<\/a><\/noindex> stworzy\u0142 Plasma Cash \u2014 podrz\u0119dny \u0142a\u0144cuch sk\u0142adaj\u0105cy si\u0119 z inteligentnego kontraktu oraz prywatnej sieci opartej na Node.js, kt\u00f3ra okresowo przekazuje swoje stany do \u0142a\u0144cucha g\u0142\u00f3wnego (Ethereum).<\/p>\n<p><img decoding=\"async\" alt=\"Publiczny test: rozwi\u0105zanie dla prywatno\u015bci i skalowalno\u015bci w Ethereum\" src=\"\/wp-content\/uploads\/2019\/10\/02cc45df3474179d0936c2a86fb7dee3.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Kluczowe procesy w Plasma Cash<\/h2>\n<p>\n<b>1. <\/b>U\u017cytkownik wywo\u0142uje funkcj\u0119 inteligentnego kontraktu `deposit`, przekazuj\u0105c do niej kwot\u0119 w ETH, kt\u00f3r\u0105 chce wp\u0142aci\u0107 do tokena Plasma Cash. Funkcja inteligentnego kontraktu tworzy token i generuje zdarzenie o tym.<\/p>\n<p><b>2. <\/b>W\u0119z\u0142y Plasma Cash, subskrybowane na zdarzenia inteligentnego kontraktu, otrzymuj\u0105 zdarzenie o utworzeniu depozytu i dodaj\u0105 do puli transakcj\u0119 o utworzeniu tokena.<\/p>\n<p><b>3. <\/b>Okresowo specjalne w\u0119z\u0142y Plasma Cash bior\u0105 wszystkie transakcje z puli (do 1 miliona) i formuj\u0105 z nich blok, obliczaj\u0105 drzewo Merkle i odpowiednio hash. Blok ten jest wysy\u0142any do innych w\u0119z\u0142\u00f3w do weryfikacji. W\u0119z\u0142y sprawdzaj\u0105, czy hash Merkle jest wa\u017cny, czy transakcje s\u0105 wa\u017cne (na przyk\u0142ad, czy nadawca tokena jest jego w\u0142a\u015bcicielem). Po weryfikacji bloku w\u0119ze\u0142 wywo\u0142uje funkcj\u0119 `submitBlock` inteligentnego kontraktu, kt\u00f3ra zapisuje w \u0142a\u0144cuchu g\u0142\u00f3wnym numer i hash bloku Merkle. Inteligentny kontrakt generuje zdarzenie o pomy\u015blnym dodaniu bloku. Transakcje s\u0105 usuwane z puli. <\/p>\n<p><b>4. <\/b>W\u0119z\u0142y, kt\u00f3re otrzyma\u0142y zdarzenie o submicie bloku, zaczynaj\u0105 stosowa\u0107 transakcje, kt\u00f3re zosta\u0142y dodane do bloku.<\/p>\n<p><b>5. <\/b>W pewnym momencie w\u0142a\u015bciciel (lub nie w\u0142a\u015bciciel) tokena chce go wycofa\u0107 z Plasma Cash. W tym celu wywo\u0142uje funkcj\u0119 `startExit`, przekazuj\u0105c jej informacje o ostatnich 2 transakcjach dotycz\u0105cych tokena, kt\u00f3re potwierdzaj\u0105, \u017ce faktycznie jest on w\u0142a\u015bcicielem tokena. Smart kontrakt, u\u017cywaj\u0105c hasha Merkle'a, sprawdza obecno\u015b\u0107 transakcji w blokach i wysy\u0142a token do wycofania, kt\u00f3re nast\u0105pi za dwa tygodnie.<\/p>\n<p><b>6. <\/b>Je\u017celi operacja wycofania tokena mia\u0142a miejsce z naruszeniami (token zosta\u0142 wydany po rozpocz\u0119ciu procedury wycofania lub token przed wycofaniem ju\u017c nale\u017ca\u0142 do kogo\u015b innego), w\u0142a\u015bciciel tokena mo\u017ce obali\u0107 wycofanie w ci\u0105gu dw\u00f3ch tygodni.<\/p>\n<p><img decoding=\"async\" alt=\"Publiczny test: rozwi\u0105zanie dla prywatno\u015bci i skalowalno\u015bci w Ethereum\" src=\"\/wp-content\/uploads\/2019\/10\/0626ca6b010eb847175dbfb0b6d7b357.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Prywatno\u015b\u0107 osi\u0105ga si\u0119 na dwa sposoby.<\/h2>\n<p>\n<b>1. <\/b>G\u0142\u00f3wna sie\u0107 nie wie nic o transakcjach, kt\u00f3re s\u0105 formowane i przesy\u0142ane wewn\u0105trz podrz\u0119dnej sieci. Publiczne pozostaje jedynie informacje o tym, kto wprowadzi\u0142 i wycofa\u0142 ETH z\/do Plasma Cash.<\/p>\n<p><b>2. <\/b>Podrz\u0119dna sie\u0107 umo\u017cliwia organizowanie anonimowych transakcji, korzystaj\u0105c z zk-SNARKs.<\/p>\n<h2>Stos technologiczny<\/h2>\n<p><\/p>\n<ul>\n<li>NodeJS<\/li>\n<li>Redis<\/li>\n<li>Etherium<\/li>\n<li>Soild<\/li>\n<\/ul>\n<p><\/p>\n<h2>Testowanie <\/h2>\n<p>\nPodczas opracowywania Plasma Cash przetestowali\u015bmy szybko\u015b\u0107 dzia\u0142ania systemu i uzyskali\u015bmy nast\u0119puj\u0105ce wyniki:<\/p>\n<ul>\n<li>do 35 000 transakcji na sekund\u0119 dodawanych do puli;<\/li>\n<li>do 1 000 000 transakcji mo\u017ce by\u0107 przechowywanych w bloku.<\/li>\n<\/ul>\n<p>\nTesty przeprowadzono na 3 nast\u0119puj\u0105cych serwerach:<\/p>\n<p><i>1. Intel Core i7-6700 Quad-Core Skylake z NVMe SSD \u2014 512 GB, 64 GB DDR4 RAM<\/i><br \/>\n Zosta\u0142y uruchomione 3 waliduj\u0105ce w\u0119z\u0142y Plasma Cash.<\/p>\n<p><i>2. AMD Ryzen 7 1700X Octa-Core \u00abSummit Ridge\u00bb (Zen), SATA SSD \u2014 500 GB, 64 GB DDR4 RAM<\/i><br \/>\n Uruchomiono w\u0119ze\u0142 ETH w testnet Ropsten.<br \/>\n Zosta\u0142y uruchomione 3 waliduj\u0105ce w\u0119z\u0142y Plasma Cash.<\/p>\n<p><i>3. Intel Core i9-9900K Octa-Core z NVMe SSD \u2014 1 TB, 64 GB DDR4 RAM<\/i><br \/>\n Uruchomiono 1 w\u0119ze\u0142 submittuj\u0105cy Plasma Cash.<br \/>\n Zosta\u0142y uruchomione 3 waliduj\u0105ce w\u0119z\u0142y Plasma Cash.<br \/>\n Testowano dodawanie transakcji do sieci Plasma Cash.<\/p>\n<p><b>Podsumowuj\u0105c: <\/b>10 w\u0119z\u0142\u00f3w Plasma Cash w prywatnej sieci.<\/p>\n<h3>Test 1<\/h3>\n<p>\nJest limit na 1 milion transakcji w bloku. Dlatego 1 milion transakcji trafia do 2 blok\u00f3w (poniewa\u017c system ma czas na zabranie cz\u0119\u015bci transakcji i ich submittowanie, podczas gdy s\u0105 one wysy\u0142ane).<\/p>\n<p><center><div class=\"youtube-placeholder\" data-id=\"pKwqyGkEgdQ\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/pKwqyGkEgdQ\/hqdefault.jpg\" alt=\"Odtwarzaj wideo\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nStan pocz\u0105tkowy: ostatni blok #7; w bazie zapisano 1 mln transakcji i token\u00f3w.<\/p>\n<p>00:00 \u2014 uruchomienie skryptu generuj\u0105cego transakcje<br \/>\n01:37 \u2014 utworzono 1 mln transakcji i rozpocz\u0119to wysy\u0142anie do w\u0119z\u0142a<br \/>\n01:46 \u2014 w\u0119ze\u0142 submittuj\u0105cy wzi\u0105\u0142 z puli 240k transakcji i formuje blok #8. Widzimy r\u00f3wnie\u017c, \u017ce do puli dodano 320k transakcji w ci\u0105gu 10 sekund.<br \/>\n01:58 \u2014 blok #8 podpisany i wys\u0142any do walidacji.<br \/>\n02:03 \u2014 blok #8 zosta\u0142 zwalidowany i wywo\u0142ana zosta\u0142a funkcja `submitBlock` smart kontraktu z hashem Merkle i numerem bloku<br \/>\n02:10 \u2014 zako\u0144czono dzia\u0142anie skryptu demo, kt\u00f3ry wys\u0142a\u0142 1 mln transakcji w 32 sekundy<br \/>\n02:33 \u2014 w\u0119z\u0142y zacz\u0119\u0142y otrzymywa\u0107 informacje, \u017ce blok #8 zosta\u0142 dodany do g\u0142\u00f3wnego \u0142a\u0144cucha i zacz\u0119\u0142y realizowa\u0107 240k transakcji<br \/>\n02:40 \u2014 z puli usuni\u0119to 240k transakcji, kt\u00f3re ju\u017c znajduj\u0105 si\u0119 w bloku #8<br \/>\n02:56 \u2014 w\u0119ze\u0142 submit pobra\u0142 z puli pozosta\u0142e 760k transakcji i rozpocz\u0105\u0142 obliczanie hasha Merkle oraz podpisywanie bloku #9<br \/>\n03:20 \u2014 wszystkie w\u0119z\u0142y zawieraj\u0105 1 mln 240k transakcji i token\u00f3w<br \/>\n03:35 \u2014 blok #9 zosta\u0142 podpisany i wysy\u0142any do walidacji do innych w\u0119z\u0142\u00f3w <br \/>\n03:41 \u2014 wyst\u0105pi\u0142 b\u0142\u0105d sieci<br \/>\n04:40 \u2014 wyczekiwano walidacji bloku #9, kt\u00f3rej czas oczekiwania wygas\u0142<br \/>\n04:54 \u2014 w\u0119ze\u0142 submit pobra\u0142 z puli pozosta\u0142e 760k transakcji i rozpocz\u0105\u0142 obliczanie hasha Merkle oraz podpisywanie bloku #9<br \/>\n05:32 \u2014 blok #9 zosta\u0142 podpisany i wysy\u0142any do walidacji do innych w\u0119z\u0142\u00f3w<br \/>\n05:53 \u2014 blok #9 zosta\u0142 zwalidowany i wys\u0142any do g\u0142\u00f3wnego \u0142a\u0144cucha<br \/>\n06:17 \u2014 w\u0119z\u0142y zacz\u0119\u0142y otrzymywa\u0107 informacje, \u017ce blok #9 zosta\u0142 dodany do g\u0142\u00f3wnego \u0142a\u0144cucha i zacz\u0119\u0142y realizowa\u0107 760k transakcji<br \/>\n06:47 \u2014 pula zosta\u0142a oczyszczona z transakcji, kt\u00f3re stanowi\u0142y blok #9<br \/>\n09:06 \u2014 wszystkie w\u0119z\u0142y zawieraj\u0105 2 mln transakcji i token\u00f3w<\/p>\n<h3>Test 2<\/h3>\n<p>\nUstalono limit na 350k na blok. W rezultacie mamy 3 bloki.<\/p>\n<p><center><div class=\"youtube-placeholder\" data-id=\"mpTfTPKYRIc\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/mpTfTPKYRIc\/hqdefault.jpg\" alt=\"Odtwarzaj wideo\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nStan pocz\u0105tkowy: ostatni blok #9; w bazie zapisano 2 mln transakcji i token\u00f3w<\/p>\n<p>00:00 \u2014 skrypt generowania transakcji zosta\u0142 ju\u017c uruchomiony<br \/>\n00:44 \u2014 stworzono 1 mln transakcji i rozpocz\u0119to ich wysy\u0142anie do w\u0119z\u0142a<br \/>\n00:56 \u2014 w\u0119ze\u0142 submit pobra\u0142 z puli 320k transakcji i formuje blok #10. R\u00f3wnie\u017c widzimy, \u017ce do puli dodano 320k transakcji w ci\u0105gu 10 sekundy<br \/>\n01:12 \u2014 blok #10 zosta\u0142 podpisany i wysy\u0142any do innych w\u0119z\u0142\u00f3w do walidacji<br \/>\n01:18 \u2014 zako\u0144czono dzia\u0142anie skryptu demo, kt\u00f3ry wys\u0142a\u0142 1 mln transakcji w 34 sekundy<br \/>\n01:20 \u2014 blok #10 zosta\u0142 zwalidowany i wys\u0142any do g\u0142\u00f3wnego \u0142a\u0144cucha <br \/>\n01:51 \u2014 wszystkie w\u0119z\u0142y otrzyma\u0142y z g\u0142\u00f3wnego \u0142a\u0144cucha informacj\u0119, \u017ce blok #10 zosta\u0142 dodany i zaczynaj\u0105 realizowa\u0107 320k transakcji<br \/>\n02:01 \u2014 pula zosta\u0142a oczyszczona o 320k transakcji, kt\u00f3re zosta\u0142y dodane do bloku #10<br \/>\n02:15 \u2014 w\u0119ze\u0142 submit pobra\u0142 z puli 350k transakcji i formuje blok #11<br \/>\n02:34 \u2014 blok #11 zosta\u0142 podpisany i wysy\u0142any do innych w\u0119z\u0142\u00f3w do walidacji<br \/>\n02:51 \u2014 blok #11 zosta\u0142 zwalidowany i wys\u0142any do g\u0142\u00f3wnego \u0142a\u0144cucha <br \/>\n02:55 \u2014 ostatni w\u0119ze\u0142 wykona\u0142 transakcje z bloku #10<br \/>\n10:59 \u2014 transakcja z dodaniem bloku #9 trwa\u0142a bardzo d\u0142ugo w \u0142a\u0144cuchu g\u0142\u00f3wnym, ale zako\u0144czy\u0142a si\u0119 pomy\u015blnie, a wszystkie w\u0119z\u0142y otrzyma\u0142y o tym informacj\u0119 i zacz\u0119\u0142y realizowa\u0107 350 tys. transakcji.<br \/>\n11:05 \u2014 pula zosta\u0142a oczyszczona o 320 tys. transakcji, kt\u00f3re zosta\u0142y dodane do bloku #11.<br \/>\n12:10 \u2014 wszystkie w\u0119z\u0142y zawieraj\u0105 1 mln 670 tys. transakcji i token\u00f3w.<br \/>\n12:17 \u2014 w\u0119ze\u0142 zg\u0142oszenia pobra\u0142 z puli 330 tys. transakcji i formuje blok #12.<br \/>\n12:32 \u2014 blok #12 zosta\u0142 podpisany i wys\u0142any do innych w\u0119z\u0142\u00f3w do weryfikacji.<br \/>\n12:39 \u2014 blok #12 zosta\u0142 zweryfikowany i wys\u0142any do \u0142a\u0144cucha g\u0142\u00f3wnego. <br \/>\n13:44 \u2014 wszystkie w\u0119z\u0142y otrzyma\u0142y z \u0142a\u0144cucha g\u0142\u00f3wnego informacj\u0119 o tym, \u017ce blok #12 zosta\u0142 dodany i zaczynaj\u0105 stosowa\u0107 330 tys. transakcji.<br \/>\n14:50 \u2014 wszystkie w\u0119z\u0142y zawieraj\u0105 2 mln transakcji i token\u00f3w.<\/p>\n<h3>Test 3<\/h3>\n<p>\nNa pierwszym i drugim serwerze jedna weryfikuj\u0105ca w\u0119ze\u0142 zosta\u0142a zast\u0105piona w\u0119z\u0142em zg\u0142oszenia. <\/p>\n<p><center><div class=\"youtube-placeholder\" data-id=\"w5QHab3heIc\" onclick=\"loadVideo(this)\">\r\n        <img decoding=\"async\" src=\"https:\/\/img.youtube.com\/vi\/w5QHab3heIc\/hqdefault.jpg\" alt=\"Odtwarzaj wideo\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nStan pocz\u0105tkowy: ostatni blok #84; w bazie zapisano 0 transakcji i token\u00f3w.<\/p>\n<p>00:00 \u2014 Uruchomiono 3 skrypty, kt\u00f3re generuj\u0105 i wysy\u0142aj\u0105 po 1 mln transakcji.<br \/>\n01:38 \u2014 stworzono 1 mln transakcji i rozpocz\u0119to przesy\u0142anie do w\u0119z\u0142a zg\u0142oszenia #3.<br \/>\n01:50 \u2014 w\u0119ze\u0142 zg\u0142oszenia #3 pobra\u0142 z puli 330 tys. transakcji i formuje blok #85 (f21). Widzimy r\u00f3wnie\u017c, \u017ce do puli dodano 350 tys. transakcji w ci\u0105gu 10 sek.<br \/>\n01:53 \u2014 stworzono 1 mln transakcji i rozpocz\u0119to przesy\u0142anie do w\u0119z\u0142a zg\u0142oszenia #1.<br \/>\n01:50 \u2014 w\u0119ze\u0142 zg\u0142oszenia #3 pobra\u0142 z puli 330 tys. transakcji i formuje blok #85 (f21). Widzimy r\u00f3wnie\u017c, \u017ce do puli dodano 350 tys. transakcji w ci\u0105gu 10 sek.<br \/>\n02:01 \u2014 w\u0119ze\u0142 zg\u0142oszenia #1 pobra\u0142 z puli 250 tys. transakcji i formuje blok #85 (65e).<br \/>\n02:06 \u2014 blok #85 (f21) zosta\u0142 podpisany i wys\u0142any do innych w\u0119z\u0142\u00f3w do weryfikacji.<br \/>\n02:08 \u2014 zako\u0144czy\u0142 prac\u0119 skrypt-demo serwera #3, kt\u00f3ry przes\u0142a\u0142 1 mln transakcji w ci\u0105gu 30 sekund.<br \/>\n02:14 \u2014 blok #85 (f21) zosta\u0142 zweryfikowany i wys\u0142any do \u0142a\u0144cucha g\u0142\u00f3wnego. <br \/>\n02:19 \u2014 blok #85 (65e) zosta\u0142 podpisany i wys\u0142any do innych w\u0119z\u0142\u00f3w do weryfikacji.<br \/>\n02:22 \u2014 stworzono 1 mln transakcji i rozpocz\u0119to przesy\u0142anie do w\u0119z\u0142a zg\u0142oszenia #2.<br \/>\n02:27 \u2014 blok #85 (65e) zosta\u0142 zweryfikowany i wys\u0142any do \u0142a\u0144cucha g\u0142\u00f3wnego. <br \/>\n02:29 \u2014 w\u0119ze\u0142 zg\u0142oszenia #2 pobra\u0142 z puli 111855 transakcji i formuje blok #85 (256).<br \/>\n02:36 \u2014 blok #85 (256) zosta\u0142 podpisany i wys\u0142any do innych w\u0119z\u0142\u00f3w do weryfikacji.<br \/>\n02:36 \u2014 zako\u0144czy\u0142 prac\u0119 skrypt-demo serwera #1, kt\u00f3ry przes\u0142a\u0142 1 mln transakcji w ci\u0105gu 42,5 sekundy.<br \/>\n02:38 \u2014 blok #85 (256) zosta\u0142 zweryfikowany i wys\u0142any do \u0142a\u0144cucha g\u0142\u00f3wnego.<br \/>\n03:08 \u2014 zako\u0144czy\u0142 prac\u0119 skrypt-demo serwera #2, kt\u00f3ry przes\u0142a\u0142 1 mln transakcji w ci\u0105gu 47 sek. <br \/>\n03:38 \u2014 wszystkie w\u0119z\u0142y otrzyma\u0142y z \u0142a\u0144cucha g\u0142\u00f3wnego informacj\u0119 o tym, \u017ce bloki #85 (f21), #86(65e), #87(256) zosta\u0142y dodane i rozpoczynaj\u0105 stosowanie 330 tys., 250 tys., 111855 transakcji.<br \/>\n03:49 \u2014 pula oczy\u015bci\u0142a si\u0119 o 330k, 250k, 111855 transakcji, kt\u00f3re zosta\u0142y dodane do blok\u00f3w #85 (f21), #86(65e), #87(256)<br \/>\n03:59 \u2014 zg\u0142oszenie w\u0119z\u0142a #1 wzi\u0119\u0142o z puli 888145 transakcji i formuje blok #88 (214), zg\u0142oszenie w\u0119z\u0142a #2 wzi\u0119\u0142o z puli 750k transakcji i formuje blok #88 (50a), zg\u0142oszenie w\u0119z\u0142a #3 wzi\u0119\u0142o z puli 670k transakcji i formuje blok #88 (d3b)<br \/>\n04:44 \u2014 blok #88 (d3b) zosta\u0142 podpisany i wys\u0142any do innych w\u0119z\u0142\u00f3w do walidacji<br \/>\n04:58 \u2014 blok #88 (214) zosta\u0142 podpisany i wys\u0142any do innych w\u0119z\u0142\u00f3w do walidacji<br \/>\n05:11 \u2014 blok #88 (50a) zosta\u0142 podpisany i wys\u0142any do innych w\u0119z\u0142\u00f3w do walidacji<br \/>\n05:11 \u2014 blok #85 (d3b) zosta\u0142 zwalidowany i wys\u0142any do g\u0142\u00f3wnego \u0142a\u0144cucha <br \/>\n05:36 \u2014 blok #85 (214) zosta\u0142 zwalidowany i wys\u0142any do g\u0142\u00f3wnego \u0142a\u0144cucha <br \/>\n05:43 \u2014 wszystkie w\u0119z\u0142y otrzyma\u0142y z g\u0142\u00f3wnego \u0142a\u0144cucha informacj\u0119, \u017ce bloki #88 (d3b), #89(214) zosta\u0142y dodane i zaczynaj\u0105 stosowa\u0107 670k, 750k transakcji<br \/>\n06:50 \u2014 z powodu przerwania po\u0142\u0105czenia blok #85 (50a) nie zosta\u0142 zwalidowany<br \/>\n06:55 \u2014 zg\u0142oszenie w\u0119z\u0142a #2 wzi\u0119\u0142o z puli 888145 transakcji i formuje blok #90 (50a)<br \/>\n08:14 \u2014 blok #90 (50a) zosta\u0142 podpisany i wys\u0142any do innych w\u0119z\u0142\u00f3w do walidacji<br \/>\n09:04 \u2014 blok #90 (50a) zosta\u0142 zwalidowany i wys\u0142any do g\u0142\u00f3wnego \u0142a\u0144cucha <br \/>\n11:23 \u2014 wszystkie w\u0119z\u0142y otrzyma\u0142y z g\u0142\u00f3wnego \u0142a\u0144cucha informacj\u0119, \u017ce blok #90 (50a) zosta\u0142 dodany, i zaczynaj\u0105 stosowa\u0107 888145 transakcji. W mi\u0119dzyczasie serwer #3 ju\u017c zastosowa\u0142 transakcje z blok\u00f3w #88 (d3b), #89(214)<br \/>\n12:11 \u2014 wszystkie pule s\u0105 puste<br \/>\n13:41 \u2014 wszystkie w\u0119z\u0142y serwera #3 zawieraj\u0105 3 miliony transakcji i token\u00f3w<br \/>\n14:35 \u2014 wszystkie w\u0119z\u0142y serwera #1 zawieraj\u0105 3 miliony transakcji i token\u00f3w<br \/>\n19:24 \u2014 wszystkie w\u0119z\u0142y serwera #2 zawieraj\u0105 3 miliony transakcji i token\u00f3w <\/p>\n<h2>Przeszkody<\/h2>\n<p>\nPodczas rozwoju Plasma Cash napotkali\u015bmy nast\u0119puj\u0105ce problemy, kt\u00f3re stopniowo rozwi\u0105zali\u015bmy i rozwi\u0105zujemy:<\/p>\n<p><b>1.<\/b> Konflikt interakcji r\u00f3\u017cnych funkcji systemu. Na przyk\u0142ad, funkcja dodawania transakcji do puli blokowa\u0142a dzia\u0142anie zg\u0142osze\u0144 i walidacji blok\u00f3w, i odwrotnie, co prowadzi\u0142o do spadku pr\u0119dko\u015bci.<\/p>\n<p><b>2. <\/b>Nie by\u0142o od razu jasne, w jaki spos\u00f3b wys\u0142a\u0107 ogromn\u0105 ilo\u015b\u0107 transakcji i jednocze\u015bnie zminimalizowa\u0107 koszty przesy\u0142ania danych.<\/p>\n<p><b>3. <\/b>Nie by\u0142o jasno okre\u015blone, w jaki spos\u00f3b i gdzie przechowywa\u0107 dane, aby osi\u0105gn\u0105\u0107 wysokie wyniki.<\/p>\n<p><b>4. <\/b>Nie by\u0142o jasne, jak zorganizowa\u0107 sie\u0107 mi\u0119dzy w\u0119z\u0142ami, poniewa\u017c rozmiar bloku z 1 milionem transakcji zajmuje oko\u0142o 100 MB.<\/p>\n<p><b>5.<\/b> Praca w trybie jednow\u0105tkowym przerywa po\u0142\u0105czenie mi\u0119dzy w\u0119z\u0142ami podczas d\u0142ugich oblicze\u0144 (na przyk\u0142ad budowa drzewa Merkle i obliczanie jego hasza).<\/p>\n<h2>Jak sobie z tym wszystkim poradzili\u015bmy?<\/h2>\n<p>\nPierwsza wersja w\u0119z\u0142a Plasma Cash by\u0142a pewnym kombajnem, kt\u00f3ry m\u00f3g\u0142 wykonywa\u0107 wszystko jednocze\u015bnie: przyjmowa\u0107 transakcje, przesy\u0142a\u0107 i walidowa\u0107 bloki, a tak\u017ce udost\u0119pnia\u0107 API do dost\u0119pu do danych. Poniewa\u017c NodeJS jest z za\u0142o\u017cenia jednow\u0105tkowy, ci\u0119\u017cka funkcja obliczania drzewa Merkle blokowa\u0142a funkcj\u0119 dodawania transakcji. Zobaczyli\u015bmy dwa sposoby na rozwi\u0105zanie tego problemu:<\/p>\n<p><b>1. <\/b>Uruchomi\u0107 kilka proces\u00f3w NodeJS, z kt\u00f3rych ka\u017cdy wykonuje okre\u015blone funkcje.<\/p>\n<p><b>2. <\/b>Zastosowa\u0107 worker_threads i przenie\u015b\u0107 wykonanie cz\u0119\u015bci kodu do w\u0105tk\u00f3w.<\/p>\n<p>Ostatecznie skorzystali\u015bmy z obu opcji jednocze\u015bnie: logicznie podzielili\u015bmy jeden w\u0119ze\u0142 na 3 cz\u0119\u015bci, kt\u00f3re mog\u0105 dzia\u0142a\u0107 oddzielnie, ale jednocze\u015bnie synchronicznie.<\/p>\n<p><b>1.<\/b> W\u0119ze\u0142 do przesy\u0142ania, kt\u00f3ry przyjmuje transakcje do puli i zajmuje si\u0119 tworzeniem blok\u00f3w.<\/p>\n<p><b>2.<\/b> W\u0119ze\u0142 waliduj\u0105cy, kt\u00f3ry sprawdza wa\u017cno\u015b\u0107 innych w\u0119z\u0142\u00f3w.<\/p>\n<p><b>3. <\/b>W\u0119ze\u0142 API \u2014 udost\u0119pnia API do dost\u0119pu do danych.<\/p>\n<p>Do ka\u017cdego w\u0119z\u0142a mo\u017cna pod\u0142\u0105czy\u0107 si\u0119 przez unix socket za pomoc\u0105 cli.<\/p>\n<p>Ci\u0119\u017ckie operacje, takie jak obliczanie drzewa Merkle, przenie\u015bli\u015bmy do osobnego w\u0105tku.<\/p>\n<p>W ten spos\u00f3b osi\u0105gn\u0119li\u015bmy normalne dzia\u0142anie wszystkich funkcji Plasma Cash jednocze\u015bnie i bez zak\u0142\u00f3ce\u0144.<\/p>\n<p>Gdy system funkcjonalnie zadzia\u0142a\u0142, zacz\u0119li\u015bmy testowa\u0107 szybko\u015b\u0107 i, niestety, uzyskali\u015bmy niezadowalaj\u0105ce wyniki: 5 000 transakcji na sekund\u0119 i do 50 000 transakcji w bloku. Musieli\u015bmy dowiedzie\u0107 si\u0119, co zosta\u0142o zaimplementowane niepoprawnie.<\/p>\n<p>Na pocz\u0105tku zacz\u0119li\u015bmy testowa\u0107 mechanizm komunikacji z Plasma Cash, aby zobaczy\u0107 maksymalne mo\u017cliwo\u015bci systemu. Wcze\u015bniej pisali\u015bmy, \u017ce w\u0119ze\u0142 Plasma Cash udost\u0119pnia interfejs unix socket. Pocz\u0105tkowo by\u0142 on tekstowy. Obiekty JSON by\u0142y przesy\u0142ane, korzystaj\u0105c z `JSON.parse()` i `JSON.stringify()`. <\/p>\n<pre><code class=\"plaintext\">{\n  \"action\": \"sendTransaction\",\n  \"payload\":{\n    \"prevHash\": \"0x8a88cc4217745fd0b4eb161f6923235da10593be66b841d47da86b9cd95d93e0\",\n    \"prevBlock\": 41,\n    \"tokenId\": \"57570139642005649136210751546585740989890521125187435281313126554130572876445\",\n    \"newOwner\": \"0x200eabe5b26e547446ae5821622892291632d4f4\",\n    \"type\": \"pay\",\n    \"data\": \"\",\n    \"signature\": \"0xd1107d0c6df15e01e168e631a386363c72206cb75b233f8f3cf883134854967e1cd9b3306cc5c0ce58f0a7397ae9b2487501b56695fe3a3c90ec0f61c7ea4a721c\"\n  }\n}\n<\/code><\/pre>\n<p>\nZmierzono pr\u0119dko\u015b\u0107 przesy\u0142ania takich obiekt\u00f3w i uzyskano ~ 130k na sekund\u0119. Pr\u00f3bowali\u015bmy zast\u0105pi\u0107 standardowe funkcje pracy z json, ale wydajno\u015b\u0107 si\u0119 nie poprawi\u0142a. Musi by\u0107, \u017ce silnik V8 jest dobrze zoptymalizowany do tych operacji.<\/p>\n<p>Praca z transakcjami, tokenami i blokami odbywa\u0142a si\u0119 przez klasy. Podczas tworzenia takich klas wydajno\u015b\u0107 spad\u0142a dwukrotnie, co \u015bwiadczy o tym, \u017ce OOP nam nie odpowiada. Musieli\u015bmy przepisa\u0107 wszystko na czysto funkcyjny spos\u00f3b.<\/p>\n<h2>Zapis do bazy<\/h2>\n<p>\nPocz\u0105tkowo wybrano Redis jako jedno z najbardziej wydajnych rozwi\u0105za\u0144, kt\u00f3re spe\u0142nia nasze wymagania: przechowywanie w formacie key-value, praca z tabelami haszuj\u0105cymi i zbiorami. Uruchomili\u015bmy redis-benchmark i uzyskali\u015bmy ~80k operacji na sekund\u0119 w trybie 1 pipelining.<\/p>\n<p>Aby osi\u0105gn\u0105\u0107 wysok\u0105 wydajno\u015b\u0107, skonfigurowali\u015bmy Redis bardziej precyzyjnie: <\/p>\n<ul>\n<li>Ustawili\u015bmy po\u0142\u0105czenie unix socket.<\/li>\n<li>Wy\u0142\u0105czyli\u015bmy zapisywanie stanu na dysk (dla niezawodno\u015bci mo\u017cna skonfigurowa\u0107 replikacj\u0119 i ju\u017c w osobnym Redisie robi\u0107 zapisywanie na dysk).<\/li>\n<\/ul>\n<p>\nW Redisie pula to tabela haszuj\u0105ca, poniewa\u017c potrzebujemy mo\u017cliwo\u015bci pobierania wszystkich transakcji jednym zapytaniem oraz usuwania transakcji pojedynczo. Pr\u00f3bowali\u015bmy u\u017cywa\u0107 zwyk\u0142ej listy, ale dzia\u0142a\u0142a wolniej podczas \u0142adowania ca\u0142ej listy. <\/p>\n<p>Przy u\u017cyciu standardowej biblioteki NodeJS Redis uzyskano wydajno\u015b\u0107 na poziomie 18k transakcji na sekund\u0119. Pr\u0119dko\u015b\u0107 spad\u0142a dziewi\u0119ciokrotnie. <\/p>\n<p>Poniewa\u017c benchmark wskazywa\u0142, \u017ce mo\u017cliwo\u015bci s\u0105 wyra\u017anie pi\u0119ciokrotnie wi\u0119ksze, zacz\u0119li\u015bmy optymalizowa\u0107. Zmienili\u015bmy bibliotek\u0119 na ioredis i uzyskali\u015bmy wydajno\u015b\u0107 ju\u017c 25k na sekund\u0119. Transakcje dodawali\u015bmy pojedynczo, u\u017cywaj\u0105c polecenia `hset`. W ten spos\u00f3b generowali\u015bmy wiele zapyta\u0144 do Redis. Pojawi\u0142 si\u0119 pomys\u0142, aby \u0142\u0105czy\u0107 transakcje w paczki i wysy\u0142a\u0107 je jednym poleceniem `hmset`. Wynik \u2014 32k na sekund\u0119. <\/p>\n<p>Z kilku powod\u00f3w, kt\u00f3re opiszemy poni\u017cej, z danymi pracujemy przy u\u017cyciu `Buffer` i, jak si\u0119 okaza\u0142o, je\u015bli przet\u0142umaczy\u0107 go na tekst (`buffer.toString(&#8216;hex&#8217;)`) przed zapisaniem, mo\u017cna uzyska\u0107 dodatkow\u0105 wydajno\u015b\u0107. W ten spos\u00f3b uda\u0142o si\u0119 zwi\u0119kszy\u0107 pr\u0119dko\u015b\u0107 do 35k na sekund\u0119. Na ten moment postanowili\u015bmy wstrzyma\u0107 dalsz\u0105 optymalizacj\u0119.<\/p>\n<p>Musieli\u015bmy przej\u015b\u0107 na protok\u00f3\u0142 binarny, poniewa\u017c:<\/p>\n<p><b>1. <\/b>System cz\u0119sto oblicza hashe, podpisy itp., a do tego potrzebuje danych w `Buffer.<\/p>\n<p><b>2.<\/b> Podczas przesy\u0142ania danych mi\u0119dzy us\u0142ugami dane binarne zajmuj\u0105 mniej miejsca ni\u017c tekst. Na przyk\u0142ad, przy wysy\u0142aniu bloku z 1 milionem transakcji, dane w tek\u015bcie mog\u0105 zajmowa\u0107 ponad 300 megabajt\u00f3w.<\/p>\n<p><b>3.<\/b> Ci\u0105g\u0142a konwersja danych wp\u0142ywa na wydajno\u015b\u0107.<\/p>\n<p>Dlatego na podstawie wzi\u0119li\u015bmy nasz w\u0142asny binarny protok\u00f3\u0142 przechowywania i przesy\u0142ania danych, opracowany na podstawie znakomitej biblioteki `binary-data`.<\/p>\n<p>W rezultacie otrzymali\u015bmy nast\u0119puj\u0105ce struktury danych:<\/p>\n<h3> \u2014 Transakcja<\/h3>\n<p><\/p>\n<pre><code class=\"plaintext\">  ```json\n  {\n    prevHash: BD.types.buffer(20),\n    prevBlock: BD.types.uint24le,\n    tokenId: BD.types.string(null),\n    type: BD.types.uint8,\n    newOwner: BD.types.buffer(20),\n    dataLength: BD.types.uint24le,\n    data: BD.types.buffer(({current}) =&gt; current.dataLength),\n    signature: BD.types.buffer(65),\n    hash: BD.types.buffer(32),\n    blockNumber: BD.types.uint24le,\n    timestamp: BD.types.uint48le,\n  }\n  ```\n<\/code><\/pre>\n<p><\/p>\n<h3> \u2014 Token<\/h3>\n<p><\/p>\n<pre><code class=\"plaintext\">  ```json\n  {\n    id: BD.types.string(null),\n    owner: BD.types.buffer(20),\n    block: BD.types.uint24le,\n    amount: BD.types.string(null),\n  }\n  ```\n<\/code><\/pre>\n<p><\/p>\n<h3> \u2014 Blok<\/h3>\n<p><\/p>\n<pre><code class=\"plaintext\">  ```json\n  {\n    number: BD.types.uint24le,\n    merkleRootHash: BD.types.buffer(32),\n    signature: BD.types.buffer(65),\n    countTx: BD.types.uint24le,\n    transactions: BD.types.array(Transaction.Protocol, ({current}) =&gt; current.countTx),\n    timestamp: BD.types.uint48le,\n  }\n  ```\n<\/code><\/pre>\n<p>\nZwyk\u0142ymi poleceniami `BD.encode(block, Protocol).slice();` i ` BD.decode(buffer, Protocol)` przekszta\u0142camy dane do `Buffer`, aby zapisa\u0107 je w Redis lub przes\u0142a\u0107 innemu w\u0119z\u0142owi i wyci\u0105gn\u0105\u0107 dane z powrotem.<\/p>\n<p>Mamy r\u00f3wnie\u017c 2 binarne protoko\u0142y do przesy\u0142ania danych mi\u0119dzy us\u0142ugami:<\/p>\n<p><i> \u2014 Protok\u00f3\u0142 do interakcji z Plasma Node poprzez gniazdo unixowe<\/i><\/p>\n<pre><code class=\"plaintext\">  ```json\n  {\n    type: BD.types.uint8,\n    messageId: BD.types.uint24le,\n    error: BD.types.uint8,\n    length: BD.types.uint24le,\n    payload: BD.types.buffer(({node}) =&gt; node.length)\n  }\n  ```\n<\/code><\/pre>\n<p>\n gdzie:<\/p>\n<ul>\n<li> <b>`type`<\/b> \u2014 dzia\u0142anie, kt\u00f3re nale\u017cy wykona\u0107, na przyk\u0142ad 1 \u2014 sendTransaction, 2 \u2014 getTransaction;<\/li>\n<li> <b>`payload`<\/b> \u2014 dane, kt\u00f3re nale\u017cy przekaza\u0107 do odpowiedniej funkcji;<\/li>\n<li> <b>`messageId`<\/b> \u2014 identyfikator wiadomo\u015bci, aby mo\u017cna by\u0142o zidentyfikowa\u0107 odpowied\u017a. <\/li>\n<\/ul>\n<p>\n<i> \u2014 Protok\u00f3\u0142 interakcji mi\u0119dzy w\u0119z\u0142ami<\/i><\/p>\n<pre><code class=\"plaintext\">  ```json\n  {\n    code: BD.types.uint8,\n    versionProtocol: BD.types.uint24le,\n    seq: BD.types.uint8,\n    countChunk: BD.types.uint24le,\n    chunkNumber: BD.types.uint24le,\n    length: BD.types.uint24le,\n    payload: BD.types.buffer(({node}) =&gt; node.length)\n  }\n  ```\n<\/code><\/pre>\n<p>\n gdzie:<\/p>\n<ul>\n<li> <b>`code`<\/b> \u2014 kod wiadomo\u015bci, na przyk\u0142ad 6 \u2014 PREPARE_NEW_BLOCK, 7 \u2014 BLOCK_VALID, 8 \u2014 BLOCK_COMMIT;<\/li>\n<li> <b>`versionProtocol`<\/b> \u2014 wersja protoko\u0142u, poniewa\u017c w sieci mog\u0105 by\u0107 uruchomione w\u0119z\u0142y z r\u00f3\u017cnymi wersjami i mog\u0105 dzia\u0142a\u0107 w r\u00f3\u017cny spos\u00f3b;<\/li>\n<li> <b>`seq`<\/b> \u2014 identyfikator wiadomo\u015bci;<\/li>\n<li> <b>`countChunk`<\/b> i <b>`chunkNumber`<\/b> s\u0105 potrzebne do podzia\u0142u du\u017cych wiadomo\u015bci;<\/li>\n<li> <b>`length`<\/b> i <b>`payload`<\/b> d\u0142ugo\u015b\u0107 i same dane.<\/li>\n<\/ul>\n<p>\nPoniewa\u017c wcze\u015bniej zdefiniowali\u015bmy typy danych, ko\u0144cowy system dzia\u0142a znacznie szybciej ni\u017c biblioteka `rlp` z Ethereum. Niestety, na razie nie uda\u0142o nam si\u0119 z niej zrezygnowa\u0107, poniewa\u017c musimy poprawi\u0107 inteligentny kontrakt, co planujemy zrobi\u0107 w przysz\u0142o\u015bci.<\/p>\n<p>Je\u015bli uda\u0142o nam si\u0119 osi\u0105gn\u0105\u0107 pr\u0119dko\u015b\u0107 <b>35 000<\/b> transakcji na sekund\u0119, musimy tak\u017ce przetwarza\u0107 je w optymalnym czasie. Poniewa\u017c przybli\u017cony czas formowania bloku wynosi 30 sekund, musimy uwzgl\u0119dni\u0107 w bloku <b>1 000 000<\/b> transakcji, co oznacza przesy\u0142anie ponad <b>100<\/b> MB danych. <\/p>\n<p>Pocz\u0105tkowo u\u017cyli\u015bmy biblioteki `ethereumjs-devp2p` do komunikacji w\u0119z\u0142\u00f3w, ale nie radzi\u0142a sobie z tak\u0105 ilo\u015bci\u0105 danych. W rezultacie skorzystali\u015bmy z biblioteki `ws` i skonfigurowali\u015bmy przesy\u0142anie danych binarnych przez websocket. Oczywi\u015bcie napotkali\u015bmy r\u00f3wnie\u017c problemy przy przesy\u0142aniu du\u017cych pakiet\u00f3w danych, ale podzielili\u015bmy je na fragmenty i teraz tych problem\u00f3w nie ma.<\/p>\n<p>Formowanie drzewa Merkle i obliczanie hasha <b>1 000 000<\/b> transakcji zajmuje oko\u0142o<b> 10<\/b> sekund ci\u0105g\u0142ego obliczania. W tym czasie po\u0142\u0105czenie z wszystkimi w\u0119z\u0142ami zd\u0105\u017cy\u0142o si\u0119 zerwa\u0107. Zdecydowano si\u0119 przenie\u015b\u0107 te obliczenia do osobnego w\u0105tku.<\/p>\n<h2>Wnioski:<\/h2>\n<p>\nTak naprawd\u0119 nasze wnioski nie s\u0105 nowe, ale z jakiego\u015b powodu wielu specjalist\u00f3w zapomina o nich podczas tworzenia. <\/p>\n<ul>\n<li>Wykorzystanie programowania funkcyjnego zamiast programowania obiektowego zwi\u0119ksza wydajno\u015b\u0107.<\/li>\n<li>Monolit jest gorszy ni\u017c architektura serwisowa dla wydajnego systemu na NodeJS.<\/li>\n<li>Wykorzystanie `worker_threads` do ci\u0119\u017ckich oblicze\u0144 poprawia responsywno\u015b\u0107 systemu, szczeg\u00f3lnie przy operacjach i\/o.<\/li>\n<li>Unix socket jest bardziej stabilny i szybszy ni\u017c zapytania http.<\/li>\n<li>Je\u015bli trzeba szybko przesy\u0142a\u0107 du\u017ce dane przez sie\u0107, lepiej skorzysta\u0107 z websocket\u00f3w i wysy\u0142a\u0107 dane binarne podzielone na fragmenty, kt\u00f3re mo\u017cna przes\u0142a\u0107 ponownie, je\u015bli nie dotr\u0105, a nast\u0119pnie po\u0142\u0105czy\u0107 w jedn\u0105 wiadomo\u015b\u0107.<\/li>\n<\/ul>\n<p>\nZapraszamy do odwiedzenia <b>GitHub<\/b> projekcie: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/opporty-com\/Plasma-Cash\/tree\/new-version\">https:\/\/github.com\/opporty-com\/Plasma-Cash\/tree\/new-version<\/a><\/noindex><\/p>\n<p>Artyku\u0142 zosta\u0142 napisany we wsp\u00f3\u0142pracy z <i>Aleksandrem Naszivanem<\/i>, starszym programist\u0105 <noindex><a rel=\"nofollow\" href=\"https:\/\/clever-solution.com\/\">Clever Solution Inc<\/a><\/noindex>.<br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/471096\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0411\u043b\u043e\u043a\u0447\u0435\u0439\u043d \u2014 \u0438\u043d\u043d\u043e\u0432\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043e\u0431\u0435\u0449\u0430\u044e\u0449\u0430\u044f \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u0441\u0444\u0435\u0440\u044b \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u043e\u0439 \u0436\u0438\u0437\u043d\u0438. \u041e\u043d\u0430 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b \u0432 \u0446\u0438\u0444\u0440\u043e\u0432\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u0444\u0438\u043d\u0430\u043d\u0441\u043e\u0432\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u0441\u043d\u0438\u0436\u0430\u0435\u0442 \u0438\u0445 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 DAPP \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043e\u0432 \u0432 \u0434\u0435\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0442\u044f\u0445. \u0423\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u043c\u043d\u043e\u0433\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0438 \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0435 \u0441\u0444\u0435\u0440\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d, \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u043c, \u0447\u0442\u043e \u044d\u0442\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":29146,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-38856","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0411\u043b\u043e\u043a\u0447\u0435\u0439\u043d \u2014 \u0438\u043d\u043d\u043e\u0432\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043e\u0431\u0435\u0449\u0430\u044e\u0449\u0430\u044f \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u0441\u0444\u0435\u0440\u044b \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u043e\u0439 \u0436\u0438\u0437\u043d\u0438.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0435\u0441\u0442: \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u0438 \u0432 \u042d\u0444\u0438\u0440\u0438\u0443\u043c\u0435 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0411\u043b\u043e\u043a\u0447\u0435\u0439\u043d \u2014 \u0438\u043d\u043d\u043e\u0432\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043e\u0431\u0435\u0449\u0430\u044e\u0449\u0430\u044f \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u0441\u0444\u0435\u0440\u044b \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u043e\u0439 \u0436\u0438\u0437\u043d\u0438.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:26:22+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:26:22+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Publiczny test: rozwi\u0105zanie dla prywatno\u015bci i skalowalno\u015bci w Ethereum | ProHoster","description":"Blockchain to innowacyjna technologia, kt\u00f3ra obiecuje poprawi\u0107 wiele dziedzin \u017cycia ludzkiego.","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0442\u0435\u0441\u0442: \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u0438 \u0432 \u042d\u0444\u0438\u0440\u0438\u0443\u043c\u0435 | ProHoster","og:description":"\u0411\u043b\u043e\u043a\u0447\u0435\u0439\u043d \u2014 \u0438\u043d\u043d\u043e\u0432\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f, \u043e\u0431\u0435\u0449\u0430\u044e\u0449\u0430\u044f \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u0441\u0444\u0435\u0440\u044b \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u043e\u0439 \u0436\u0438\u0437\u043d\u0438.","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:26:22+00:00","article:modified_time":"2019-10-31T19:26:22+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"38856","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-23 23:42:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 12:15:36","updated":"2026-01-23 23:42:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/38856","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=38856"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/38856\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media\/29146"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=38856"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=38856"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=38856"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}