{"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\/it\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume","title":{"rendered":"Test pubblico: soluzione per la privacy e la scalabilit\u00e0 in Ethereum","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><b>Blockchain<\/b> \u2014 una tecnologia innovativa che promette di migliorare molti aspetti della vita umana. Essa trasferisce processi e prodotti reali nello spazio digitale, garantendo velocit\u00e0 e affidabilit\u00e0 delle operazioni finanziarie, riducendo i costi e consentendo la creazione di moderne applicazioni DAPP utilizzando contratti intelligenti in reti decentralizzate.<\/p>\n<p>Considerando i numerosi vantaggi e le diverse aree di applicazione della blockchain, pu\u00f2 sembrare strano che questa promettente tecnologia non sia ancora penetrata in tutti i settori. Il problema \u00e8 che le blockchain decentralizzate attuali mancano di scalabilit\u00e0. Ethereum gestisce circa 20 transazioni al secondo, il che non \u00e8 sufficiente per soddisfare le esigenze del dinamico business moderno. Allo stesso tempo, le aziende che utilizzano la tecnologia blockchain non si aiutano a rinunciare a Ethereum a causa del suo elevato livello di protezione contro hackeraggi e guasti di rete.<\/p>\n<p>Per garantire decentramento, sicurezza e scalabilit\u00e0 nella blockchain, affrontando cos\u00ec il Dilemma della Scalabilit\u00e0, il team di sviluppatori <noindex><a rel=\"nofollow\" href=\"https:\/\/opporty.com\/\">Opporty<\/a><\/noindex> ha creato Plasma Cash \u2014 una side chain composta da un contratto intelligente e una rete privata basata su Node.js, che trasferisce periodicamente il proprio stato nella catena principale (Ethereum).<\/p>\n<p><img decoding=\"async\" alt=\"Test pubblico: soluzione per la privacy e la scalabilit\u00e0 in 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>I processi chiave in Plasma Cash<\/h2>\n<p>\n<b>1. <\/b>L'utente chiama la funzione del contratto intelligente `deposit`, passando l'importo in ETH che desidera depositare nel token Plasma Cash. La funzione del contratto intelligente crea un token e genera un evento in merito.<\/p>\n<p><b>2. <\/b>I nodi Plasma Cash, iscritti agli eventi del contratto intelligente, ricevono l'evento di creazione del deposito e aggiungono alla pool la transazione di creazione del token.<\/p>\n<p><b>3. <\/b>Periodicamente, nodi speciali di Plasma Cash prendono tutte le transazioni dalla pool (fino a 1 milione) e formano un blocco, calcolano l'albero di Merkle e, di conseguenza, l'hash. Questo blocco viene inviato ad altri nodi per la verifica. I nodi controllano se l'hash di Merkle \u00e8 valido, se le transazioni sono valide (ad esempio, se il mittente del token \u00e8 il suo proprietario). Dopo la verifica del blocco, il nodo chiama la funzione `submitBlock` del contratto intelligente, che salva nella catena principale il numero e l'hash di Merkle del blocco. Il contratto intelligente genera un evento di avvenuta aggiunta del blocco. Le transazioni vengono rimosse dalla pool. <\/p>\n<p><b>4. <\/b>I nodi che ricevono l'evento di invio del blocco iniziano ad applicare le transazioni che sono state aggiunte nel blocco.<\/p>\n<p><b>5. <\/b>A un certo punto, il proprietario (o non proprietario) del token desidera ritirarlo da Plasma Cash. A tale scopo, chiama la funzione `startExit`, passando le informazioni sulle ultime 2 transazioni relative al token che confermano che \u00e8 lui il proprietario del token. Il contratto intelligente, utilizzando l'hash Merkle, verifica la presenza delle transazioni nei blocchi e invia il token per il prelievo, che avverr\u00e0 dopo due settimane.<\/p>\n<p><b>6. <\/b>Se l'operazione di prelievo del token avviene con violazioni (il token \u00e8 stato speso dopo l'inizio della procedura di prelievo o il token era gi\u00e0 di qualcun altro prima del prelievo), il proprietario del token pu\u00f2 contestare il prelievo entro due settimane.<\/p>\n<p><img decoding=\"async\" alt=\"Test pubblico: soluzione per la privacy e la scalabilit\u00e0 in Ethereum\" src=\"\/wp-content\/uploads\/2019\/10\/0626ca6b010eb847175dbfb0b6d7b357.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>La privacy \u00e8 raggiunta in due modi<\/h2>\n<p>\n<b>1. <\/b>La catena principale non sa nulla delle transazioni che vengono create e inviate all'interno della catena secondaria. Rimane pubblica l'informazione su chi ha depositato e prelevato ETH in\/da Plasma Cash.<\/p>\n<p><b>2. <\/b>La catena secondaria consente di organizzare transazioni anonime utilizzando zk-SNARKs.<\/p>\n<h2>Stack tecnologico<\/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>Test <\/h2>\n<p>\nSviluppando Plasma Cash, abbiamo testato la velocit\u00e0 del sistema e ottenuto i seguenti risultati:<\/p>\n<ul>\n<li>fino a 35.000 transazioni al secondo vengono aggiunte al pool;<\/li>\n<li>fino a 1.000.000 transazioni possono essere memorizzate in un blocco.<\/li>\n<\/ul>\n<p>\nI test sono stati condotti su 3 seguenti server:<\/p>\n<p><i>1. Intel Core i7-6700 Quad-Core Skylake incl. NVMe SSD \u2014 512 GB, 64 GB DDR4 RAM<\/i><br \/>\n Sono stati attivati 3 nodi validatori di 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 \u00c8 stato attivato un nodo della testnet ETH Ropsten.<br \/>\n Sono stati attivati 3 nodi validatori di Plasma Cash.<\/p>\n<p><i>3. Intel Core i9-9900K Octa-Core incl. NVMe SSD \u2014 1 TB, 64 GB DDR4 RAM<\/i><br \/>\n \u00c8 stato attivato 1 nodo per il submit di Plasma Cash.<br \/>\n Sono stati attivati 3 nodi validatori di Plasma Cash.<br \/>\n \u00c8 stato avviato un test per aggiungere transazioni nella rete Plasma Cash.<\/p>\n<p><b>In totale: <\/b>10 nodi di Plasma Cash in una rete privata.<\/p>\n<h3>Test 1<\/h3>\n<p>\nC'\u00e8 un limite di 1 milione di transazioni in un blocco. Pertanto, 1 milione di transazioni vengono distribuite su 2 blocchi (poich\u00e9 il sistema riesce a prendere parte delle transazioni e ad inviarle mentre vengono trasferite).<\/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=\"Guarda il video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nStato iniziale: ultimo blocco #7; nel database sono memorizzati 1 milione di transazioni e token.<\/p>\n<p>00:00 \u2014 avvio dello script di generazione delle transazioni<br \/>\n01:37 \u2014 creato 1 milione di transazioni e iniziato l'invio al nodo<br \/>\n01:46 \u2014 il nodo di submit ha preso dal pool 240k transazioni e sta formando il blocco #8. Vedi anche che nel pool vengono aggiunti 320k transazioni in 10 sec<br \/>\n01:58 \u2014 blocco #8 firmato e inviato per la validazione<br \/>\n02:03 \u2014 il blocco #8 \u00e8 stato convalidato e chiamata la funzione `submitBlock` del contratto intelligente con l'hash Merkle e il numero di blocco<br \/>\n02:10 \u2014 il demo script ha terminato il suo lavoro, inviando 1 milione di transazioni in 32 secondi<br \/>\n02:33 \u2014 i nodi hanno iniziato a ricevere informazioni che il blocco #8 \u00e8 stato aggiunto alla catena principale e hanno iniziato a eseguire 240k transazioni<br \/>\n02:40 \u2014 240k transazioni sono state rimosse dal pool, che sono gi\u00e0 nel blocco #8<br \/>\n02:56 \u2014 il nodo submit ha preso dal pool le rimanenti 760k transazioni e ha iniziato a calcolare l'hash Merkle e firmare il blocco #9<br \/>\n03:20 \u2014 tutti i nodi contengono 1 milione e 240k transazioni e token<br \/>\n03:35 \u2014 il blocco #9 \u00e8 stato firmato e inviato per convalida ad altri nodi <br \/>\n03:41 \u2014 si \u00e8 verificato un errore di rete<br \/>\n04:40 \u2014 il timeout ha interrotto l'attesa per la convalida del blocco #9<br \/>\n04:54 \u2014 il nodo submit ha preso dal pool le rimanenti 760k transazioni e ha iniziato a calcolare l'hash Merkle e firmare il blocco #9<br \/>\n05:32 \u2014 il blocco #9 \u00e8 stato firmato e inviato per convalida ad altri nodi<br \/>\n05:53 \u2014 il blocco #9 \u00e8 stato convalidato ed inviato alla catena principale<br \/>\n06:17 \u2014 i nodi hanno iniziato a ricevere informazioni che il blocco #9 \u00e8 stato aggiunto alla catena principale e hanno iniziato a eseguire 760k transazioni<br \/>\n06:47 \u2014 il pool \u00e8 stato svuotato dalle transazioni presenti nel blocco #9<br \/>\n09:06 \u2014 tutti i nodi contengono 2 milioni di transazioni e token<\/p>\n<h3>Test 2<\/h3>\n<p>\nC'\u00e8 un limite di 350k per blocco. Di conseguenza, abbiamo 3 blocchi.<\/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=\"Guarda il video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nStato iniziale: ultimo blocco #9; nel database sono salvati 2 milioni di transazioni e token<\/p>\n<p>00:00 \u2014 lo script di generazione delle transazioni \u00e8 gi\u00e0 stato avviato<br \/>\n00:44 \u2014 sono state create 1 milione di transazioni e \u00e8 iniziato l'invio al nodo<br \/>\n00:56 \u2014 il nodo submit ha preso dal pool 320k transazioni e sta formando il blocco #10. Vediamo anche che al pool sono state aggiunte 320k transazioni in 10 secondi<br \/>\n01:12 \u2014 il blocco #10 \u00e8 stato firmato e inviato agli altri nodi per la convalida<br \/>\n01:18 \u2014 il demo script ha terminato il suo lavoro, inviando 1 milione di transazioni in 34 secondi<br \/>\n01:20 \u2014 il blocco #10 \u00e8 stato convalidato ed inviato alla catena principale <br \/>\n01:51 \u2014 tutti i nodi hanno ricevuto dalla catena principale informazioni che il blocco #10 \u00e8 stato aggiunto e iniziano a elaborare 320k transazioni<br \/>\n02:01 \u2014 il pool si \u00e8 svuotato di 320k transazioni che sono state aggiunte al blocco #10<br \/>\n02:15 \u2014 il nodo submit ha preso dal pool 350k transazioni e sta formando il blocco #11<br \/>\n02:34 \u2014 il blocco #11 \u00e8 stato firmato e inviato ad altri nodi per la convalida<br \/>\n02:51 \u2014 il blocco #11 \u00e8 stato convalidato ed inviato alla catena principale <br \/>\n02:55 \u2014 l'ultimo nodo ha eseguito le transazioni dal blocco #10<br \/>\n10:59 \u2014 La transazione con il submit del blocco #9 \u00e8 stata eseguita molto a lungo nella catena principale, ma \u00e8 stata completata e tutti i nodi hanno ricevuto questa informazione e hanno iniziato a eseguire 350k transazioni.<br \/>\n11:05 \u2014 Il pool si \u00e8 liberato di 320k transazioni, che sono state aggiunte al blocco #11.<br \/>\n12:10 \u2014 Tutti i nodi contengono 1 milione e 670k transazioni e token.<br \/>\n12:17 \u2014 Il nodo submit ha prelevato dal pool 330k transazioni e sta formando il blocco #12.<br \/>\n12:32 \u2014 Il blocco #12 \u00e8 stato firmato e inviato agli altri nodi per la validazione.<br \/>\n12:39 \u2014 Il blocco #12 \u00e8 stato validato e inviato alla catena principale. <br \/>\n13:44 \u2014 Tutti i nodi hanno ricevuto dalla catena principale l'informazione che il blocco #12 \u00e8 stato aggiunto e iniziano ad applicare 330k transazioni.<br \/>\n14:50 \u2014 Tutti i nodi contengono 2 milioni di transazioni e token.<\/p>\n<h3>Test 3<\/h3>\n<p>\nNel primo e nel secondo server, un nodo di validazione \u00e8 stato sostituito con un nodo submit. <\/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=\"Guarda il video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nStato iniziale: ultimo blocco #84; nella base sono salvate 0 transazioni e token.<\/p>\n<p>00:00 \u2014 Sono stati avviati 3 script che generano e inviano 1 milione di transazioni ciascuno.<br \/>\n01:38 \u2014 Sono state create 1 milione di transazioni e \u00e8 iniziato l'invio al nodo submit #3.<br \/>\n01:50 \u2014 Il nodo submit #3 ha prelevato dal pool 330k transazioni e sta formando il blocco #85 (f21). Inoltre, vediamo che nel pool vengono aggiunti 350k transazioni in 10 secondi.<br \/>\n01:53 \u2014 Sono state create 1 milione di transazioni e \u00e8 iniziato l'invio al nodo submit #1.<br \/>\n01:50 \u2014 Il nodo submit #3 ha prelevato dal pool 330k transazioni e sta formando il blocco #85 (f21). Inoltre, vediamo che nel pool vengono aggiunti 350k transazioni in 10 secondi.<br \/>\n02:01 \u2014 Il nodo submit #1 ha prelevato dal pool 250k transazioni e sta formando il blocco #85 (65e).<br \/>\n02:06 \u2014 Il blocco #85 (f21) \u00e8 stato firmato e inviato agli altri nodi per la validazione.<br \/>\n02:08 \u2014 Il demo-script del server #3 ha terminato il suo lavoro, inviando 1 milione di transazioni in 30 secondi.<br \/>\n02:14 \u2014 Il blocco #85 (f21) \u00e8 stato validato e inviato alla catena principale. <br \/>\n02:19 \u2014 Il blocco #85 (65e) \u00e8 stato firmato e inviato agli altri nodi per la validazione.<br \/>\n02:22 \u2014 Sono state create 1 milione di transazioni e \u00e8 iniziato l'invio al nodo submit #2.<br \/>\n02:27 \u2014 Il blocco #85 (65e) \u00e8 stato validato e inviato alla catena principale. <br \/>\n02:29 \u2014 Il nodo submit #2 ha prelevato dal pool 111855 transazioni e sta formando il blocco #85 (256).<br \/>\n02:36 \u2014 Il blocco #85 (256) \u00e8 stato firmato e inviato agli altri nodi per la validazione.<br \/>\n02:36 \u2014 Il demo-script del server #1 ha terminato il suo lavoro, inviando 1 milione di transazioni in 42.5 secondi.<br \/>\n02:38 \u2014 Il blocco #85 (256) \u00e8 stato validato e inviato alla catena principale.<br \/>\n03:08 \u2014 Il demo-script del server #2 ha terminato il suo lavoro, inviando 1 milione di transazioni in 47 secondi. <br \/>\n03:38 \u2014 Tutti i nodi hanno ricevuto dalla catena principale l'informazione che i blocchi #85 (f21), #86(65e), #87(256) sono stati aggiunti e iniziano ad applicare 330k, 250k, 111855 transazioni.<br \/>\n03:49 \u2014 il pool si \u00e8 ripulito di 330k, 250k, 111855 transazioni, che sono state aggiunte ai blocchi #85 (f21), #86(65e), #87(256)<br \/>\n03:59 \u2014 il submit node #1 ha prelevato 888145 transazioni dal pool e sta formando il blocco #88 (214), il submit node #2 ha prelevato 750k transazioni dal pool e sta formando il blocco #88 (50a), il submit node #3 ha prelevato 670k transazioni dal pool e sta formando il blocco #88 (d3b)<br \/>\n04:44 \u2014 il blocco #88 (d3b) \u00e8 firmato e inviato ad altri nodi per la validazione<br \/>\n04:58 \u2014 il blocco #88 (214) \u00e8 firmato e inviato ad altri nodi per la validazione<br \/>\n05:11 \u2014 il blocco #88 (50a) \u00e8 firmato e inviato ad altri nodi per la validazione<br \/>\n05:11 \u2014 il blocco #85 (d3b) \u00e8 stato validato e inviato nella catena principale <br \/>\n05:36 \u2014 il blocco #85 (214) \u00e8 stato validato e inviato nella catena principale <br \/>\n05:43 \u2014 tutti i nodi hanno ricevuto dalla catena principale l'informazione che i blocchi #88 (d3b), #89(214) sono stati aggiunti e iniziano ad applicare 670k, 750k transazioni<br \/>\n06:50 \u2014 a causa di un'interruzione della connessione, il blocco #85 (50a) non \u00e8 stato validato<br \/>\n06:55 \u2014 il submit node #2 ha prelevato 888145 transazioni dal pool e sta formando il blocco #90 (50a)<br \/>\n08:14 \u2014 il blocco #90 (50a) \u00e8 firmato e inviato ad altri nodi per la validazione<br \/>\n09:04 \u2014 il blocco #90 (50a) \u00e8 stato validato e inviato nella catena principale <br \/>\n11:23 \u2014 tutti i nodi hanno ricevuto dalla catena principale l'informazione che il blocco #90 (50a) \u00e8 stato aggiunto e iniziano ad applicare 888145 transazioni. Nel frattempo, il server #3 aveva gi\u00e0 applicato le transazioni dai blocchi #88 (d3b), #89(214)<br \/>\n12:11 \u2014 tutti i pool sono vuoti<br \/>\n13:41 \u2014 tutti i nodi del server #3 contengono 3 milioni di transazioni e token<br \/>\n14:35 \u2014 tutti i nodi del server #1 contengono 3 milioni di transazioni e token<br \/>\n19:24 \u2014 tutti i nodi del server #2 contengono 3 milioni di transazioni e token <\/p>\n<h2>Ostacoli<\/h2>\n<p>\nDurante lo sviluppo di Plasma Cash, ci siamo trovati di fronte alle seguenti problematiche, che abbiamo risolto e stiamo risolvendo:<\/p>\n<p><b>1.<\/b> Conflitto tra le diverse funzioni del sistema. Ad esempio, la funzione di aggiunta delle transazioni al pool bloccava il lavoro di submit e validazione dei blocchi e viceversa, il che portava a una diminuzione della velocit\u00e0.<\/p>\n<p><b>2. <\/b>Non era immediato capire come inviare un grande numero di transazioni minimizzando al contempo i costi di trasmissione dei dati.<\/p>\n<p><b>3. <\/b>Non era chiaro come e dove archiviare i dati per ottenere risultati elevati.<\/p>\n<p><b>4. <\/b>Non era chiaro come organizzare la rete tra i nodi, dato che la dimensione di un blocco con 1 milione di transazioni occupa circa 100 MB.<\/p>\n<p><b>5.<\/b> Lavorare in modalit\u00e0 single-thread rompe la connessione tra i nodi quando sono in corso calcoli lunghi (ad esempio, costruzione dell'albero di Merkle e calcolo del suo hash).<\/p>\n<h2>Come abbiamo gestito tutto questo?<\/h2>\n<p>\nLa prima versione del nodo Plasma Cash era una sorta di combinazione che poteva fare tutto contemporaneamente: ricevere transazioni, sottomettere e convalidare blocchi, fornire un'API per accedere ai dati. Poich\u00e9 NodeJS \u00e8 originariamente monolitico, la pesante funzione di calcolo dell'albero di Merkle bloccava la funzione di aggiunta delle transazioni. Abbiamo visto due opzioni per risolvere questo problema:<\/p>\n<p><b>1. <\/b>Lanciare pi\u00f9 processi NodeJS, ognuno dei quali esegue funzioni specifiche.<\/p>\n<p><b>2. <\/b>Utilizzare worker_threads e spostare l'esecuzione di parte del codice nei thread.<\/p>\n<p>Alla fine abbiamo utilizzato entrambe le opzioni contemporaneamente: abbiamo logicamente suddiviso un nodo in 3 parti, che possono lavorare separatamente, ma allo stesso tempo in modo sincronizzato.<\/p>\n<p><b>1.<\/b> Nodo di sottomissione, che riceve le transazioni nel pool e si occupa della creazione dei blocchi.<\/p>\n<p><b>2.<\/b> Nodo di convalida, che controlla la validit\u00e0 dei nodi.<\/p>\n<p><b>3. <\/b>Nodo API \u2014 fornisce un'API per l'accesso ai dati.<\/p>\n<p>Inoltre, \u00e8 possibile collegarsi a ciascun nodo attraverso un socket unix tramite cli.<\/p>\n<p>Operazioni pesanti, come il calcolo dell'albero di Merkle, le abbiamo spostate in un thread separato.<\/p>\n<p>In questo modo, abbiamo raggiunto un funzionamento normale di tutte le funzioni di Plasma Cash contemporaneamente e senza errori.<\/p>\n<p>Non appena il sistema ha iniziato a funzionare, abbiamo iniziato a testare la velocit\u00e0 e, sfortunatamente, abbiamo ottenuto risultati insoddisfacenti: 5.000 transazioni al secondo e fino a 50.000 transazioni per blocco. \u00c8 stato necessario scoprire cosa fosse stato implementato in modo errato.<\/p>\n<p>Per cominciare, abbiamo iniziato a testare il meccanismo di comunicazione con Plasma Cash, per scoprire le capacit\u00e0 massime del sistema. In precedenza avevamo scritto che il nodo Plasma Cash fornisce un'interfaccia socket unix. Inizialmente era testuale. Gli oggetti json venivano trasmessi utilizzando `JSON.parse()` e `JSON.stringify()`. <\/p>\n<pre><code class=\"plaintext\">```json\n{\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```\n<\/code><\/pre>\n<p>\nAbbiamo misurato la velocit\u00e0 di invio di tali oggetti e abbiamo ottenuto circa 130k al secondo. Abbiamo provato a sostituire le funzioni standard per lavorare con json, ma le prestazioni non sono migliorate. Deve essere che il motore V8 \u00e8 ben ottimizzato per queste operazioni.<\/p>\n<p>Il lavoro con transazioni, token e blocchi \u00e8 stato realizzato tramite classi. La creazione di tali classi ha ridotto le prestazioni di due volte, il che indica che l'OOP non \u00e8 adatto a noi. Abbiamo dovuto riscrivere tutto utilizzando un approccio puramente funzionale.<\/p>\n<h2>Scrittura nel database<\/h2>\n<p>\nInizialmente, per la memorizzazione dei dati, \u00e8 stata scelta Redis come una delle soluzioni pi\u00f9 performanti, soddisfacendo le nostre esigenze: storage key-value, gestione di hash table e insiemi. Abbiamo eseguito redis-benchmark e ottenuto ~80k operazioni al secondo in modalit\u00e0 1 pipelining.<\/p>\n<p>Per alte prestazioni, abbiamo ottimizzato Redis pi\u00f9 nel dettaglio: <\/p>\n<ul>\n<li>Abbiamo configurato una connessione tramite socket unix.<\/li>\n<li>Abbiamo disattivato il salvataggio dello stato su disco (per maggior sicurezza \u00e8 possibile configurare una replica e fare il salvataggio su un Redis separato).<\/li>\n<\/ul>\n<p>\nIn Redis, il pool \u00e8 una tabella hash, in quanto abbiamo bisogno della possibilit\u00e0 di ottenere tutte le transazioni in una sola richiesta e di eliminare transazioni singolarmente. Abbiamo provato a usare una semplicissima lista, ma questa lavora pi\u00f9 lentamente quando si scarica tutta la lista. <\/p>\n<p>Utilizzando la libreria standard NodeJS per Redis, abbiamo ottenuto prestazioni di 18k transazioni al secondo. La velocit\u00e0 \u00e8 diminuita di 9 volte. <\/p>\n<p>Poich\u00e9 il benchmark mostrava capacit\u00e0 chiaramente cinque volte superiori, abbiamo iniziato a ottimizzare. Abbiamo cambiato libreria in ioredis e ottenuto prestazioni di 25k al secondo. Le transazioni sono state aggiunte singolarmente, usando il comando `hset`. In questo modo, abbiamo generato molte richieste a Redis. \u00c8 emersa l'idea di unire le transazioni in batch e inviarle con un solo comando `hmset`. Il risultato \u00e8 stato 32k al secondo. <\/p>\n<p>Per diversi motivi che descriveremo di seguito, lavoriamo con i dati utilizzando `Buffer` e, come si \u00e8 rivelato, se lo si traduce in testo (`buffer.toString('hex')`) prima della scrittura, \u00e8 possibile ottenere prestazioni aggiuntive. In questo modo, la velocit\u00e0 \u00e8 stata aumentata fino a 35k al secondo. Al momento, abbiamo deciso di sospendere ulteriori ottimizzazioni.<\/p>\n<p>Abbiamo dovuto passare al protocollo binario poich\u00e9:<\/p>\n<p><b>1. <\/b>Il sistema calcola spesso hash, firme ecc., e per questo ha bisogno di dati in `Buffer`.<\/p>\n<p><b>2.<\/b> Quando vengono trasferiti tra i servizi, i dati binari occupano meno spazio rispetto al testo. Ad esempio, durante l'invio di un blocco con 1 milione di transazioni, i dati in testo possono occupare pi\u00f9 di 300 megabyte.<\/p>\n<p><b>3.<\/b> La continua conversione dei dati influisce sulle prestazioni.<\/p>\n<p>Pertanto, abbiamo basato il nostro protocollo binario per la memorizzazione e la trasmissione dei dati sul fantastico framework `binary-data`.<\/p>\n<p>Di conseguenza, abbiamo ottenuto le seguenti strutture dati:<\/p>\n<h3> \u2014 Transazione<\/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 Blocco<\/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>\nCon i comandi standard `BD.encode(block, Protocol).slice();` e `BD.decode(buffer, Protocol)` trasformiamo i dati in `Buffer` per salvarli in Redis o inviarli a un altro nodo e per estrarre nuovamente i dati.<\/p>\n<p>Abbiamo anche 2 protocolli binari per la trasmissione dei dati tra i servizi:<\/p>\n<p><i> \u2014 Protocollo per interagire con Plasma Node tramite 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 dove:<\/p>\n<ul>\n<li> <b>`type`<\/b> \u2014 azione da eseguire, ad esempio 1 \u2014 sendTransaction, 2 \u2014 getTransaction;<\/li>\n<li> <b>`payload`<\/b> \u2014 dati da inviare alla funzione corrispondente;<\/li>\n<li> <b>`messageId`<\/b> \u2014 id del messaggio per identificare la risposta. <\/li>\n<\/ul>\n<p>\n<i> \u2014 Protocollo di interazione tra nodi<\/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 dove:<\/p>\n<ul>\n<li> <b>`code`<\/b> \u2014 codice del messaggio, ad esempio 6 \u2014 PREPARE_NEW_BLOCK, 7 \u2014 BLOCK_VALID, 8 \u2014 BLOCK_COMMIT;<\/li>\n<li> <b>`versionProtocol`<\/b> \u2014 versione del protocollo, poich\u00e9 nella rete possono essere attivate nodi con versioni diverse e possono funzionare in modi differenti;<\/li>\n<li> <b>`seq`<\/b> \u2014 identificatore del messaggio;<\/li>\n<li> <b>`countChunk`<\/b> e <b>`chunkNumber`<\/b> necessari per suddividere i messaggi di grandi dimensioni;<\/li>\n<li> <b>`length`<\/b> e <b>`payload`<\/b> lunghezza e dati stessi.<\/li>\n<\/ul>\n<p>\nPoich\u00e9 abbiamo tipizzato i dati in anticipo, il sistema finale funziona molto pi\u00f9 velocemente rispetto alla libreria `rlp` di Ethereum. Purtroppo, non siamo ancora riusciti a rinunciare ad essa, poich\u00e9 \u00e8 necessario migliorare il contratto smart, cosa che prevediamo di fare in futuro.<\/p>\n<p>Se siamo riusciti a raggiungere la velocit\u00e0 <b>35 000<\/b> transazioni al secondo, dobbiamo anche elaborarle in un tempo ottimale. Poich\u00e9 il tempo medio di formazione di un blocco \u00e8 di 30 secondi, \u00e8 necessario includere nel blocco <b>1 000 000<\/b> transazioni, il che significa inviare pi\u00f9 di <b>100<\/b> MB di dati. <\/p>\n<p>Inizialmente abbiamo utilizzato la libreria `ethereumjs-devp2p` per la comunicazione tra i nodi, ma non era in grado di gestire cos\u00ec tanti dati. Di conseguenza, abbiamo usato la libreria `ws` e configurato l'invio di dati binari tramite websocket. Certo, ci siamo anche imbattuti in problemi nell'invio di grandi pacchetti di dati, ma li abbiamo suddivisi in chunk e ora non abbiamo pi\u00f9 questi problemi.<\/p>\n<p>Inoltre, la creazione dell'albero di Merkle e il calcolo dell'hash <b>1 000 000<\/b> delle transazioni richiedono circa<b> 10<\/b> secondi di calcolo continuo. Durante questo tempo la connessione con tutti i nodi tende a cadere. \u00c8 stato deciso di spostare questo calcolo in un thread separato.<\/p>\n<h2>Conclusioni:<\/h2>\n<p>\nIn realt\u00e0, le nostre conclusioni non sono nuove, ma per qualche motivo molti specialisti le dimenticano durante lo sviluppo. <\/p>\n<ul>\n<li>L'uso della programmazione funzionale invece della programmazione orientata agli oggetti aumenta le prestazioni.<\/li>\n<li>Un monolite \u00e8 peggiore di un'architettura basata sui servizi per un sistema performante su NodeJS.<\/li>\n<li>L'uso di `worker_threads` per calcoli intensivi migliora la reattivit\u00e0 del sistema, soprattutto quando si lavora con operazioni I\/O.<\/li>\n<li>Il socket unix \u00e8 pi\u00f9 stabile e veloce delle richieste HTTP.<\/li>\n<li>Se hai bisogno di trasmettere rapidamente grandi dati tramite rete, \u00e8 meglio utilizzare i websocket e inviare dati binari suddivisi in chunk, che possono essere ripetuti se non vengono ricevuti, e poi uniti in un unico messaggio.<\/li>\n<\/ul>\n<p>\nTi invitiamo a visitare <b>GitHub<\/b> progetto: <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>L'articolo \u00e8 stato scritto in collaborazione con <i>Alexander Nashivan<\/i>, sviluppatore senior di <noindex><a rel=\"nofollow\" href=\"https:\/\/clever-solution.com\/\">Clever Solution Inc<\/a><\/noindex>.<br \/>\n<br \/>Fonte: <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\/it\/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=\"it_IT\" \/>\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\/it\/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\udd47Test pubblico: soluzione per privacy e scalabilit\u00e0 in Ethereum | ProHoster","description":"Il blockchain \u00e8 una tecnologia innovativa che promette di migliorare molti aspetti della vita umana.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/38856","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=38856"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/38856\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/29146"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=38856"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=38856"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=38856"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}