{"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\/da\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume","title":{"rendered":"Offentlig test: l\u00f8sning til privatliv og skalerbarhed i Ethereum","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><b>Blockchain<\/b> \u2014 en innovativ teknologi, der lover at forbedre mange omr\u00e5der af menneskelivet. Den transporterer reale processer og produkter ind i det digitale rum, sikrer hastighed og p\u00e5lidelighed i finansielle transaktioner, reducerer omkostningerne ved dem, og g\u00f8r det muligt at skabe moderne DAPP-applikationer med brug af intelligente kontrakter i decentraliserede netv\u00e6rk.<\/p>\n<p>I betragtning af de mange fordele og forskellige anvendelsesomr\u00e5der, kan det synes m\u00e6rkeligt, at denne lovende teknologi endnu ikke har tr\u00e6ngt ind i alle brancher. Problemet er, at moderne decentraliserede blockchains mangler skalerbarhed. Ethereum behandler omkring 20 transaktioner i sekundet, hvilket er utilstr\u00e6kkeligt til at im\u00f8dekomme behovene i nutidens dynamiske erhvervsliv. Samtidig t\u00f8ver virksomheder, der anvender blockchain-teknologi, med at slippe Ethereum p\u00e5 grund af dens h\u00f8je grad af beskyttelse mod hacking og netv\u00e6rksfejl.<\/p>\n<p>For at sikre decentralisering, sikkerhed og skalerbarhed i blockchain og dermed l\u00f8se Skaleringsdilemmaet, <noindex><a rel=\"nofollow\" href=\"https:\/\/opporty.com\/\">Opporty<\/a><\/noindex> har teamet udviklet Plasma Cash \u2014 en underk\u00e6de, der best\u00e5r af en smart kontrakt og et privat netv\u00e6rk baseret p\u00e5 Node.js, som periodisk overf\u00f8rer sin tilstand til rodk\u00e6den (Ethereum).<\/p>\n<p><img decoding=\"async\" alt=\"Offentlig test: l\u00f8sning til privatliv og skalerbarhed i 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>N\u00f8gleprocesser i Plasma Cash<\/h2>\n<p>\n<b>1. <\/b>Brugeren kalder smart kontraktens `deposit`-funktion ved at videregive det bel\u00f8b i ETH, som han \u00f8nsker at placere i Plasma Cash-tokenet. Smart kontraktens funktion skaber tokenet og genererer en begivenhed om dette.<\/p>\n<p><b>2. <\/b>Plasma Cash-noder, der er tilmeldt begivenhederne fra smart kontrakten, modtager begivenheden om oprettelsen af indbetalingen og tilf\u00f8jer transaktionen om oprettelsen af tokenet til puljen.<\/p>\n<p><b>3. <\/b>Periodisk tager s\u00e6rlige Plasma Cash-noder alle transaktioner fra puljen (op til 1 million) og danner en blok ud fra dem, beregner Merkle-tr\u00e6et og dermed hash'en. Denne blok sendes til de andre noder til verifikation. Noderne kontrollerer, om Merkle-hash'en er gyldig, og om transaktionerne er gyldige (for eksempel, om afsenderen af tokenet er dens ejer). Efter verifikationen af blokken kalder noden smart kontraktens `submitBlock`-funktion, som gemmer bloknummeret og Merkle-hash'en i rodk\u00e6den. Smart kontrakten genererer en begivenhed om den succesfulde tilf\u00f8jelse af blokken. Transaktionerne fjernes fra puljen. <\/p>\n<p><b>4. <\/b>Noder, der modtager begivenheden om block submission, begynder at anvende de transaktioner, der er blevet tilf\u00f8jet til blocket.<\/p>\n<p><b>5. <\/b>P\u00e5 et tidspunkt \u00f8nsker ejer (eller ikke ejer) af tokenet at tr\u00e6kke det tilbage fra Plasma Cash. For dette kalder han funktionen `startExit`, og sender de seneste 2 transaktioner om tokenet, som bekr\u00e6fter, at han er ejer af tokenet. Smartkontrakten bruger Merkle-hash for at verificere, at transaktionerne findes i blokkene og sender tokenet til at blive trukket tilbage, hvilket vil ske om to uger.<\/p>\n<p><b>6. <\/b>Hvis tokenudtr\u00e6kningen skete med overtr\u00e6delser (tokenet blev brugt efter proceduren for udtr\u00e6kning startede, eller tokenet var allerede andres f\u00f8r udtr\u00e6kning), kan tokenets ejer anf\u00e6gte udtr\u00e6kningen inden for to uger.<\/p>\n<p><img decoding=\"async\" alt=\"Offentlig test: l\u00f8sning til privatliv og skalerbarhed i Ethereum\" src=\"\/wp-content\/uploads\/2019\/10\/0626ca6b010eb847175dbfb0b6d7b357.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>Privatliv opn\u00e5s p\u00e5 to m\u00e5der<\/h2>\n<p>\n<b>1. <\/b>Rodek\u00e6den ved ikke noget om de transaktioner, der dannes og sendes inden for den underliggende k\u00e6de. Information om, hvem der indsatte og trak ETH ind\/ud af Plasma Cash, forbliver offentlig.<\/p>\n<p><b>2. <\/b>Den underliggende k\u00e6de muligg\u00f8r anonyme transaktioner ved at bruge zk-SNARKs.<\/p>\n<h2>Teknologisk stack<\/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>Testning <\/h2>\n<p>\nVed udviklingen af Plasma Cash testede vi systemets hastighed og opn\u00e5ede f\u00f8lgende resultater:<\/p>\n<ul>\n<li>op til 35.000 transaktioner pr. sekund tilf\u00f8jes til puljen;<\/li>\n<li>op til 1.000.000 transaktioner kan gemmes i en blok.<\/li>\n<\/ul>\n<p>\nTestene blev udf\u00f8rt p\u00e5 de f\u00f8lgende 3 servere:<\/p>\n<p><i>1. Intel Core i7-6700 Quad-Core Skylake inkl. NVMe SSD \u2014 512 GB, 64 GB DDR4 RAM<\/i><br \/>\n 3 validerende Plasma Cash noder blev opsat.<\/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 En Ropsten testnet ETH node blev opsat.<br \/>\n 3 validerende Plasma Cash noder blev opsat.<\/p>\n<p><i>3. Intel Core i9-9900K Octa-Core inkl. NVMe SSD \u2014 1 TB, 64 GB DDR4 RAM<\/i><br \/>\n 1 submit Plasma Cash node blev opsat.<br \/>\n 3 validerende Plasma Cash noder blev opsat.<br \/>\n Der blev k\u00f8rt en test for at tilf\u00f8je transaktioner til Plasma Cash netv\u00e6rket.<\/p>\n<p><b>I alt: <\/b>10 Plasma Cash noder i et privat netv\u00e6rk.<\/p>\n<h3>Test 1<\/h3>\n<p>\nDer er en gr\u00e6nse p\u00e5 1 million transaktioner i en blok. Derfor bliver 1 million transaktioner fordelt p\u00e5 2 blokke (da systemet n\u00e5r at tage nogle transaktioner og indsende dem, mens de sendes).<\/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=\"Afspil video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nUrsprungligt tilstand: sidste blok #7; databasen gemte 1 million transaktioner og tokens.<\/p>\n<p>00:00 \u2014 start af script til generation af transaktioner<br \/>\n01:37 \u2014 1 million transaktioner er oprettet, og sending til noden er begyndt<br \/>\n01:46 \u2014 submit noden tog 240k transaktioner fra puljen og danner blok #8. Vi ser ogs\u00e5, at 320k transaktioner tilf\u00f8jes til puljen p\u00e5 10 sekunder<br \/>\n01:58 \u2014 blok #8 er underskrevet og sendt til validering<br \/>\n02:03 \u2014 blok #8 er blevet valideret, og funktionen `submitBlock` i smartkontrakten er blevet kaldt med Merkle-hash og bloknummeret<br \/>\n02:10 \u2014 demo-scriptet er f\u00e6rdigt og har sendt 1 million transaktioner p\u00e5 32 sekunder<br \/>\n02:33 \u2014 noderne begyndte at modtage information om, at blok #8 er blevet tilf\u00f8jet til den rod k\u00e6de og begyndte at behandle 240.000 transaktioner<br \/>\n02:40 \u2014 240.000 transaktioner blev fjernet fra puljen, som allerede er i blok #8<br \/>\n02:56 \u2014 submit-noden tog de resterende 760.000 transaktioner fra puljen og begyndte at beregne Merkle-hash og signere blok #9<br \/>\n03:20 \u2014 alle noder indeholder 1.240.000 transaktioner og tokens<br \/>\n03:35 \u2014 blok #9 er blevet signeret og sendes til validering i andre noder <br \/>\n03:41 \u2014 der opstod en netv\u00e6rksfejl<br \/>\n04:40 \u2014 validering af blok #9 stoppede p\u00e5 grund af timeout<br \/>\n04:54 \u2014 submit-noden tog de resterende 760.000 transaktioner fra puljen og begyndte at beregne Merkle-hash og signere blok #9<br \/>\n05:32 \u2014 blok #9 er blevet signeret og sendes til validering i andre noder<br \/>\n05:53 \u2014 blok #9 er blevet valideret og sendt til den rod k\u00e6de<br \/>\n06:17 \u2014 noderne begyndte at modtage information om, at blok #9 er blevet tilf\u00f8jet til den rod k\u00e6de, og de begyndte at behandle 760.000 transaktioner<br \/>\n06:47 \u2014 puljen er blevet renset for transaktioner, der er i blok #9<br \/>\n09:06 \u2014 alle noder indeholder 2 millioner transaktioner og tokens<\/p>\n<h3>Test 2<\/h3>\n<p>\nDer er en gr\u00e6nse p\u00e5 350.000 for blokken. Resultatet er 3 blokke.<\/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=\"Afspil video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nStarttilstand: den sidste blok #9; der er gemt 2 millioner transaktioner og tokens i databasen<\/p>\n<p>00:00 \u2014 scriptet til generering af transaktioner er allerede startet<br \/>\n00:44 \u2014 der er oprettet 1 million transaktioner, og sendingen til noden er startet<br \/>\n00:56 \u2014 submit-noden tog 320.000 transaktioner fra puljen og danner blok #10. Vi ser ogs\u00e5, at 320.000 transaktioner tilf\u00f8jes til puljen p\u00e5 10 sekunder<br \/>\n01:12 \u2014 blok #10 er blevet signeret og sendes til de andre noder til validering<br \/>\n01:18 \u2014 demo-scriptet er f\u00e6rdigt og har sendt 1 million transaktioner p\u00e5 34 sekunder<br \/>\n01:20 \u2014 blok #10 er blevet valideret og sendt til den rod k\u00e6de <br \/>\n01:51 \u2014 alle noder har modtaget information fra den rod k\u00e6de om, at blok #10 er blevet tilf\u00f8jet, og de begynder at anvende 320.000 transaktioner<br \/>\n02:01 \u2014 puljen er blevet renset for 320.000 transaktioner, der blev tilf\u00f8jet til blok #10<br \/>\n02:15 \u2014 submit-noden tog 350.000 transaktioner fra puljen og danner blok #11<br \/>\n02:34 \u2014 blok #11 er blevet signeret og sendes til de andre noder til validering<br \/>\n02:51 \u2014 blok #11 er blevet valideret og sendt til den rod k\u00e6de <br \/>\n02:55 \u2014 den sidste node har udf\u00f8rt transaktionerne fra blok #10<br \/>\n10:59 \u2014 meget lang tid brugte den rod k\u00e6de til at udf\u00f8re transaktionen med submission af blok #9, men den blev gennemf\u00f8rt, og alle noder fik information om det og begyndte at udf\u00f8re 350k transaktioner<br \/>\n11:05 \u2014 puljen blev ryddet med 320k transaktioner, som blev tilf\u00f8jet til blok #11<br \/>\n12:10 \u2014 alle noder indeholder 1 million 670k transaktioner og tokens<br \/>\n12:17 \u2014 submission noden tog 330k transaktioner fra puljen og danner blok #12<br \/>\n12:32 \u2014 blok #12 er underskrevet og sendes til andre noder til validering<br \/>\n12:39 \u2014 blok #12 er valideret og sendt til den rod k\u00e6de <br \/>\n13:44 \u2014 alle noder har f\u00e5et information fra den rod k\u00e6de om, at blok #12 er tilf\u00f8jet, og begynder at anvende 330k transaktioner<br \/>\n14:50 \u2014 alle noder indeholder 2 millioner transaktioner og tokens<\/p>\n<h3>Test 3<\/h3>\n<p>\nP\u00e5 den f\u00f8rste og anden server blev en valideringsnode udskiftet med en submissionsnode. <\/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=\"Afspil video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nStarttilstand: sidste blok #84; 0 transaktioner og tokens er gemt i databasen<\/p>\n<p>00:00 \u2014 3 scripts er startet, som genererer og sender 1 million transaktioner<br \/>\n01:38 \u2014 1 million transaktioner er oprettet, og sendingen til submissionsnode #3 er startet<br \/>\n01:50 \u2014 submissionsnode #3 tog 330k transaktioner fra puljen og danner blok #85 (f21). Vi ser ogs\u00e5, at puljen tilf\u00f8jes med 350k transaktioner p\u00e5 10 sekunder<br \/>\n01:53 \u2014 1 million transaktioner er oprettet, og sendingen til submissionsnode #1 er startet<br \/>\n01:50 \u2014 submissionsnode #3 tog 330k transaktioner fra puljen og danner blok #85 (f21). Vi ser ogs\u00e5, at puljen tilf\u00f8jes med 350k transaktioner p\u00e5 10 sekunder<br \/>\n02:01 \u2014 submissionsnode #1 tog 250k transaktioner fra puljen og danner blok #85 (65e)<br \/>\n02:06 \u2014 blok #85 (f21) er underskrevet og sendes til andre noder til validering<br \/>\n02:08 \u2014 demo-scriptet p\u00e5 server #3 er f\u00e6rdigt, som har sendt 1 million transaktioner p\u00e5 30 sekunder<br \/>\n02:14 \u2014 blok #85 (f21) er valideret og sendt til den rod k\u00e6de <br \/>\n02:19 \u2014 blok #85 (65e) er underskrevet og sendes til andre noder til validering<br \/>\n02:22 \u2014 1 million transaktioner er oprettet, og sendingen til submissionsnode #2 er startet<br \/>\n02:27 \u2014 blok #85 (65e) er valideret og sendt til den rod k\u00e6de <br \/>\n02:29 \u2014 submissionsnode #2 tog 111855 transaktioner fra puljen og danner blok #85 (256).<br \/>\n02:36 \u2014 blok #85 (256) er underskrevet og sendes til andre noder til validering<br \/>\n02:36 \u2014 demo-scriptet p\u00e5 server #1 er f\u00e6rdigt, som har sendt 1 million transaktioner p\u00e5 42.5 sekunder<br \/>\n02:38 \u2014 blok #85 (256) er valideret og sendt til den rod k\u00e6de<br \/>\n03:08 \u2014 demo-scriptet p\u00e5 server #2 er f\u00e6rdigt, som har sendt 1 million transaktioner p\u00e5 47 sekunder <br \/>\n03:38 \u2014 alle noder har f\u00e5et information fra den rod k\u00e6de om, at blokke #85 (f21), #86(65e), #87(256) er tilf\u00f8jet, og begynder at anvende 330k, 250k, 111855 transaktioner<br \/>\n03:49 \u2014 puljen er blevet renset for 330k, 250k, 111855 transaktioner, som blev tilf\u00f8jet til blokke #85 (f21), #86(65e), #87(256)<br \/>\n03:59 \u2014 submission node #1 har taget 888145 transaktioner fra puljen og danner blok #88 (214), submission node #2 har taget 750k transaktioner fra puljen og danner blok #88 (50a), submission node #3 har taget 670k transaktioner fra puljen og danner blok #88 (d3b)<br \/>\n04:44 \u2014 blok #88 (d3b) er blevet underskrevet og sendes til de andre noder for validering<br \/>\n04:58 \u2014 blok #88 (214) er blevet underskrevet og sendes til de andre noder for validering<br \/>\n05:11 \u2014 blok #88 (50a) er blevet underskrevet og sendes til de andre noder for validering<br \/>\n05:11 \u2014 blok #85 (d3b) er blevet valideret og sendt til den prim\u00e6re k\u00e6de <br \/>\n05:36 \u2014 blok #85 (214) er blevet valideret og sendt til den prim\u00e6re k\u00e6de <br \/>\n05:43 \u2014 alle noder har modtaget information fra den prim\u00e6re k\u00e6de om, at blokke #88 (d3b), #89(214) er blevet tilf\u00f8jet og begynder at anvende 670k, 750k transaktioner<br \/>\n06:50 \u2014 p\u00e5 grund af forbindelsesafbrydelse er blok #85 (50a) ikke blevet valideret<br \/>\n06:55 \u2014 submission node #2 har taget 888145 transaktioner fra puljen og danner blok #90 (50a)<br \/>\n08:14 \u2014 blok #90 (50a) er blevet underskrevet og sendes til de andre noder for validering<br \/>\n09:04 \u2014 blok #90 (50a) er blevet valideret og sendt til den prim\u00e6re k\u00e6de <br \/>\n11:23 \u2014 alle noder har modtaget information fra den prim\u00e6re k\u00e6de om, at blok #90 (50a) er blevet tilf\u00f8jet, og begynder at anvende 888145 transaktioner. Imens har server #3 l\u00e6nge v\u00e6ret i gang med at anvende transaktioner fra blokke #88 (d3b), #89(214)<br \/>\n12:11 \u2014 alle puljer er tomme<br \/>\n13:41 \u2014 alle noder p\u00e5 server #3 indeholder 3 millioner transaktioner og tokens<br \/>\n14:35 \u2014 alle noder p\u00e5 server #1 indeholder 3 millioner transaktioner og tokens<br \/>\n19:24 \u2014 alle noder p\u00e5 server #2 indeholder 3 millioner transaktioner og tokens <\/p>\n<h2>Hindringer<\/h2>\n<p>\nUnder udviklingen af Plasma Cash st\u00f8dte vi p\u00e5 f\u00f8lgende problemer, som vi gradvist har l\u00f8st og stadig l\u00f8ser:<\/p>\n<p><b>1.<\/b> Konflikt mellem forskellige funktioner i systemet. For eksempel blokerede funktionen tilf\u00f8jelse af transaktioner til puljen operationen af submission og validering af blokke, og omvendt, hvilket f\u00f8rte til et fald i hastigheden.<\/p>\n<p><b>2. <\/b>Det var ikke klart, hvordan man kunne sende et stort antal transaktioner og samtidig minimere omkostningerne ved datatransmission.<\/p>\n<p><b>3. <\/b>Det var ikke klart, hvordan og hvor man skulle opbevare data for at opn\u00e5 h\u00f8je resultater.<\/p>\n<p><b>4. <\/b>Det var ikke klart, hvordan man skulle organisere netv\u00e6rket mellem noderne, da st\u00f8rrelsen p\u00e5 en blok med 1 million transaktioner fylder omkring 100 Mb.<\/p>\n<p><b>5.<\/b> Arbejdet i enkelttr\u00e5det tilstand bryder forbindelsen mellem noderne, n\u00e5r der udf\u00f8res langvarige beregninger (for eksempel opbygning af Merkle-tr\u00e6et og beregning af dets hash).<\/p>\n<h2>Hvordan klarede vi alt dette?<\/h2>\n<p>\nDen f\u00f8rste version af Plasma Cash-noden var en slags kombineret l\u00f8sning, der kunne g\u00f8re alt p\u00e5 \u00e9n gang: modtage transaktioner, indsende og validere blokke, og leverede API til dataadgang. Da NodeJS oprindeligt er enkelttr\u00e5det, blokerede den tunge funktion til beregning af Merkle-tr\u00e6et funktionen til at tilf\u00f8je transaktioner. Vi s\u00e5 to muligheder for at l\u00f8se dette problem:<\/p>\n<p><b>1. <\/b>K\u00f8re flere NodeJS-processer, hvor hver udf\u00f8rer bestemte funktioner.<\/p>\n<p><b>2. <\/b>Brug af worker_threads og flytte udf\u00f8relsen af dele af koden til tr\u00e5de.<\/p>\n<p>I sidste ende anvendte vi begge l\u00f8sninger samtidigt: vi delte logisk en node op i 3 dele, som kan arbejde separat, men samtidig synkront.<\/p>\n<p><b>1.<\/b> Indsendningsnode, som modtager transaktioner i puljen og h\u00e5ndterer oprettelse af blokke.<\/p>\n<p><b>2.<\/b> Valideringsnode, som verificerer validiteten af noderne.<\/p>\n<p><b>3. <\/b>API-node \u2014 leverer API til dataadgang.<\/p>\n<p>Hver node kan tilsluttes via en unix socket gennem CLI.<\/p>\n<p>Tunge operationer, s\u00e5som beregning af Merkle-tr\u00e6et, flyttede vi til en separat tr\u00e5d.<\/p>\n<p>Dermed opn\u00e5ede vi normal drift af alle funktioner i Plasma Cash samtidigt og uden fejl.<\/p>\n<p>S\u00e5 snart systemet fungerede, begyndte vi at teste hastigheden, og desv\u00e6rre fik vi utilfredsstillende resultater: 5 000 transaktioner pr. sekund og op til 50 000 transaktioner i en blok. Vi m\u00e5tte finde ud af, hvad der var implementeret forkert.<\/p>\n<p>For at starte testede vi kommunikationsmekanismen med Plasma Cash for at finde systemets maksimale kapacitet. Tidligere havde vi skrevet, at Plasma Cash-noden tilbyder unix socket-interface. Oprindeligt var det tekstbaseret, json objekter blev sendt ved hj\u00e6lp af `JSON.parse()` og `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>\nVi m\u00e5lte hastigheden for overf\u00f8rsel af s\u00e5danne objekter og fik ~ 130k pr. sekund. Vi pr\u00f8vede at erstatte standardfunktionerne til arbejde med json, men pr\u00e6stationen forbedredes ikke. M\u00e5 v\u00e6re, at V8-motoren er godt optimeret til disse operationer.<\/p>\n<p>Arbejdet med transaktioner, tokens, blokke foregik gennem klasser. Da vi oprettede s\u00e5danne klasser, faldt pr\u00e6stationen med det halve, hvilket indikerer, at OOP ikke passer til os. Vi m\u00e5tte omskrive alt til en ren funktionel tilgang.<\/p>\n<h2>Skrivning til databasen<\/h2>\n<p>\nOprindeligt blev Redis valgt til datalagring som en af de mest effektive l\u00f8sninger, der opfylder vores krav: key-value lagring, arbejde med hash-tabeller, m\u00e6ngder. Vi k\u00f8rte redis-benchmark og fik ~80k operationer pr. sekund i tilstand 1 pipelining.<\/p>\n<p>For h\u00f8j pr\u00e6station har vi finjusteret Redis: <\/p>\n<ul>\n<li>Vi har etableret en unix socket-forbindelse.<\/li>\n<li>Vi har deaktiveret tilstandens gemmelse p\u00e5 disk (for p\u00e5lidelighed kan man s\u00e6tte en replica op og gemme til disk i en separat Redis).<\/li>\n<\/ul>\n<p>\nI Redis er et pool en hash-tabel, da vi har brug for muligheden for at hente alle transaktioner med en foresp\u00f8rgsel og slette transaktioner enkeltvis. Vi pr\u00f8vede at bruge en almindelig liste, men den fungerer langsommere ved udtr\u00e6kning af hele listen. <\/p>\n<p>Ved brug af standard NodeJS Redis-biblioteket fik vi en pr\u00e6station p\u00e5 18k transaktioner pr. sekund. Hastigheden faldt med 9 gange. <\/p>\n<p>Da benchmark viste os mulighederne klart 5 gange st\u00f8rre, begyndte vi at optimere. Vi skiftede bibliotek til ioredis og fik en pr\u00e6station p\u00e5 25k pr. sekund. Vi tilf\u00f8jede transaktioner enkeltvis ved at bruge kommandoen `hset`. P\u00e5 denne m\u00e5de genererede vi mange foresp\u00f8rgsler til Redis. Ideen opstod om at samle transaktioner i pakker og sende dem med \u00e9n kommando `hmset`. Resultatet \u2014 32k pr. sekund. <\/p>\n<p>Af flere grunde, som vi vil beskrive nedenfor, arbejder vi med data ved hj\u00e6lp af `Buffer`, og det viste sig, at hvis man konverterer det til tekst (`buffer.toString('hex')`) inden skrivning, kan man opn\u00e5 en forbedret ydeevne. Dermed lykkedes det at \u00f8ge hastigheden til 35.000 pr. sekund. I \u00f8jeblikket har vi besluttet at suspendere yderligere optimering.<\/p>\n<p>Vi m\u00e5tte skifte til bin\u00e6r protokol, da:<\/p>\n<p><b>1. <\/b>Systemet beregner ofte hashes, signaturer osv., og til dette har det brug for data i `Buffer.<\/p>\n<p><b>2.<\/b> N\u00e5r man sender mellem tjenester, vejer bin\u00e6re data mindre end tekst. For eksempel, n\u00e5r man sender en blok med 1 million transaktioner, kan dataene i teksten tage over 300 megabyte.<\/p>\n<p><b>3.<\/b> Fortsat datakonvertering p\u00e5virker ydeevnen.<\/p>\n<p>Derfor har vi baseret vores egen bin\u00e6re protokol til lagring og overf\u00f8rsel af data, udviklet med den fantastiske bibliotek `binary-data`.<\/p>\n<p>Som resultat har vi f\u00f8lgende datastrukturer:<\/p>\n<h3> \u2014 Transaktion<\/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>\nMed de almindelige kommandoer `BD.encode(block, Protocol).slice();` og ` BD.decode(buffer, Protocol)` konverterer vi data til `Buffer` til lagring i Redis eller for at sende til en anden node og hente data tilbage.<\/p>\n<p>Vi har ogs\u00e5 2 bin\u00e6re protokoller til dataoverf\u00f8rsel mellem tjenester:<\/p>\n<p><i> \u2014 Protokol til interaktion med Plasma Node via unix socket<\/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 hvor:<\/p>\n<ul>\n<li> <b>`type`<\/b> \u2014 den handling, der skal udf\u00f8res, f.eks. 1 \u2014 sendTransaction, 2 \u2014 getTransaction;<\/li>\n<li> <b>`payload`<\/b> \u2014 de data, der skal sendes til den tilsvarende funktion;<\/li>\n<li> <b>`messageId`<\/b> \u2014 id for beskeden, s\u00e5 man kan identificere svaret. <\/li>\n<\/ul>\n<p>\n<i> \u2014 Protokol for interaktion mellem noder<\/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 hvor:<\/p>\n<ul>\n<li> <b>`code`<\/b> \u2014 koden for beskeden, f.eks. 6 \u2014 PREPARE_NEW_BLOCK, 7 \u2014 BLOCK_VALID, 8 \u2014 BLOCK_COMMIT;<\/li>\n<li> <b>`versionProtocol`<\/b> \u2014 versionen af protokollen, da der kan v\u00e6re noder i netv\u00e6rket med forskellige versioner, og de kan fungere forskelligt;<\/li>\n<li> <b>`seq`<\/b> \u2014 identifikatoren for beskeden;<\/li>\n<li> <b>`countChunk`<\/b> og <b>`chunkNumber`<\/b> n\u00f8dvendige for at opdele store beskeder;<\/li>\n<li> <b>`length`<\/b> og <b>`payload`<\/b> l\u00e6ngden og selve dataene.<\/li>\n<\/ul>\n<p>\nDa vi p\u00e5 forh\u00e5nd typeklassificerede dataene, fungerer det endelige system meget hurtigere end `rlp`-biblioteket fra Ethereum. Desv\u00e6rre har vi ikke v\u00e6ret i stand til at droppe det endnu, da vi skal arbejde videre med smart-kontrakten, hvilket vi planl\u00e6gger at g\u00f8re i fremtiden.<\/p>\n<p>Hvis vi har form\u00e5et at n\u00e5 en hastighed <b>35 000<\/b> af transaktioner pr. sekund, skal vi ogs\u00e5 behandle dem inden for optimal tid. Da den omtrentlige tid til dannelse af en blok tager 30 sekunder, skal vi inkludere i blokken <b>1 000 000<\/b> transaktioner, hvilket betyder, at vi sender mere end <b>100<\/b> mb data. <\/p>\n<p>Oprindeligt brugte vi `ethereumjs-devp2p`-biblioteket til at kommunikere mellem noderne, men det kunne ikke h\u00e5ndtere s\u00e5 meget data. Derfor brugte vi `ws`-biblioteket og satte op for at sende bin\u00e6re data over websocket. Selvf\u00f8lgelig st\u00f8ttede vi ogs\u00e5 p\u00e5 problemer med at sende store datapakker, men vi delte dem op i chunks, og nu er disse problemer l\u00f8st.<\/p>\n<p>Desuden kr\u00e6ver dannelsen af Merkle-tr\u00e6et og beregningen af hash <b>1 000 000<\/b> transaktioner cirka<b> 10<\/b> sekunder med kontinuerlig beregning. I denne tid f\u00f8lger forbindelsen til alle noderne ofte med. Det blev besluttet at flytte denne beregning til en separat tr\u00e5d.<\/p>\n<h2>Konklusioner:<\/h2>\n<p>\nFaktisk er vores konklusioner ikke nye, men alligevel glemmer mange specialister dem under udviklingen. <\/p>\n<ul>\n<li>Brugen af funktionel programmering frem for objektorienteret programmering \u00f8ger ydeevnen.<\/li>\n<li>Monolit er d\u00e5rligere end servicearkitektur for et performant system p\u00e5 NodeJS.<\/li>\n<li>Brugen af `worker_threads` til tunge beregninger forbedrer systemets reaktivitet, is\u00e6r ved h\u00e5ndtering af i\/o-operationer.<\/li>\n<li>Unix-sockets er mere stabile og hurtigere end http-anmodninger.<\/li>\n<li>Hvis store data skal overf\u00f8res hurtigt over netv\u00e6rket, er det bedre at bruge websockets til at sende bin\u00e6re data opdelt i chunks, som kan sendes igen, hvis de ikke n\u00e5r frem, og derefter samles til en enkelt meddelelse.<\/li>\n<\/ul>\n<p>\nVi inviterer dig til at bes\u00f8ge <b>GitHub<\/b> projektet: <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>Artiklen blev skrevet i samarbejde med <i>Alexander Nashivan<\/i>, seniorudvikler <noindex><a rel=\"nofollow\" href=\"https:\/\/clever-solution.com\/\">Clever Solution Inc<\/a><\/noindex>.<br \/>\n<br \/>Kilde: <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.3 - 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\/da\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\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\/da\/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\udd47Offentlig test: l\u00f8sning til privatliv og skalerbarhed i Ethereum | ProHoster","description":"Blockchain er en innovativ teknologi, der lover at forbedre mange omr\u00e5der af menneskelivet.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","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\/da\/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\/da\/wp-json\/wp\/v2\/posts\/38856","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=38856"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/38856\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/29146"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=38856"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=38856"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=38856"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}