{"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\/es\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume","title":{"rendered":"Prueba p\u00fablica: soluci\u00f3n para la privacidad y escalabilidad en Ethereum","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><b>Blockchain<\/b> \u2014 una tecnolog\u00eda innovadora que promete mejorar muchos aspectos de la vida humana. Transfiere procesos y productos reales al espacio digital, asegura la velocidad y confiabilidad de las transacciones financieras, reduce sus costos y tambi\u00e9n permite crear aplicaciones DAPP modernas utilizando contratos inteligentes en redes descentralizadas.<\/p>\n<p>Considerando las numerosas ventajas y diversas \u00e1reas de aplicaci\u00f3n del blockchain, puede parecer extra\u00f1o que esta prometedora tecnolog\u00eda a\u00fan no haya penetrado en todas las industrias. El problema es que los blockchains descentralizados actuales carecen de escalabilidad. Ethereum procesa alrededor de 20 transacciones por segundo, lo cual es insuficiente para satisfacer las necesidades de los negocios din\u00e1micos actuales. Al mismo tiempo, las empresas que utilizan la tecnolog\u00eda blockchain no se atreven a abandonar Ethereum debido a su alto grado de protecci\u00f3n contra hacks y fallos de red.<\/p>\n<p>Para asegurar descentralizaci\u00f3n, seguridad y escalabilidad en el blockchain, resolviendo as\u00ed la Trilema de Escalabilidad, el equipo de desarrolladores <noindex><a rel=\"nofollow\" href=\"https:\/\/opporty.com\/\">Opporty<\/a><\/noindex> cre\u00f3 Plasma Cash \u2014 una cadena lateral compuesta por un contrato inteligente y una red privada basada en Node.js que transmite peri\u00f3dicamente su estado a la cadena principal (Ethereum).<\/p>\n<p><img decoding=\"async\" alt=\"Prueba p\u00fablica: soluci\u00f3n para la privacidad y escalabilidad en 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>Los procesos clave en Plasma Cash<\/h2>\n<p>\n<b>1. <\/b>El usuario invoca la funci\u00f3n del contrato inteligente `deposit`, transmiti\u00e9ndole la cantidad en ETH que desea depositar en el token Plasma Cash. La funci\u00f3n del contrato inteligente crea el token y genera un evento al respecto.<\/p>\n<p><b>2. <\/b>Los nodos de Plasma Cash, suscritos a los eventos del contrato inteligente, reciben el evento de creaci\u00f3n del dep\u00f3sito y a\u00f1aden a la pool la transacci\u00f3n de creaci\u00f3n del token.<\/p>\n<p><b>3. <\/b>Peri\u00f3dicamente, nodos especiales de Plasma Cash toman todas las transacciones de la pool (hasta 1 mill\u00f3n) y forman un bloque a partir de ellas, calculan el \u00e1rbol de Merkle y, en consecuencia, el hash. Este bloque se env\u00eda a otros nodos para verificaci\u00f3n. Los nodos comprueban si el hash de Merkle es v\u00e1lido y si las transacciones son v\u00e1lidas (por ejemplo, si el remitente del token es su propietario). Tras la verificaci\u00f3n del bloque, el nodo invoca la funci\u00f3n `submitBlock` del contrato inteligente, que guarda en la cadena principal el n\u00famero y el hash de Merkle del bloque. El contrato inteligente genera un evento de adici\u00f3n exitosa del bloque. Las transacciones se eliminan de la pool. <\/p>\n<p><b>4. <\/b>Los nodos que reciben el evento de env\u00edo del bloque comienzan a aplicar las transacciones que se han a\u00f1adido al bloque.<\/p>\n<p><b>5. <\/b>En alg\u00fan momento, el propietario (o no propietario) del token desea retirarlo de Plasma Cash. Para ello, invoca la funci\u00f3n `startExit`, proporcionando informaci\u00f3n sobre las \u00faltimas 2 transacciones del token, que confirman que \u00e9l es el propietario del token. El contrato inteligente, utilizando el hash Merkle, verifica la presencia de las transacciones en los bloques y env\u00eda el token para que se retire, lo cual ocurrir\u00e1 en dos semanas.<\/p>\n<p><b>6. <\/b>Si la operaci\u00f3n de retiro del token se realiz\u00f3 de manera indebida (el token fue gastado despu\u00e9s de iniciar el procedimiento de retiro o el token ya era ajeno antes del retiro), el propietario del token puede impugnar el retiro dentro de un plazo de dos semanas.<\/p>\n<p><img decoding=\"async\" alt=\"Prueba p\u00fablica: soluci\u00f3n para la privacidad y escalabilidad en Ethereum\" src=\"\/wp-content\/uploads\/2019\/10\/0626ca6b010eb847175dbfb0b6d7b357.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h2>La privacidad se logra de dos maneras<\/h2>\n<p>\n<b>1. <\/b>La cadena ra\u00edz no conoce las transacciones que se generan y env\u00edan dentro de la cadena secundaria. La informaci\u00f3n p\u00fablica se mantiene sobre qui\u00e9n ingres\u00f3 y retir\u00f3 ETH en\/desde Plasma Cash.<\/p>\n<p><b>2. <\/b>La cadena secundaria permite organizar transacciones an\u00f3nimas utilizando zk-SNARKs.<\/p>\n<h2>Stack tecnol\u00f3gico<\/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>Pruebas <\/h2>\n<p>\nAl desarrollar Plasma Cash, probamos la velocidad del sistema y obtuvimos los siguientes resultados:<\/p>\n<ul>\n<li>hasta 35,000 transacciones por segundo se a\u00f1aden al pool;<\/li>\n<li>hasta 1,000,000 transacciones pueden almacenarse en un bloque.<\/li>\n<\/ul>\n<p>\nLas pruebas se llevaron a cabo en los siguientes 3 servidores:<\/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 Se levantaron 3 nodos validados de 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 Se levant\u00f3 un nodo de ETH en la testnet de Ropsten.<br \/>\n Se levantaron 3 nodos validados de 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 Se levant\u00f3 1 nodo de env\u00edo de Plasma Cash.<br \/>\n Se levantaron 3 nodos validados de Plasma Cash.<br \/>\n Se ejecut\u00f3 una prueba sobre el env\u00edo de transacciones en la red de Plasma Cash.<\/p>\n<p><b>Total: <\/b>10 nodos de Plasma Cash en una red privada.<\/p>\n<h3>Prueba 1<\/h3>\n<p>\nHay un l\u00edmite de 1 mill\u00f3n de transacciones por bloque. Por lo tanto, 1 mill\u00f3n de transacciones se dividen en 2 bloques (ya que el sistema puede tomar parte de las transacciones y enviarlas mientras se est\u00e1n enviando).<\/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=\"Reproducir video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nEstado inicial: bloque final #7; se han guardado 1 mill\u00f3n de transacciones y tokens en la base.<\/p>\n<p>00:00 \u2014 inicio del script de generaci\u00f3n de transacciones<br \/>\n01:37 \u2014 se han creado 1 mill\u00f3n de transacciones y se ha iniciado el env\u00edo al nodo<br \/>\n01:46 \u2014 el nodo de env\u00edo tom\u00f3 del pool 240k transacciones y est\u00e1 formando el bloque #8. Tambi\u00e9n vemos que se a\u00f1aden 320k transacciones al pool en 10 segundos<br \/>\n01:58 \u2014 bloque #8 firmado y enviado a validaci\u00f3n<br \/>\n02:03 \u2014 el bloque #8 ha sido validado y se ha llamado a la funci\u00f3n `submitBlock` del contrato inteligente con el hash de Merkle y el n\u00famero de bloque<br \/>\n02:10 \u2014 se ha terminado de ejecutar el script de demostraci\u00f3n, que envi\u00f3 1 mill\u00f3n de transacciones en 32 segundos<br \/>\n02:33 \u2014 los nodos han comenzado a recibir informaci\u00f3n sobre que el bloque #8 se ha agregado a la cadena ra\u00edz y han comenzado a procesar 240 mil transacciones<br \/>\n02:40 \u2014 se han eliminado 240 mil transacciones del pool, que ya est\u00e1n en el bloque #8<br \/>\n02:56 \u2014 el nodo de env\u00edo tom\u00f3 del pool las restantes 760 mil transacciones y comenz\u00f3 a calcular el hash de Merkle y a firmar el bloque #9<br \/>\n03:20 \u2014 todos los nodos contienen 1 mill\u00f3n 240 mil transacciones y tokens<br \/>\n03:35 \u2014 el bloque #9 ha sido firmado y se env\u00eda a validaci\u00f3n a otros nodos <br \/>\n03:41 \u2014 ocurri\u00f3 un error de red<br \/>\n04:40 \u2014 se ha agotado el tiempo de espera para la validaci\u00f3n del bloque #9<br \/>\n04:54 \u2014 el nodo de env\u00edo tom\u00f3 del pool las restantes 760 mil transacciones y comenz\u00f3 a calcular el hash de Merkle y a firmar el bloque #9<br \/>\n05:32 \u2014 el bloque #9 ha sido firmado y se env\u00eda a validaci\u00f3n a otros nodos<br \/>\n05:53 \u2014 el bloque #9 ha sido validado y enviado a la cadena ra\u00edz<br \/>\n06:17 \u2014 los nodos han comenzado a recibir informaci\u00f3n sobre que el bloque #9 se ha agregado a la cadena ra\u00edz y han comenzado a procesar 760 mil transacciones<br \/>\n06:47 \u2014 el pool se ha limpiado de las transacciones en el bloque #9<br \/>\n09:06 \u2014 todos los nodos contienen 2 millones de transacciones y tokens<\/p>\n<h3>Test 2<\/h3>\n<p>\nHay un l\u00edmite de 350k por bloque. Como resultado, tenemos 3 bloques.<\/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=\"Reproducir video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nEstado inicial: \u00faltimo bloque #9; en la base se han guardado 2 millones de transacciones y tokens<\/p>\n<p>00:00 \u2014 el script de generaci\u00f3n de transacciones ya est\u00e1 en ejecuci\u00f3n<br \/>\n00:44 \u2014 se han creado 1 mill\u00f3n de transacciones y se ha comenzado a enviarlas al nodo<br \/>\n00:56 \u2014 el nodo de env\u00edo tom\u00f3 del pool 320 mil transacciones y est\u00e1 formando el bloque #10. Tambi\u00e9n vemos que se agregan 320 mil transacciones al pool en 10 segundos<br \/>\n01:12 \u2014 el bloque #10 ha sido firmado y se env\u00eda a otros nodos para validaci\u00f3n<br \/>\n01:18 \u2014 se ha terminado de ejecutar el script de demostraci\u00f3n, que envi\u00f3 1 mill\u00f3n de transacciones en 34 segundos<br \/>\n01:20 \u2014 el bloque #10 ha sido validado y enviado a la cadena ra\u00edz <br \/>\n01:51 \u2014 todos los nodos han recibido de la cadena ra\u00edz informaci\u00f3n sobre que el bloque #10 ha sido agregado, y comienzan a aplicar 320 mil transacciones<br \/>\n02:01 \u2014 el pool se ha limpiado de 320 mil transacciones, que fueron agregadas al bloque #10<br \/>\n02:15 \u2014 el nodo de env\u00edo tom\u00f3 del pool 350 mil transacciones y est\u00e1 formando el bloque #11<br \/>\n02:34 \u2014 el bloque #11 ha sido firmado y se env\u00eda a otros nodos para validaci\u00f3n<br \/>\n02:51 \u2014 el bloque #11 ha sido validado y enviado a la cadena ra\u00edz <br \/>\n02:55 \u2014 el \u00faltimo nodo ha completado las transacciones del bloque #10<br \/>\n10:59 \u2014 se ha tardado mucho en procesar la transacci\u00f3n en la cadena ra\u00edz con la presentaci\u00f3n del bloque #9, pero se complet\u00f3 y todos los nodos recibieron la informaci\u00f3n y comenzaron a procesar 350k transacciones.<br \/>\n11:05 \u2014 el pool se ha limpiado de 320k transacciones, que se a\u00f1adieron al bloque #11.<br \/>\n12:10 \u2014 todos los nodos contienen 1 mill\u00f3n 670k transacciones y tokens.<br \/>\n12:17 \u2014 el nodo de presentaci\u00f3n tom\u00f3 del pool 330k transacciones y est\u00e1 formando el bloque #12.<br \/>\n12:32 \u2014 el bloque #12 ha sido firmado y se env\u00eda a otros nodos para validaci\u00f3n.<br \/>\n12:39 \u2014 el bloque #12 fue validado y enviado a la cadena ra\u00edz. <br \/>\n13:44 \u2014 todos los nodos recibieron de la cadena ra\u00edz la informaci\u00f3n de que el bloque #12 fue a\u00f1adido y comienzan a aplicar 330k transacciones.<br \/>\n14:50 \u2014 todos los nodos contienen 2 millones de transacciones y tokens.<\/p>\n<h3>Prueba 3.<\/h3>\n<p>\nEn el primer y segundo servidor, un nodo validante fue reemplazado por un nodo de presentaci\u00f3n. <\/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=\"Reproducir video\" loading=\"lazy\" width=\"480\" height=\"360\" style=\"width:100%;height:auto;\">\r\n        <div class=\"play-button\"><\/div>\r\n    <\/div><\/center><br \/>\nEstado inicial: \u00faltimo bloque #84; en la base se han guardado 0 transacciones y tokens.<\/p>\n<p>00:00 \u2014 Se han iniciado 3 scripts que generan y env\u00edan 1 mill\u00f3n de transacciones cada uno.<br \/>\n01:38 \u2014 se han creado 1 mill\u00f3n de transacciones y comenz\u00f3 el env\u00edo al nodo de presentaci\u00f3n #3.<br \/>\n01:50 \u2014 el nodo de presentaci\u00f3n #3 tom\u00f3 del pool 330k transacciones y est\u00e1 formando el bloque #85 (f21). Tambi\u00e9n vemos que se a\u00f1aden 350k transacciones al pool en 10 segundos.<br \/>\n01:53 \u2014 se han creado 1 mill\u00f3n de transacciones y comenz\u00f3 el env\u00edo al nodo de presentaci\u00f3n #1.<br \/>\n01:50 \u2014 el nodo de presentaci\u00f3n #3 tom\u00f3 del pool 330k transacciones y est\u00e1 formando el bloque #85 (f21). Tambi\u00e9n vemos que se a\u00f1aden 350k transacciones al pool en 10 segundos.<br \/>\n02:01 \u2014 el nodo de presentaci\u00f3n #1 tom\u00f3 del pool 250k transacciones y est\u00e1 formando el bloque #85 (65e).<br \/>\n02:06 \u2014 el bloque #85 (f21) ha sido firmado y se env\u00eda a otros nodos para validaci\u00f3n.<br \/>\n02:08 \u2014 ha finalizado la ejecuci\u00f3n del script demo del servidor #3, que envi\u00f3 1 mill\u00f3n de transacciones en 30 segundos.<br \/>\n02:14 \u2014 el bloque #85 (f21) fue validado y enviado a la cadena ra\u00edz. <br \/>\n02:19 \u2014 el bloque #85 (65e) ha sido firmado y se env\u00eda a otros nodos para validaci\u00f3n.<br \/>\n02:22 \u2014 se han creado 1 mill\u00f3n de transacciones y comenz\u00f3 el env\u00edo al nodo de presentaci\u00f3n #2.<br \/>\n02:27 \u2014 el bloque #85 (65e) fue validado y enviado a la cadena ra\u00edz. <br \/>\n02:29 \u2014 el nodo de presentaci\u00f3n #2 tom\u00f3 del pool 111855 transacciones y est\u00e1 formando el bloque #85 (256).<br \/>\n02:36 \u2014 el bloque #85 (256) ha sido firmado y se env\u00eda a otros nodos para validaci\u00f3n.<br \/>\n02:36 \u2014 ha finalizado la ejecuci\u00f3n del script demo del servidor #1, que envi\u00f3 1 mill\u00f3n de transacciones en 42.5 segundos.<br \/>\n02:38 \u2014 el bloque #85 (256) fue validado y enviado a la cadena ra\u00edz.<br \/>\n03:08 \u2014 ha finalizado la ejecuci\u00f3n del script demo del servidor #2, que envi\u00f3 1 mill\u00f3n de transacciones en 47 segundos. <br \/>\n03:38 \u2014 todos los nodos recibieron de la cadena ra\u00edz la informaci\u00f3n de que los bloques #85 (f21), #86(65e), #87(256) fueron a\u00f1adidos y comienzan a aplicar 330k, 250k, 111855 transacciones.<br \/>\n03:49 \u2014 el pool se limpi\u00f3 de 330k, 250k, 111855 transacciones, que fueron a\u00f1adidas a los bloques #85 (f21), #86(65e), #87(256)<br \/>\n03:59 \u2014 el submit del nodo #1 tom\u00f3 888145 transacciones del pool y est\u00e1 formando el bloque #88 (214), el submit del nodo #2 tom\u00f3 del pool 750k transacciones y est\u00e1 formando el bloque #88 (50a), el submit del nodo #3 tom\u00f3 670k transacciones del pool y est\u00e1 formando el bloque #88 (d3b)<br \/>\n04:44 \u2014 el bloque #88 (d3b) ha sido firmado y se env\u00eda a otros nodos para validaci\u00f3n<br \/>\n04:58 \u2014 el bloque #88 (214) ha sido firmado y se env\u00eda a otros nodos para validaci\u00f3n<br \/>\n05:11 \u2014 el bloque #88 (50a) ha sido firmado y se env\u00eda a otros nodos para validaci\u00f3n<br \/>\n05:11 \u2014 el bloque #85 (d3b) ha sido validado y enviado a la cadena ra\u00edz <br \/>\n05:36 \u2014 el bloque #85 (214) ha sido validado y enviado a la cadena ra\u00edz <br \/>\n05:43 \u2014 todos los nodos recibieron de la cadena ra\u00edz informaci\u00f3n sobre que los bloques #88 (d3b), #89(214) han sido a\u00f1adidos y comienzan a aplicar 670k, 750k transacciones<br \/>\n06:50 \u2014 debido a la interrupci\u00f3n de la conexi\u00f3n, el bloque #85 (50a) no fue validado<br \/>\n06:55 \u2014 el submit del nodo #2 tom\u00f3 888145 transacciones del pool y est\u00e1 formando el bloque #90 (50a)<br \/>\n08:14 \u2014 el bloque #90 (50a) ha sido firmado y se env\u00eda a otros nodos para validaci\u00f3n<br \/>\n09:04 \u2014 el bloque #90 (50a) ha sido validado y enviado a la cadena ra\u00edz <br \/>\n11:23 \u2014 todos los nodos recibieron de la cadena ra\u00edz informaci\u00f3n de que el bloque #90 (50a) ha sido a\u00f1adido, y comienzan a aplicar 888145 transacciones. A su vez, el servidor #3 ya hab\u00eda aplicado transacciones de los bloques #88 (d3b), #89(214)<br \/>\n12:11 \u2014 todos los pools est\u00e1n vac\u00edos<br \/>\n13:41 \u2014 todos los nodos del servidor #3 contienen 3 millones de transacciones y tokens<br \/>\n14:35 \u2014 todos los nodos del servidor #1 contienen 3 millones de transacciones y tokens<br \/>\n19:24 \u2014 todos los nodos del servidor #2 contienen 3 millones de transacciones y tokens <\/p>\n<h2>Obst\u00e1culos<\/h2>\n<p>\nDurante el desarrollo de Plasma Cash, nos enfrentamos a los siguientes problemas, que hemos resuelto y continuamos resolviendo:<\/p>\n<p><b>1.<\/b> Conflicto en la interacci\u00f3n de diversas funciones del sistema. Por ejemplo, la funci\u00f3n de a\u00f1adir transacciones al pool bloqueaba el trabajo de submit y validaci\u00f3n de bloques, y viceversa, lo que llevaba a una disminuci\u00f3n de la velocidad.<\/p>\n<p><b>2. <\/b>No estaba claro c\u00f3mo enviar una gran cantidad de transacciones y al mismo tiempo minimizar los costos de transmisi\u00f3n de datos.<\/p>\n<p><b>3. <\/b>No estaba claro c\u00f3mo y d\u00f3nde almacenar los datos para alcanzar altos resultados.<\/p>\n<p><b>4. <\/b>No estaba claro c\u00f3mo organizar la red entre los nodos, ya que el tama\u00f1o de un bloque con 1 mill\u00f3n de transacciones ocupa alrededor de 100 MB.<\/p>\n<p><b>5.<\/b> El funcionamiento en modo de un solo hilo rompe la conexi\u00f3n entre los nodos cuando se llevan a cabo c\u00e1lculos prolongados (por ejemplo, la construcci\u00f3n del \u00e1rbol Merkle y el c\u00e1lculo de su hash).<\/p>\n<h2>\u00bfC\u00f3mo manejamos todo esto?<\/h2>\n<p>\nLa primera versi\u00f3n del nodo de Plasma Cash era una especie de combinaci\u00f3n que pod\u00eda hacer todo simult\u00e1neamente: aceptar transacciones, enviar y validar bloques, y proporcionaba una API para acceder a los datos. Dado que NodeJS es originalmente de un solo hilo, la funci\u00f3n pesada de c\u00e1lculo del \u00e1rbol Merkle bloqueaba la funci\u00f3n de adici\u00f3n de transacciones. Vimos dos opciones para resolver este problema:<\/p>\n<p><b>1. <\/b>Ejecutar varios procesos de NodeJS, cada uno de los cuales realiza funciones espec\u00edficas.<\/p>\n<p><b>2. <\/b>Utilizar worker_threads y trasladar la ejecuci\u00f3n de parte del c\u00f3digo a hilos.<\/p>\n<p>Al final, utilizamos ambas opciones al mismo tiempo: dividimos l\u00f3gicamente un nodo en 3 partes que pueden funcionar por separado, pero a la vez de forma sincr\u00f3nica.<\/p>\n<p><b>1.<\/b> Nodo de env\u00edo, que acepta transacciones en el pool y se encarga de la creaci\u00f3n de bloques.<\/p>\n<p><b>2.<\/b> Nodo de validaci\u00f3n, que verifica la validez de los nodos.<\/p>\n<p><b>3. <\/b>Nodo API, que proporciona una API para acceder a los datos.<\/p>\n<p>Adem\u00e1s, se puede conectar a cada nodo a trav\u00e9s de un socket unix mediante cli.<\/p>\n<p>Las operaciones pesadas, como el c\u00e1lculo del \u00e1rbol Merkle, las trasladamos a un hilo separado.<\/p>\n<p>De esta manera, logramos que todas las funciones de Plasma Cash funcionen simult\u00e1neamente y sin fallas.<\/p>\n<p>Una vez que el sistema comenz\u00f3 a funcionar funcionalmente, comenzamos a probar la velocidad y, desafortunadamente, obtuvimos resultados insatisfactorios: 5,000 transacciones por segundo y hasta 50,000 transacciones por bloque. Tuvimos que averiguar qu\u00e9 se hab\u00eda implementado incorrectamente.<\/p>\n<p>Primero, comenzamos a probar el mecanismo de comunicaci\u00f3n con Plasma Cash para descubrir la capacidad m\u00e1xima del sistema. Anteriormente, mencionamos que el nodo de Plasma Cash proporciona una interfaz de socket unix. Inicialmente era de texto. Los objetos json se enviaban utilizando `JSON.parse()` y `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>\nMedimos la velocidad de transferencia de tales objetos y obtuvimos ~ 130k por segundo. Intentamos reemplazar las funciones est\u00e1ndar para trabajar con JSON, pero no mejor\u00f3 el rendimiento. Debe ser que el motor V8 est\u00e1 bien optimizado para estas operaciones.<\/p>\n<p>El trabajo con transacciones, tokens y bloques se realiz\u00f3 a trav\u00e9s de clases. Al crear tales clases, el rendimiento se redujo a la mitad, lo que indica que la POO no nos conviene. Tuvimos que reescribir todo en un enfoque puramente funcional.<\/p>\n<h2>Escritura en la base de datos<\/h2>\n<p>\nInicialmente, elegimos Redis para el almacenamiento de datos como una de las soluciones m\u00e1s eficientes que satisface nuestros requisitos: almacenamiento key-value, trabajo con tablas hash, conjuntos. Ejecutamos redis-benchmark y obtuvimos ~80k operaciones por segundo en modo de 1 pipelining.<\/p>\n<p>Para un alto rendimiento, configuramos Redis m\u00e1s finamente: <\/p>\n<ul>\n<li>Establecimos conexi\u00f3n por socket unix.<\/li>\n<li>Desactivamos el guardado de estado en disco (para mayor fiabilidad, se puede configurar una r\u00e9plica y realizar el guardado en disco en un Redis separado).<\/li>\n<\/ul>\n<p>\nEn Redis, el pool es una tabla hash, ya que necesitamos la capacidad de obtener todas las transacciones en una sola solicitud y eliminar transacciones individualmente. Intentamos usar una lista com\u00fan, pero funcionaba m\u00e1s lentamente al descargar toda la lista. <\/p>\n<p>Al utilizar la biblioteca est\u00e1ndar de NodeJS para Redis, obtuvimos un rendimiento de 18k transacciones por segundo. La velocidad cay\u00f3 9 veces. <\/p>\n<p>Dado que el benchmark nos mostraba capacidades claramente 5 veces mayores, comenzamos a optimizar. Cambiamos la biblioteca a ioredis y logramos un rendimiento de 25k por segundo. Agregamos las transacciones una a una, usando el comando `hset`. De esta manera, generamos muchas solicitudes a Redis. Surgi\u00f3 la idea de agrupar transacciones en lotes y enviarlas con un solo comando `hmset`. El resultado \u2014 32k por segundo. <\/p>\n<p>Por varias razones que describiremos a continuaci\u00f3n, trabajamos con los datos utilizando `Buffer` y, como result\u00f3, si lo convertimos a texto (`buffer.toString('hex')`) antes de escribir, podemos obtener un rendimiento adicional. De esta manera, la velocidad se pudo aumentar hasta 35k por segundo. Por el momento, decidimos suspender la optimizaci\u00f3n adicional.<\/p>\n<p>Tuvimos que pasar al protocolo binario porque:<\/p>\n<p><b>1. <\/b>El sistema a menudo calcula hashes, firmas, etc., y para ello necesita los datos en `Buffer.<\/p>\n<p><b>2.<\/b> Al transferir entre servicios, los datos binarios pesan menos que el texto. Por ejemplo, al enviar un bloque con 1 mill\u00f3n de transacciones, los datos en texto pueden ocupar m\u00e1s de 300 megabytes.<\/p>\n<p><b>3.<\/b> La conversi\u00f3n constante de datos afecta al rendimiento.<\/p>\n<p>Por lo tanto, tomamos como base nuestro propio protocolo binario de almacenamiento y transmisi\u00f3n de datos, desarrollado sobre la maravillosa biblioteca `binary-data`.<\/p>\n<p>Como resultado, obtuvimos las siguientes estructuras de datos:<\/p>\n<h3> \u2014 Transacci\u00f3n<\/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 Bloque<\/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 los comandos `BD.encode(block, Protocol).slice();` y ` BD.decode(buffer, Protocol)` transformamos los datos en un `Buffer` para guardarlos en Redis o enviarlos a otro nodo y extraer los datos de nuevo.<\/p>\n<p>Tambi\u00e9n tenemos 2 protocolos binarios para la transmisi\u00f3n de datos entre servicios:<\/p>\n<p><i> \u2014 Protocolo para interactuar con Plasma Node a trav\u00e9s de un socket unix<\/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 donde:<\/p>\n<ul>\n<li> <b>`type`<\/b> \u2014 acci\u00f3n que debe realizarse, por ejemplo, 1 \u2014 sendTransaction, 2 \u2014 getTransaction;<\/li>\n<li> <b>`payload`<\/b> \u2014 datos que deben ser enviados a la funci\u00f3n correspondiente;<\/li>\n<li> <b>`messageId`<\/b> \u2014 ID del mensaje para que se pueda identificar la respuesta. <\/li>\n<\/ul>\n<p>\n<i> \u2014 Protocolo de interacci\u00f3n entre nodos<\/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 donde:<\/p>\n<ul>\n<li> <b>`code`<\/b> \u2014 c\u00f3digo del mensaje, por ejemplo 6 \u2014 PREPARE_NEW_BLOCK, 7 \u2014 BLOCK_VALID, 8 \u2014 BLOCK_COMMIT;<\/li>\n<li> <b>`versionProtocol`<\/b> \u2014 versi\u00f3n del protocolo, ya que en la red pueden haber nodos con diferentes versiones y pueden funcionar de manera distinta;<\/li>\n<li> <b>`seq`<\/b> \u2014 identificador del mensaje;<\/li>\n<li> <b>`countChunk`<\/b> y <b>`chunkNumber`<\/b> necesarios para fragmentar grandes mensajes;<\/li>\n<li> <b>`length`<\/b> y <b>`payload`<\/b> longitud y los propios datos.<\/li>\n<\/ul>\n<p>\nDado que tipificamos los datos de antemano, el sistema final funciona mucho m\u00e1s r\u00e1pido que la biblioteca `rlp` de Ethereum. Desafortunadamente, a\u00fan no hemos podido prescindir de ella, ya que es necesario mejorar el contrato inteligente, lo que planeamos hacer en el futuro.<\/p>\n<p>Si hemos logrado alcanzar una velocidad <b>35 000<\/b> de transacciones por segundo, tambi\u00e9n necesitamos procesarlas en el tiempo \u00f3ptimo. Dado que el tiempo aproximado para la formaci\u00f3n de un bloque es de 30 segundos, necesitamos incluir en el bloque <b>1 000 000<\/b> transacciones, lo que significa enviar m\u00e1s de <b>100<\/b> MB de datos. <\/p>\n<p>Inicialmente, utilizamos la biblioteca `ethereumjs-devp2p` para la comunicaci\u00f3n entre nodos, pero no manejaba tal cantidad de datos. Como resultado, utilizamos la biblioteca `ws` y configuramos el env\u00edo de datos binarios a trav\u00e9s de websocket. Por supuesto, tambi\u00e9n encontramos problemas al enviar grandes paquetes de datos, pero los dividimos en fragmentos y ahora no hay esos problemas.<\/p>\n<p>Adem\u00e1s, la formaci\u00f3n del \u00e1rbol de Merkle y el c\u00e1lculo del hash <b>1 000 000<\/b> de las transacciones requiere alrededor de<b> 10<\/b> segundos de c\u00e1lculo continuo. Durante este tiempo, la conexi\u00f3n con todos los nodos puede interrumpirse. Se decidi\u00f3 trasladar este c\u00e1lculo a un hilo separado.<\/p>\n<h2>Conclusiones:<\/h2>\n<p>\nDe hecho, nuestras conclusiones no son nuevas, pero por alguna raz\u00f3n muchos especialistas las olvidan al desarrollar. <\/p>\n<ul>\n<li>Usar Programaci\u00f3n Funcional en lugar de Programaci\u00f3n Orientada a Objetos aumenta el rendimiento.<\/li>\n<li>Un monolito es peor que una arquitectura de servicios para un sistema de alto rendimiento en NodeJS.<\/li>\n<li>Usar `worker_threads` para c\u00e1lculos pesados mejora la capacidad de respuesta del sistema, especialmente al trabajar con operaciones de i\/o.<\/li>\n<li>El socket unix es m\u00e1s estable y r\u00e1pido que las solicitudes http.<\/li>\n<li>Si se necesitan transferir grandes datos r\u00e1pidamente a trav\u00e9s de la red, es mejor usar websockets y enviar datos binarios divididos en fragmentos, que se pueden re-enviar si no llegan, y luego combinarlos en un solo mensaje.<\/li>\n<\/ul>\n<p>\nTe invitamos a visitar <b>GitHub<\/b> el proyecto: <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>El art\u00edculo fue escrito en colaboraci\u00f3n con <i>Alexander Nashivan<\/i>, desarrollador senior de <noindex><a rel=\"nofollow\" href=\"https:\/\/clever-solution.com\/\">Clever Solution Inc<\/a><\/noindex>.<br \/>\n<br \/>Fuente: <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.2 - 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\/es\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\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\/es\/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\udd47Prueba p\u00fablica: soluci\u00f3n para la privacidad y escalabilidad en Ethereum | ProHoster","description":"La blockchain es una tecnolog\u00eda innovadora que promete mejorar muchas \u00e1reas de la vida humana.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/publichnyj-test-reshenie-dlya-privatnosti-i-masshtabiruemosti-v-efiriume","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","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\/es\/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\/es\/wp-json\/wp\/v2\/posts\/38856","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=38856"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/38856\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/29146"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=38856"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=38856"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=38856"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}