O Livro Branco do NEAR
Validez del estado y disponibilidad de datos
La idea central en blockchains fragmentados es que la mayoría de los participantes que operan o el uso de la red no puede validar bloques en todos los fragmentos. Como tal, siempre que cualquier participante necesita interactuar con un fragmento en particular que generalmente no puede descargue y valide el historial completo del fragmento. El aspecto de partición de la fragmentación, sin embargo, plantea un potencial significativo problema: sin descargar y validar el historial completo de un determinado fragmento, el participante no puede necesariamente estar seguro de que el estado con el que 5Esta sección, excepto la subsección 2.5.3, se publicó anteriormente en https://near.ai/ fragmento2. Si lo leíste antes, salta a la siguiente sección.
interactúan es el resultado de alguna secuencia válida de bloques y que dicha secuencia de bloques es de hecho la cadena canónica en el fragmento. Un problema que no existe en un blockchain no fragmentado. Primero presentaremos una solución simple a este problema que ha sido propuesta. por muchos protocolos y luego analizar cómo esta solución puede romperse y qué se han hecho intentos para abordarlo. 2.1 Rotación de validadores La solución ingenua a la validez del estado se muestra en la figura 5: digamos que asumimos que todo el sistema tiene del orden de miles de validators, de los cuales no más del 20% son maliciosos o fallarán de otra manera (por ejemplo, al no ser en línea para producir un bloque). Entonces, si tomamos una muestra de 200 validators, la probabilidad de más de 1 3 reprobados a efectos prácticos se puede suponer que es cero. Figura 5: Muestreo validators 1 3 es un umbral importante. Existe una familia de protocolos de consenso, llamados BFT protocolos de consenso, que garantizan que mientras menos de 1 3 de los participantes fallan, ya sea al estrellarse o al actuar de alguna manera que viole las protocolo, se alcanzará el consenso. Con esta suposición de porcentaje honesto validator, si el conjunto actual de validators en un fragmento nos proporciona algún bloque, la solución ingenua supone que el bloque es válido y que está construido sobre lo que los validators creían que era la cadena canónica para ese fragmento cuando comenzaron a validar. Los validators aprendió la cadena canónica del conjunto anterior de validators, quienes por el mismo suposición construida sobre el bloque que era la cabeza de la cadena canónica antes de eso. Por inducción toda la cadena es válida y dado que no hay un conjunto de validators en cualquier momento se producen bifurcaciones, la solución ingenua también es segura de que la corriente chain es la única cadena en el fragmento. Consulte la figura 6 para obtener una visualización.
Figura 6: Un blockchain con cada bloque finalizado mediante el consenso BFT Esta solución simple no funciona si asumimos que los validators pueden ser corrompidos adaptativamente, lo cual no es una suposición descabellada6. Adaptablemente corromper un solo fragmento en un sistema con 1000 fragmentos es significativamente más barato que corromper todo el sistema. Por tanto, la seguridad del protocolo disminuye linealmente con el número de fragmentos. Para tener certeza en la validez de un bloque, debemos saber que en cualquier momento de la historia ningún fragmento del sistema ha una mayoría de validators en connivencia; con adversarios adaptativos, ya no tenemos tal certeza. Como comentamos en la sección 1.5, los validator en colusión pueden ejercer dos comportamientos maliciosos básicos: crear bifurcaciones y producir bloques no válidos. Las bifurcaciones maliciosas pueden abordarse mediante bloques que se entrecruzan con la cadena Beacon, que generalmente está diseñada para tener una seguridad significativamente mayor que la cadena Beacon. las cadenas de fragmentos. Sin embargo, producir bloques no válidos es una tarea mucho más problema desafiante de abordar. 2.2 Validez del estado Considere la figura 7 en la que el fragmento #1 está dañado y un actor malicioso produce bloque B no válido. Supongamos que en este bloque B se acuñaron 1000 tokens de la nada aire en la cuenta de Alice. El actor malintencionado produce entonces un bloque C válido (en un sentido de que las transacciones en C se aplican correctamente) encima de B, ofuscando el bloque B no válido e inicia una transacción entre fragmentos al fragmento #2 que transfiere esos 1000 tokens a la cuenta de Bob. A partir de este momento el mal Los token creados residen en un blockchain completamente válido en el fragmento #2. Algunos enfoques simples para abordar este problema son: 6Leer esto artículo para detalles en como adaptativo corrupción puede ser llevado fuera: https://medium.com/nearprotocol/d859adb464c8. Para más detalles en adaptativo corrupción, leer https://github.com/ethereum/wiki/wiki/Sharding-FAQ# ¿Cuáles-son-los-modelos-de-seguridad-bajo-los-que-estamos-operando?Figura 7: Una transacción entre fragmentos de una cadena que tiene un bloque no válido 1. Para validators del fragmento #2 para validar el bloque desde el cual se realizó la transacción se inicia. Esto no funcionará ni siquiera en el ejemplo anterior, ya que el bloque C parece ser completamente válido. 2. Para validators en el fragmento #2 para validar una gran cantidad de bloques que preceden al bloque desde el cual se inicia la transacción. Naturalmente, para cualquier número de bloques N validados por el fragmento receptor el malicioso validators pueden crear N+1 bloques válidos además del bloque no válido que producido. Una idea prometedora para resolver este problema sería organizar los fragmentos en un gráfico no dirigido en el que cada fragmento está conectado a varios otros fragmentos, y solo permitir transacciones entre fragmentos entre fragmentos vecinos (por ejemplo, así es como La fragmentación de Vlad Zamfir esencialmente funciona7, y una idea similar se utiliza en la de Kadena. Chainweb [1]). Si se necesita una transacción entre fragmentos entre fragmentos que están no vecinos, dicha transacción se enruta a través de múltiples fragmentos. en este diseño Se espera que un validator en cada fragmento valide todos los bloques en su fragmento así como todos los bloques en todos los fragmentos vecinos. Considere una figura a continuación con 10 fragmentos, cada uno con cuatro vecinos y no hay dos fragmentos que requieran más de dos saltos para una comunicación entre fragmentos como se muestra en la figura 8. El fragmento #2 no solo valida su propio blockchain, sino también los blockchains de todos los vecinos, incluido el fragmento n.° 1. Entonces, si un actor malicioso en el fragmento #1 está intentando crear un bloque B no válido, luego construye el bloque C encima de él e inicia una transacción entre fragmentos, dicha transacción entre fragmentos no se realizará desde el Fragmento #2 habrá validado toda la historia del Fragmento #1 que hará que identifique el bloque B no válido. 7Lea más sobre el diseño aquí: https://medium.com/nearprotocol/37e538177ed9
Figura 8: Una transacción entre fragmentos no válida en un sistema tipo cadena web que ser detectado Si bien corromper un único fragmento ya no es un ataque viable, corromper un pocos fragmentos siguen siendo un problema. En la figura 9, un adversario corrompiendo ambos Shard
1 y el fragmento #2 ejecutan con éxito una transacción entre fragmentos al fragmento #3
con fondos de un bloque B no válido: Figura 9: Una transacción entre fragmentos no válida en un sistema tipo cadena web que no ser detectado El fragmento n.º 3 valida todos los bloques del fragmento n.º 2, pero no del fragmento n.º 1, y no tiene forma de detectar el bloque malicioso. Hay dos direcciones principales para resolver adecuadamente la validez estatal: los pescadores
y pruebas criptográficas de cómputo. 2.3 pescador La idea detrás del primer enfoque es la siguiente: siempre que un encabezado de bloque se comunica entre cadenas para cualquier propósito (como el enlace cruzado con el cadena de baliza, o una transacción entre fragmentos), hay un período de tiempo durante cual cualquier validator honesto puede proporcionar una prueba de que el bloqueo no es válido. allí Hay varias construcciones que permiten pruebas muy sucintas de que los bloques son no válido, por lo que la sobrecarga de comunicación para los nodos receptores es mucho menor que el de recibir un bloqueo completo. Con este enfoque, siempre que haya al menos un validator honesto en el fragmento, el sistema es seguro. Figura 10: pescador Este es el enfoque dominante (además de fingir que el problema no existe) entre los protocolos propuestos hoy. Este enfoque, sin embargo, tiene dos principales desventajas: 1. El período de desafío debe ser lo suficientemente largo para el validator honesto. para reconocer que se produjo un bloque, descargarlo, verificarlo completamente y preparar el desafío si el bloque no es válido. La introducción de ese período ralentizar significativamente las transacciones entre fragmentos. 2. La existencia del protocolo de desafío crea un nuevo vector de ataques cuando los nodos maliciosos envían spam con desafíos no válidos. Una solución obvia a este problema es hacer que los retadores depositen una cierta cantidad de tokens que se devuelven si el desafío es válido. Esta es sólo una solución parcial, ya que Todavía podría ser benéfico para el adversario enviar spam al sistema (y quemar los depósitos) con impugnaciones no válidas, por ejemplo para impedir la validezdesafío de un honesto validator de pasar. Estos ataques son llamados ataques de duelo. Consulte la sección 3.7.2 para conocer una forma de evitar este último punto. 2.4 Argumentos de conocimiento sucintos y no interactivos La segunda solución a la corrupción de múltiples fragmentos es utilizar algún tipo de construcción criptográfica que permita demostrar que un determinado cálculo (como como calcular un bloque a partir de un conjunto de transacciones) se realizó correctamente. Este tipo de construcciones existen, p. zk-SNARK, zk-STARK y algunos otros, y algunos se utilizan activamente en los protocolos blockchain actuales para pagos privados, más notablemente ZCash. El principal problema con tales primitivos es que son notoriamente lentos de calcular. P.ej. Protocolo Coda, que utiliza zk-SNARK específicamente para demostrar que todos los bloques en el blockchain son válidos, dijo en un de las entrevistas que puede tomar 30 segundos por transacción para crear una prueba (Este número probablemente sea menor ahora). Curiosamente, no es necesario que una parte de confianza calcule una prueba, ya que la prueba no sólo da fe de la validez del cálculo para el que está construida, sino también de la la validez de la prueba misma. Por tanto, el cálculo de tales pruebas se puede dividir entre un conjunto de participantes con significativamente menos redundancia de lo que sería necesario realizar algún cálculo sin confianza. También permite a los participantes que calculan zk-SNARK para ejecutarse en hardware especial sin reducir el descentralización del sistema. Los desafíos de los zk-SNARK, además del rendimiento, son: 1. Dependencia de primitivas criptográficas menos investigadas y menos probadas; 2. "Residuos tóxicos": los zk-SNARK dependen de una configuración confiable en la que un grupo de personas realiza algún cálculo y luego descarta el intermedio valores de ese cálculo. Si todos los participantes del procedimiento se confabulan y se mantienen los valores intermedios, se pueden crear pruebas falsas; 3. Se introduce complejidad adicional en el diseño del sistema; 4. Los zk-SNARK solo funcionan para un subconjunto de cálculos posibles, por lo que un protocolo con un lenguaje Turing completo smart contract no podría usar SNARK para demostrar la validez de la cadena. 2.5 Disponibilidad de datos El segundo problema que abordaremos es la disponibilidad de datos. Generalmente nodos que operan un blockchain particular se separan en dos grupos: nodos completos, aquellos que descargan cada bloque completo y validan cada transacción, y Light Nodos, aquellos que solo descargan encabezados de bloques y usan pruebas de Merkle para las partes del estado y las transacciones que les interesan, como se muestra en la figura 11.
Figura 11: árbol de merkle Ahora bien, si la mayoría de los nodos completos se confabulan, pueden producir un bloque, válido o no es válido y envía su hash a los nodos de luz, pero nunca revela el contenido completo del bloque. Hay varias maneras en que pueden beneficiarse de ello. Por ejemplo, considere la figura 12: Figura 12: Problema de disponibilidad de datos Hay tres bloques: el anterior, A, está producido por validators honestos; el actual, B, tiene validators en connivencia; y el siguiente, C, también se producirá por validators honestos (el blockchain se muestra en la esquina inferior derecha). Eres un comerciante. Los validators del bloque actual (B) recibieron el bloque A de los validators anteriores, calculó un bloque en el que recibe dinero,y le envié un encabezado de ese bloque con una prueba Merkle del estado en el que tiene dinero (o una prueba Merkle de una transacción válida que envía el dinero a ti). Con la seguridad de que la transacción está finalizada, usted brinda el servicio. Sin embargo, los validators nunca distribuyen el contenido completo del bloque B a cualquiera. Como tal, los validator__s honestos del bloque C no pueden recuperar el bloque y se ven obligados a detener el sistema o a construir sobre A, privándolo a usted como comerciante de dinero. Cuando aplicamos el mismo escenario a la fragmentación, las definiciones de completo y El nodo ligero generalmente se aplica por fragmento: validators en cada fragmento descarga cada bloquear en ese fragmento y validar cada transacción en ese fragmento, pero otros nodos del sistema, incluidos aquellos que capturan el estado de las cadenas de fragmentos en el cadena de balizas, descargue solo los encabezados. Por lo tanto, los validators en el fragmento son efectivamente nodos completos para ese fragmento, mientras que otros participantes en el sistema, incluida la cadena de balizas, funcionan como nodos luminosos. Para que funcione el enfoque del pescador que analizamos anteriormente, los validators honestos Debe poder descargar bloques que estén vinculados cruzadamente a la cadena de baliza. Si validators maliciosos vinculaban un encabezado de un bloque no válido (o lo usaban para iniciar una transacción entre fragmentos), pero nunca distribuyó el bloque, el honesto Los validators no tienen forma de crear un desafío. Cubriremos tres enfoques para abordar este problema que complementan unos a otros. 2.5.1 Pruebas de custodia El problema más inmediato a resolver es si un bloque está disponible una vez esta publicado. Una idea propuesta es tener los llamados Notarios que rotan entre fragmentos con más frecuencia que validators cuyo único trabajo es descargar un bloquear y dar fe de que pudieron descargarlo. pueden ser rotan con más frecuencia porque no necesitan descargar el estado completo del fragmento, a diferencia de los validators que no se pueden rotar con frecuencia ya que debe descargar el estado del fragmento cada vez que gira, como se muestra en la figura 13. El problema con este enfoque ingenuo es que es imposible demostrar más tarde si el Notario pudo o no descargar el bloque, por lo que un Notario pueden optar por dar fe siempre de que pudieron descargar el bloque sin incluso intentar recuperarlo. Una solución a esto es que los notarios proporcionen alguna evidencia o apostar alguna cantidad de tokens que acrediten que el bloque fue descargado. Una de esas soluciones se analiza aquí: https://ethresear.ch/t/ Bonos de custodia de 1 bit amigables con la agregación/2236. 2.5.2 Códigos de borrado Cuando un nodo de luz en particular recibe un hash de un bloque, para aumentar el valor del nodo Si está seguro de que el bloque está disponible, puede intentar descargar algunos archivos aleatorios. pedazos del bloque. Esta no es una solución completa, ya que a menos que los nodos de luz descargar colectivamente el bloque completo que los productores de bloques maliciosos pueden elegir
Figura 13: Los validadores necesitan descargar el estado y, por lo tanto, no se pueden rotar. frecuentemente retener las partes del bloque que no fueron descargadas por ningún nodo ligero, por lo que el bloque aún no está disponible. Una solución es utilizar una construcción llamada Códigos de borrado para que sea posible para recuperar el bloque completo incluso si solo una parte del bloque está disponible, como se muestra en la figura 14. Figura 14: Merkle tree construido sobre datos codificados de borrado Tanto Polkadot como Ethereum Serenity tienen diseños en torno a esta idea que Proporcionar una manera para que los nodos ligeros estén razonablemente seguros de que los bloques están disponibles. El enfoque Ethereum Serenity tiene una descripción detallada en [2].2.5.3 El enfoque de Polkadot respecto de la disponibilidad de datos En Polkadot, como en la mayoría de las soluciones fragmentadas, cada fragmento (llamado parachain) envía instantáneas de sus bloques a la cadena de baliza (llamada cadena de retransmisión). Digamos que hay 2f + 1 validators en la cadena de relés. Los productores de bloques de los bloques parachain, llamados Alzadores, una vez que se produce el bloque parachain, calcule una versión codificada de borrado del bloque que consta de 2f +1 partes, de modo que cualquier f partes sea suficiente. para reconstruir el bloque. Luego distribuyen una parte a cada validator en el cadena de relevo. Una cadena de retransmisión particular validator solo firmaría en una cadena de retransmisión bloque si tienen su parte para cada bloque de parachain que se captura en dicho bloque de cadena de relés. Por lo tanto, si un bloque de cadena de retransmisión tiene firmas de 2f + 1 validators, y mientras no más de f de ellos violen el protocolo, cada El bloque parachain se puede reconstruir obteniendo las piezas de validators. que siguen el protocolo. Ver figura 15. Figura 15: Disponibilidad de datos de Polkadot 2.5.4 Disponibilidad de datos a largo plazo Tenga en cuenta que todos los enfoques discutidos anteriormente solo dan fe del hecho de que un bloque se publicó y ya está disponible. Los bloques pueden dejar de estar disponibles más adelante por una variedad de razones: nodos que se desconectan, nodos que borran intencionalmente datos históricos datos, y otros. Un documento técnico que vale la pena mencionar y que aborda este problema es Polyshard [3], que utiliza códigos de borrado para hacer que los bloques estén disponibles en todos los fragmentos, incluso si hay varios Los fragmentos pierden completamente sus datos. Desafortunadamente, su enfoque específico requiere todos los fragmentos para descargar bloques de todos los demás fragmentos, lo cual es prohibitivamente caro. La disponibilidad a largo plazo no es un problema tan urgente: dado que ningún participante Se espera que el sistema sea capaz de validar todas las cadenas en todos los
fragmentos, la seguridad del protocolo fragmentado debe diseñarse de tal manera manera que el sistema sea seguro incluso si algunos bloques antiguos en algunos fragmentos se vuelven completamente no disponible.
Validade estadual e disponibilidade de dados
A ideia central em blockchains fragmentados é que a maioria dos participantes operando ou usar a rede não pode validar blocos em todos os shards. Como tal, sempre que qualquer participante precisa interagir com um fragmento específico, eles geralmente não podem baixe e valide todo o histórico do shard. O aspecto de particionamento do sharding, no entanto, levanta um potencial significativo problema: sem baixar e validar todo o histórico de um determinado fragmento, o participante não pode necessariamente ter certeza de que o estado com o qual 5Esta seção, exceto a subseção 2.5.3, foi publicada anteriormente em https://near.ai/ fragmento2. Se você leu antes, pule para a próxima seção.
eles interagem é o resultado de alguma sequência válida de blocos e que tal sequência de blocos é de fato a cadeia canônica no fragmento. Um problema que não existe em um blockchain não fragmentado. Apresentaremos primeiro uma solução simples para este problema que foi proposta por muitos protocolos e depois analisar como essa solução pode falhar e o que foram feitas tentativas para resolvê-lo. 2.1 Rotação de validadores A solução ingênua para a validade do estado é mostrada na figura 5: digamos que assumimos que todo o sistema possui da ordem de milhares de validators, dos quais não mais do que 20% são maliciosos ou irão falhar de outra forma (como por não serem online para produzir um bloco). Então, se amostrarmos 200 validators, a probabilidade de mais de 1 3 a falha para fins práticos pode ser assumida como zero. Figura 5: Amostragem de validators 1 3 é um limite importante. Existe uma família de protocolos de consenso, chamada BFT protocolos de consenso, que garantem que por menos de 1 3 de participantes falham, seja por bater ou por agir de alguma forma que viole o protocolo, o consenso será alcançado. Com esta suposição de porcentagem honesta de validator, se o conjunto atual de validators em um fragmento nos fornece algum bloqueio, a solução ingênua assume que o bloco é válido e que é construído sobre o que os validators acreditam ser a cadeia canônica desse fragmento quando eles começaram a validar. Os validators aprendeu a cadeia canônica do conjunto anterior de validators, que pelo mesmo suposição construída no topo do bloco que era o topo da cadeia canônica antes disso. Por indução, toda a cadeia é válida e, como nenhum conjunto de validators em qualquer ponto produziu garfos, a solução ingênua também é certa de que o atual chain é a única cadeia no fragmento. Veja a figura 6 para uma visualização.
Figura 6: Um blockchain com cada bloco finalizado via consenso BFT Esta solução simples não funciona se assumirmos que os validators podem ser corrompido adaptativamente, o que não é uma suposição irracional6. Adaptativamente corromper um único fragmento em um sistema com 1.000 fragmentos é significativamente mais barato do que corromper todo o sistema. Portanto, a segurança do protocolo diminui linearmente com o número de shards. Para ter certeza da validade um bloco, devemos saber que em qualquer momento da história nenhum fragmento do sistema foi a maioria dos validators conspirando; com adversários adaptativos, não temos mais tanta certeza. Como discutimos na seção 1.5, validators coniventes podem exercer dois comportamentos maliciosos básicos: criar bifurcações e produzir blocos inválidos. Forks maliciosos podem ser resolvidos por blocos interligados à cadeia Beacon, que geralmente é projetada para ter segurança significativamente maior do que as cadeias de fragmentos. Produzir blocos inválidos, no entanto, é uma tarefa significativamente mais problema desafiador para resolver. 2.2 Validade do Estado Considere a figura 7 na qual o fragmento nº 1 está corrompido e um agente malicioso produz bloco inválido B. Suponha que neste bloco B 1000 tokens foram cunhados ir ao ar por conta de Alice. O ator malicioso então produz o bloco C válido (em um sentido de que as transações em C são aplicadas corretamente) em cima de B, ofuscando o bloco inválido B e inicia uma transação entre fragmentos para o fragmento #2 que transfere esses 1.000 tokens para a conta de Bob. A partir deste momento o indevidamente tokens criados residem em um blockchain completamente válido no fragmento #2. Algumas abordagens simples para resolver esse problema são: 6Leia isso artigo para detalhes ligado como adaptativo corrupção pode ser carregado fora: https://medium.com/nearprotocol/d859adb464c8. Para mais detalhes ligado adaptativo corrupção, leia https://github.com/ethereum/wiki/wiki/Sharding-FAQ# quais são os modelos de segurança sob os quais estamos operandoFigura 7: Uma transação entre fragmentos de uma cadeia que possui um bloco inválido 1. Para validators do Shard #2 para validar o bloco do qual a transação é iniciado. Isso não funcionará nem no exemplo acima, pois o bloco C parece ser completamente válido. 2. Para validators no Shard #2 para validar um grande número de blocos anteriores ao bloco a partir do qual a transação é iniciada. Naturalmente, por qualquer número de blocos N validados pelo fragmento receptor do malicioso validators podem criar N+1 blocos válidos em cima do bloco inválido que eles produzido. Uma ideia promissora para resolver esse problema seria organizar os fragmentos em um gráfico não direcionado em que cada fragmento está conectado a vários outros fragmentos, e permitir apenas transações entre fragmentos vizinhos (por exemplo, é assim que A fragmentação de Vlad Zamfir funciona essencialmente7, e uma ideia semelhante é usada na fragmentação de Kadena. Chainweb [1]). Se uma transação entre fragmentos for necessária entre fragmentos que são não vizinhos, tal transação é roteada através de vários fragmentos. Neste projeto espera-se que um validator em cada fragmento valide todos os blocos em seu fragmento bem como todos os blocos em todos os fragmentos vizinhos. Considere uma figura abaixo com 10 fragmentos, cada um com quatro vizinhos, e não há dois fragmentos que exijam mais mais de dois saltos para uma comunicação entre fragmentos mostrada na figura 8. O fragmento nº 2 não está apenas validando seu próprio blockchain, mas também blockchains de todos os vizinhos, incluindo o Shard #1. Então, se um ator malicioso no Shard #1 está tentando criar um bloco B inválido e, em seguida, construir o bloco C sobre ele e iniciar uma transação entre fragmentos, tal transação entre fragmentos não ocorrerá desde o Shard #2 terá validado toda a história do Shard #1 que fará com que ele identifique o bloco B inválido. 7Leia mais sobre o design aqui: https://medium.com/nearprotocol/37e538177ed9
Figura 8: Uma transação cruzada inválida em um sistema tipo chainweb que irá ser detectado Embora corromper um único fragmento não seja mais um ataque viável, corromper um poucos fragmentos continuam sendo um problema. Na figura 9, um adversário corrompendo ambos os Shard
1 e Shard #2 executam com sucesso uma transação entre fragmentos para o Shard #3
com fundos de um bloco B inválido: Figura 9: Uma transação cruzada inválida em um sistema tipo chainweb que irá não ser detectado O Shard #3 valida todos os blocos no Shard #2, mas não no Shard #1, e não tem como detectar o bloco malicioso. Existem duas direções principais para resolver adequadamente a validade do estado: os pescadores
e provas criptográficas de computação. 2.3 Pescador A ideia por trás da primeira abordagem é a seguinte: sempre que um cabeçalho de bloco é comunicado entre cadeias para qualquer finalidade (como ligação cruzada com o cadeia de beacon ou uma transação entre fragmentos), há um período de tempo durante qual qualquer validator honesto pode fornecer uma prova de que o bloqueio é inválido. Lá são diversas construções que permitem provas muito sucintas de que os blocos são inválido, então a sobrecarga de comunicação para os nós receptores é bem menor do que receber um bloco completo. Com esta abordagem, enquanto houver pelo menos um validator honesto no fragmento, o sistema é seguro. Figura 10: Pescador Esta é a abordagem dominante (além de fingir que o problema não existe) entre os protocolos propostos hoje. Esta abordagem, no entanto, tem duas principais desvantagens: 1. O período de desafio precisa ser suficientemente longo para o honesto validator reconhecer que um bloco foi produzido, baixá-lo, verificá-lo completamente e preparar o desafio se o bloco for inválido. A introdução de tal período seria retardar significativamente as transações entre fragmentos. 2. A existência do protocolo de desafio cria um novo vetor de ataques quando nós maliciosos enviam spam com desafios inválidos. Uma solução óbvia para este problema é fazer com que os desafiantes depositem alguma quantia de tokens que são retornados se o desafio for válido. Esta é apenas uma solução parcial, pois ainda pode ser benéfico para o adversário enviar spam ao sistema (e queimar os depósitos) com desafios inválidos, por exemplo, para evitar o válidodesafio de um validator honesto de passar. Esses ataques são chamados ataques de luto. Consulte a seção 3.7.2 para saber como contornar o último ponto. 2.4 Argumentos de conhecimento sucintos e não interativos A segunda solução para a corrupção de múltiplos fragmentos é usar algum tipo de construção criptográfica que permita provar que um determinado cálculo (como como calcular um bloco de um conjunto de transações) foi realizado corretamente. Tais construções existem, por ex. zk-SNARKs, zk-STARKs e alguns outros, e alguns são usados ativamente em protocolos blockchain hoje para pagamentos privados, mais notavelmente ZCash. O principal problema com tais primitivas é que elas são notoriamente lentos para calcular. Por exemplo Protocolo Coda, que usa zk-SNARKs especificamente para provar que todos os blocos em blockchain são válidos, dito em um das entrevistas que pode levar 30 segundos por transação para criar uma prova (este número provavelmente é menor agora). Curiosamente, uma prova não precisa ser computada por uma parte confiável, uma vez que a prova não apenas atesta a validade do cálculo para o qual foi construída, mas também a validade da própria prova. Assim, o cálculo de tais provas pode ser dividido entre um conjunto de participantes com significativamente menos redundância do que seria necessário para realizar alguma computação sem confiança. Também permite aos participantes que computam zk-SNARKs para rodar em hardware especial sem reduzir o descentralização do sistema. Os desafios dos zk-SNARKs, além do desempenho, são: 1. Dependência de primitivas criptográficas menos pesquisadas e testadas ao longo do tempo; 2. “Resíduos tóxicos” – zk-SNARKs dependem de uma configuração confiável na qual um grupo de pessoas realiza alguns cálculos e depois descarta o intermediário valores desse cálculo. Se todos os participantes do procedimento conspirarem e manter os valores intermediários, podem ser criadas provas falsas; 3. Complexidade extra introduzida no design do sistema; 4. zk-SNARKs funcionam apenas para um subconjunto de cálculos possíveis, portanto, um protocolo com uma linguagem Turing-completa smart contract não seria capaz de usar SNARKs para provar a validade da cadeia. 2,5 Disponibilidade de dados O segundo problema que abordaremos é a disponibilidade de dados. Geralmente nós operando um determinado blockchain são separados em dois grupos: Full Nodes, aqueles que baixam cada bloco completo e validam cada transação, e Light Nós, aqueles que baixam apenas cabeçalhos de bloco e usam provas Merkle para peças do estado e das transações nas quais estão interessados, conforme mostrado na figura 11.
Figura 11: Árvore Merkel Agora, se a maioria dos nós completos conspirar, eles podem produzir um bloco, válido ou inválido e envia seu hash para os nós leves, mas nunca divulga o conteúdo completo do bloco. Existem várias maneiras pelas quais eles podem se beneficiar disso. Por exemplo, considere a figura 12: Figura 12: Problema de disponibilidade de dados Existem três blocos: o anterior, A, é produzido por validators honestos; o atual, B, tem validators conspirando; e o próximo, C, também será produzido por validators honestos (o blockchain está representado no canto inferior direito). Você é um comerciante. Os validators do bloco atual (B) receberam o bloco A dos validators anteriores, calculou um bloco no qual você recebe dinheiro,e enviei a você um cabeçalho desse bloco com uma prova Merkle do estado em que você tem dinheiro (ou uma prova Merkle de uma transação válida que envia o dinheiro para você). Confiante de que a transação foi finalizada, você fornece o serviço. Porém, os validators nunca distribuem o conteúdo completo do bloco B para qualquer um. Como tal, os validators honestos do bloco C não podem recuperar o bloco e são forçados a paralisar o sistema ou a construir em cima de A, privando você como comerciante de dinheiro. Quando aplicamos o mesmo cenário à fragmentação, as definições de completo e nó leve geralmente se aplica por fragmento: validators em cada download de fragmento a cada bloquear nesse fragmento e validar todas as transações nesse fragmento, mas outros nós no sistema, incluindo aqueles que capturam o estado das cadeias de fragmentos no cadeia de beacon, baixe apenas os cabeçalhos. Assim, os validators no fragmento são nós efetivamente completos para esse fragmento, enquanto outros participantes do sistema, incluindo a cadeia de beacon, operam como nós leves. Para que a abordagem do pescador que discutimos acima funcione, validators honestos precisa ser capaz de baixar blocos que estão interligados à cadeia de beacon. Se validators maliciosos vinculassem um cabeçalho de um bloco inválido (ou o usassem para iniciar uma transação entre fragmentos), mas nunca distribuiu o bloco, o honesto validators não têm como criar um desafio. Abordaremos três abordagens para resolver este problema que complementam um ao outro. 2.5.1 Provas de Custódia O problema mais imediato a ser resolvido é se um bloco estará disponível uma vez está publicado. Uma ideia proposta é ter os chamados Notários que façam rodízio entre fragmentos com mais frequência do que validators cuja única tarefa é baixar um bloquear e atestar que eles conseguiram baixá-lo. Eles podem ser girados com mais frequência porque não precisam baixar o estado inteiro do fragmento, ao contrário dos validators que não podem ser girados com frequência, pois devem baixar o estado do shard cada vez que eles giram, conforme mostrado na figura 13. O problema com esta abordagem ingénua é que é impossível provar mais tarde se o Tabelião conseguiu ou não fazer o download do bloco, então um Tabelião podem optar por sempre atestar que conseguiram baixar o bloco sem mesmo tentando recuperá-lo. Uma solução para isto é os Notários fornecerem alguma evidência ou apostar alguma quantidade de tokens atestando que o bloco foi baixado. Uma dessas soluções é discutida aqui: https://ethresear.ch/t/ Títulos de custódia compatíveis com agregação de 1 bit/2236. 2.5.2 Códigos de apagamento Quando um determinado nó light recebe um hash de um bloco, para aumentar a capacidade do nó confiança de que o bloco está disponível, ele pode tentar baixar alguns blocos aleatórios. pedaços do bloco. Esta não é uma solução completa, pois a menos que os nós de luz baixar coletivamente o bloco inteiro que os produtores de blocos maliciosos podem escolher
Figura 13: Os validadores precisam baixar o estado e, portanto, não podem ser girados frequentemente reter as partes do bloco que não foram baixadas por nenhum light node, assim ainda tornando o bloco indisponível. Uma solução é usar uma construção chamada Erasure Codes para tornar possível para recuperar o bloco completo mesmo que apenas uma parte do bloco esteja disponível, conforme mostrado na figura 14. Figura 14: Merkle tree criado com base em dados codificados para eliminação Tanto Polkadot quanto Ethereum Serenity têm designs em torno dessa ideia de que fornecer uma maneira para que os nós leves tenham confiança razoável de que os blocos estão disponíveis. A abordagem Ethereum Serenity tem uma descrição detalhada em [2].2.5.3 Abordagem de Polkadot para disponibilidade de dados Em Polkadot, como na maioria das soluções fragmentadas, cada fragmento (chamado parachain) captura seus blocos na cadeia de beacon (chamada cadeia de retransmissão). Digamos que existem 2f + 1 validators na cadeia de retransmissão. Os produtores de blocos de parachain, chamados agrupadores, uma vez que o bloco parachain é produzido, calcule uma versão codificada para apagamento do bloco que consiste em 2f +1 partes, de modo que quaisquer f partes sejam suficientes para reconstruir o bloco. Eles então distribuem uma parte para cada validator no cadeia de relé. Uma cadeia de retransmissão específica validator só assinaria em uma cadeia de retransmissão bloco se eles tiverem sua parte para cada bloco parachain que é capturado para tal bloco de cadeia de relé. Assim, se um bloco de cadeia de relés tiver assinaturas de 2f + 1 validators, e enquanto não mais do que f deles violarem o protocolo, cada o bloco parachain pode ser reconstruído buscando as partes dos validators que seguem o protocolo. Veja a figura 15. Figura 15: Disponibilidade de dados de Polkadot 2.5.4 Disponibilidade de dados a longo prazo Observe que todas as abordagens discutidas acima apenas atestam o fato de que um bloco foi publicado e está disponível agora. Os blocos podem ficar indisponíveis posteriormente por vários motivos: nós ficando off-line, nós apagando intencionalmente o histórico dados e outros. Um whitepaper que vale a pena mencionar que aborda esse problema é o Polyshard [3], que usa códigos de apagamento para disponibilizar blocos em fragmentos, mesmo que vários os fragmentos perdem completamente seus dados. Infelizmente, a sua abordagem específica exige todos os shards para baixar blocos de todos os outros shards, o que é proibitivamente caro. A disponibilidade a longo prazo não é uma questão tão premente: uma vez que nenhum participante espera-se que o sistema seja capaz de validar todas as cadeias em todos os
fragmentos, a segurança do protocolo fragmentado precisa ser projetada de tal forma maneira que o sistema é seguro, mesmo que alguns blocos antigos em alguns fragmentos se tornem completamente indisponível.
Nightshade
3.1 De cadenas de fragmentos a fragmentos de fragmentos El modelo de fragmentación con cadenas de fragmentos y una cadena de balizas es muy poderoso pero tiene ciertas complejidades. En particular, es necesario ejecutar la regla de elección de la bifurcación. en cada cadena por separado, la regla de elección de bifurcación en las cadenas de fragmentos y la baliza La cadena debe construirse de manera diferente y probarse por separado. En Nightshade modelamos el sistema como un único blockchain, en el que cada El bloque contiene lógicamente todas las transacciones para todos los fragmentos y cambia el Estado completo de todos los fragmentos. Físicamente, sin embargo, ningún participante descarga el estado completo o el bloque lógico completo. En cambio, cada participante de la red sólo mantiene el estado que corresponde a los fragmentos para los que validan las transacciones, y la lista de todas las transacciones en el bloque se divide en físicas trozos, un trozo por fragmento. En condiciones ideales, cada bloque contiene exactamente un fragmento por fragmento por bloque, que corresponde aproximadamente al modelo con cadenas de fragmentos en el que el Las cadenas de fragmentos producen bloques con la misma velocidad que la cadena de baliza. Sin embargo, Debido a retrasos en la red, es posible que falten algunos fragmentos, por lo que en la práctica cada bloque contiene uno o cero fragmentos por fragmento. Consulte la sección 3.3 para obtener detalles sobre cómo Se producen bloques. Figura 16: Un modelo con cadenas de fragmentos a la izquierda y con una cadena que tiene bloques divididos en trozos a la derecha
3.2 Consenso Los dos enfoques dominantes para el consenso en la década de blockchains hoy son el cadena más larga (o más pesada), en la que la cadena que tiene más trabajo o participación utilizado para construirlo se considera canónico, y BFT, en el que para cada bloque algunos un conjunto de validator alcanzan un consenso BFT. En los protocolos propuestos recientemente, este último es el enfoque más dominante, ya que proporciona una finalidad inmediata, mientras que en la cadena más larga se necesitan más bloques. que se construirá encima del bloque para asegurar la finalidad. A menudo para un significado seguridad: el tiempo que lleva construir un número suficiente de bloques supone el orden de horas. Usar el consenso BFT en cada bloque también tiene desventajas, tales como: 1. El consenso BFT implica una cantidad considerable de comunicación. mientras Los avances recientes permiten alcanzar el consenso en tiempo lineal en número. de los participantes (ver, por ejemplo, [4]), todavía se nota una sobrecarga por bloque; 2. Es inviable que todos los participantes de la red participen en el BFT consenso por bloque, por lo que normalmente sólo un subconjunto de participantes muestreados aleatoriamente alcanza el consenso. Un conjunto muestreado aleatoriamente puede ser, en principio, se corrompe adaptativamente y, en teoría, se puede crear una bifurcación. el sistema cualquiera de los dos necesita ser modelado para estar listo para tal evento y, por lo tanto, aún tener una regla de elección de bifurcación además del consenso BFT, o estar diseñado para cerrar abajo en tal evento. Cabe mencionar que algunos diseños, como Algorand [5], reducen significativamente la probabilidad de corrupción adaptativa. 3. Lo más importante es que el sistema se detiene si 1 3 o más de todos los participantes son fuera de línea. Por lo tanto, cualquier falla temporal de la red o una división de la red puede detener completamente el sistema. Idealmente, el sistema debe poder continuar operar mientras al menos la mitad de los participantes estén en línea (la mayoría Los protocolos basados en cadena continúan funcionando incluso si menos de la mitad de los participantes están en línea, pero la conveniencia de esta propiedad es más discutible. dentro de la comunidad). Un modelo híbrido en el que el consenso utilizado es el más pesado La cadena, pero algunos bloques se finalizan periódicamente utilizando un dispositivo de finalidad BFT mantienen las ventajas de ambos modelos. Estos dispositivos de finalidad BFT son Casper FFG [6] usado en Ethereum 2.0 8, Casper CBC (ver https://vitalik. ca/general/2018/12/05/cbc_casper.html) y ABUELO (ver https:// medium.com/polkadot-network/d08a24a021b5) utilizado en Polkadot. Nightshade utiliza el consenso de cadena más pesado. Específicamente cuando un bloque productor produce un bloque (ver sección 3.3), puede recolectar firmas de otros productores de bloques y validators que acrediten el bloque anterior. Ver sección 3.8 para obtener detalles sobre cómo se agrega una cantidad tan grande de firmas. el peso 8Vea también la sesión de pizarra con Justin Drake para obtener una descripción detallada de Casper. FFG y cómo se integra con el consenso de la cadena más pesada de GHOST aquí: https://www. youtube.com/watch?v=S262StTwkmode un bloque es entonces la participación acumulada de todos los firmantes cuyas firmas son incluido en el bloque. El peso de una cadena es la suma de los pesos de los bloques. Además del consenso de cadena más pesado, utilizamos un dispositivo de finalidad que utiliza las certificaciones para finalizar los bloques. Para reducir la complejidad del sistema, utilizamos un dispositivo de finalidad que no influye de ninguna manera en la regla de elección de la bifurcación, y en su lugar sólo introduce condiciones de corte adicionales, de modo que una vez que un bloque es finalizado por el dispositivo de finalidad, una bifurcación es imposible a menos que un porcentaje muy grande del total de la apuesta se reduce drásticamente. Casper CBC es un dispositivo de finalidad, y Actualmente modela con Casper CBC en mente. También trabajamos en un protocolo BFT separado llamado TxFlow. En el momento de Al escribir este documento no está claro si se utilizará TxFlow en lugar de Casper. CBC. Sin embargo, observamos que la elección del dispositivo final es en gran medida ortogonal al resto del diseño. 3.3 producción de bloques En Nightshade hay dos roles: productores de bloques y validators. en cualquier punto el sistema contiene w productores de bloques, w = 100 en nuestros modelos, y wv validators, en nuestro modelo v = 100, wv = 10, 000. El sistema es Prueba de participación, lo que significa que tanto los productores de bloques como los validators tienen algún número de moneda (denominada "tokens") bloqueada por un período de tiempo que excede con creces el tiempo que dedican a realizar sus tareas de construcción y validación de la cadena. Como ocurre con todos los sistemas de Prueba de participación, no todos los productores de bloques w y no todos los wv validators son entidades diferentes, ya que eso no se puede hacer cumplir. cada uno de los productores de bloques w y los wv validators, sin embargo, tienen una estaca. El sistema contiene n fragmentos, n = 1000 en nuestro modelo. Como se menciona en sección 3.1, en Nightshade no hay cadenas de fragmentos; en cambio, todos los productores de bloques y validator están construyendo un único blockchain, al que nos referimos como cadena principal. El estado de la cadena principal se divide en n fragmentos y cada bloque productor y validator en cualquier momento solo han descargado localmente un subconjunto de el estado que corresponde a algún subconjunto de los fragmentos, y solo el proceso y validar transacciones que afecten a esas partes del estado. Para convertirse en productor de bloques, un participante de la red bloquea algunos grandes cantidad de tokens (una participación). El mantenimiento de la red se realiza en épocas, donde una época es un período de tiempo del orden de días. Los participantes con lo que está en juego más al comienzo de una época particular es el bloque productores de esa época. Cada productor de bloques se asigna a fragmentos sw (digamos sw = 40, lo que haría sww/n = 4 productores de bloques por fragmento). el bloque El productor descarga el estado del fragmento al que están asignados antes de la época. comienza, y a lo largo de la época recopila transacciones que afectan ese fragmento, y los aplica al Estado. Para cada bloque b en la cadena principal, y para cada fragmento s, hay uno de los productores de bloques asignados a s, quien es responsable de producir la parte de b relacionada al fragmento. La parte de b relacionada con el fragmento s se llama fragmento y contiene el lista de las transacciones para que el fragmento se incluya en b, así como el merkleraíz del estado resultante. b en última instancia sólo contendrá un encabezado muy pequeño de el fragmento, es decir, la raíz merkle de todas las transacciones aplicadas (consulte la sección 3.7.1 para detalles exactos), y la raíz merkle del estado final. A lo largo del resto del documento, a menudo nos referimos al productor de bloques. que es responsable de producir un fragmento en un momento particular para un fragmento en particular como productor de trozos. El productor de fragmentos es siempre uno de los productores de bloques. Los productores de bloques y los productores de trozos rotan cada bloque según a un horario fijo. Los productores de bloques tienen un pedido y producen repetidamente. bloques en ese orden. P.ej. Si hay 100 productores de bloques, el primer bloque Los productores son responsables de producir los bloques 1, 101, 201, etc., el segundo es responsable de producir 2, 102, 202, etc.). Dado que la producción de trozos, a diferencia de la producción de bloques, requiere mantener el estado, y para cada fragmento solo los productores de bloques sww/n mantienen el estado por fragmento, en consecuencia, solo los productores de bloques sww/n rotan para crear trozos. P.ej. con las constantes anteriores con cuatro productores de bloques asignados a En cada fragmento, cada productor de bloques creará fragmentos una vez cada cuatro bloques. 3.4 Garantizar la disponibilidad de datos Para garantizar la disponibilidad de datos utilizamos un enfoque similar al de Polkadot descrito en la sección 2.5.3. Una vez que un productor de bloques produce un fragmento, crea una versión codificada de borrado con un código de bloque óptimo (w, ⌊w/6 + 1⌋) del trozo. Luego envían una parte del fragmento codificado de borrado (a esas partes las llamamos partes de fragmentos, o solo partes) a cada productor de bloques. Calculamos un árbol merkle que contiene todas las partes como las hojas, y el El encabezado de cada fragmento contiene la raíz merkle de dicho árbol. Las piezas se envían a los validators mediante mensajes onepart. Cada uno de esos mensajes contiene el encabezado del fragmento, el ordinal de la parte y el contenido de la parte. el El mensaje también contiene la firma del productor del bloque que produjo el chunk y la ruta merkle para demostrar que la parte corresponde al encabezado y es producido por el productor de bloques adecuado. Una vez que un productor de bloques recibe un bloque de la cadena principal, primero verifica si tenga mensajes de una parte para cada fragmento incluido en el bloque. Si no, el bloque no se procesa hasta que se recuperan los mensajes de una parte que faltan. Una vez que se reciben todos los mensajes de una parte, el productor del bloque recupera el partes restantes de los pares y reconstruye los fragmentos que mantienen el estado. El productor de bloques no procesa un bloque de la cadena principal si es por al menos un fragmento incluido en el bloque no tienen el mensaje de una parte correspondiente, o si al menos para un fragmento para el cual mantienen el estado no pueden reconstruir todo el trozo. Para que un fragmento en particular esté disponible es suficiente que ⌊w/6⌋+1 del bloque los productores tienen sus partes y les sirven. Así, mientras el número de Los actores maliciosos no superan ⌊w/3⌋ninguna cadena que tenga más de medio bloque. los productores que lo construyen pueden tener fragmentos no disponibles.Figura 17: Cada bloque contiene uno o cero fragmentos por fragmento, y cada fragmento tiene un código de borrado. Cada parte del fragmento codificado de borrado se envía a un lugar designado productor de bloques a través de un mensaje especial de una parte 3.4.1 Tratar con productores de bloques perezosos Si un productor de bloques tiene un bloque al que le falta un mensaje de una parte, podría optar por firmar aún así, porque si el bloque termina en la cadena, maximizará la recompensa para el productor del bloque. No hay riesgo para el bloque. productor ya que es imposible probar posteriormente que el productor del bloque no tenía el mensaje de una parte. Para solucionarlo, hacemos que cada fragmento sea productor al crear el fragmento para elija un color (rojo o azul) para cada parte del futuro fragmento codificado y guárdelo la máscara de bits del color asignado en el fragmento antes de codificarlo. cada una de las partes El mensaje contiene el color asignado a la pieza y el color se utiliza cuando calcular la raíz merkle de las partes codificadas. Si el productor del trozo se desvía del protocolo, se puede probar fácilmente, ya que la raíz de merkle no corresponden a mensajes de una parte, o los colores en los mensajes de una parte que corresponden a la raíz de merkle no coincidirán con la máscara en el fragmento. Cuando un productor de bloques firma en un bloque, incluye una máscara de bits de todos los piezas rojas que recibieron por los trozos incluidos en el bloque. Publicar un la máscara de bits incorrecta es un comportamiento que se puede recortar. Si un productor de bloques no ha recibido un mensaje de una parte, no tienen forma de saber el color del mensaje, y Por lo tanto, tienen un 50% de posibilidades de ser eliminados si intentan firmar a ciegas el bloque. 3.5 Solicitud de transición de estado Los productores de fragmentos sólo eligen qué transacciones incluir en el fragmento, pero no aplique la transición de estado cuando produzcan un fragmento. En consecuencia,
el encabezado del fragmento contiene la raíz merkle del estado merkelizado como antes se aplican las transacciones en el fragmento. Las transacciones solo se aplican cuando un bloque completo que incluye el fragmento se procesa. Un participante solo procesa un bloque si 1. El bloque anterior fue recibido y procesado; 2. Para cada fragmento, el participante no mantiene el estado que tiene. visto el mensaje de una parte; 3. Para cada fragmento, el participante mantiene el estado porque tiene el trozo completo. Una vez que se procesa el bloque, para cada fragmento para el cual el participante mantiene el estado, aplican las transacciones y calculan el nuevo estado a partir de que se aplican las transacciones, después de lo cual están listas para producir los fragmentos para el siguiente bloque, si están asignados a algún fragmento, ya que tienen la raíz merkle del nuevo estado merkelizado. 3.6 Transacciones y recibos entre fragmentos Si una transacción necesita afectar a más de un fragmento, debe realizarse consecutivamente. ejecutado en cada fragmento por separado. La transacción completa se envía al primer fragmento. afectado, y una vez que la transacción se incluye en el fragmento de dicho fragmento, y se aplica después de que el fragmento se incluye en un bloque, genera el llamado recibo transacción, que se enruta al siguiente fragmento en el que la transacción debe ser ejecutado. Si se requieren más pasos, la ejecución de la transacción de recibo genera una nueva transacción de recibo y así sucesivamente. 3.6.1 Duración de la transacción del recibo Es deseable que la transacción de recibo se aplique en el bloque que sigue inmediatamente al bloque en el que se generó. La transacción del recibo es sólo generado después de que el bloque anterior fue recibido y aplicado por los productores de bloques que mantienen el fragmento de origen, y debe ser conocido en el momento en que El fragmento para el siguiente bloque es producido por los productores de bloques del destino. fragmento. Por lo tanto, el recibo debe comunicarse desde el fragmento de origen al fragmento de destino en el corto período de tiempo entre esos dos eventos. Sea A el último bloque producido que contiene una transacción t que genera un recibo r. Sea B el siguiente bloque producido (es decir, un bloque que tiene A como su bloque anterior) que queremos contener r. Sea t estar en el fragmento a y r en el fragmento b. La vida útil del recibo, también representada en la figura 18, es la siguiente: Elaborar y almacenar los recibos. El cpa del productor de fragmentos para fragmentos a recibe el bloque A, aplica la transacción t y genera el recibo r. cpa luego almacena todos los recibos producidos en su almacenamiento interno persistente indexado por la identificación del fragmento de origen.Distribuyendo los recibos. Una vez que cpa esté listo para producir el fragmento para fragmento a para el bloque B, obtienen todos los recibos generados al aplicar las transacciones del bloque A para el fragmento a y los incluyen en el fragmento para shrad a en el bloque B. Una vez que se genera dicho fragmento, cpa produce su borrado codificado versión y todos los mensajes onepart correspondientes. cpa sabe qué productores de bloques mantienen el estado completo para qué fragmentos. Para un productor de bloques en particular pb cpa incluye los ingresos que resultaron de aplicar las transacciones del bloque A para el fragmento a que tiene como destino cualquiera de los fragmentos que le interesan a bp en el mensaje de una parte cuando distribuyeron el fragmento para el fragmento a en el bloque B (consulte la figura 17, que muestra los recibos incluidos en el mensaje de una parte). Recibir los recibos. Recuerde que los participantes (tanto productores de bloques como validators) no procesan bloques hasta que tengan mensajes de una parte. para cada fragmento incluido en el bloque. Por lo tanto, cuando un participante en particular aplica el bloque B, tiene todos los mensajes de una parte que corresponden a fragmentos en B, y por lo tanto tienen todos los recibos entrantes que tienen los fragmentos el participante mantiene el estado como destino. Al aplicar el transición de estado para un fragmento en particular, el participante aplica ambos recibos que han recopilado para el fragmento en los mensajes de una parte, así como todos las transacciones incluidas en el propio fragmento. Figura 18: La vida útil de una transacción de recibo 3.6.2 Manejar demasiados recibos Es posible que el número de recibos dirigidos a un fragmento concreto en un bloque en particular es demasiado grande para ser procesado. Por ejemplo, considere la figura 19, en en el que cada transacción en cada fragmento genera un recibo dirigido al fragmento 1. En el siguiente bloque, la cantidad de recibos que el fragmento 1 debe procesar es comparable a la carga que todos los fragmentos combinados procesaron mientras se manipulaban el bloque anterior.
Figura 19: Si todos los recibos apuntan al mismo fragmento, es posible que el fragmento no tenga la capacidad de procesarlos Para solucionarlo utilizamos una técnica similar a la utilizada en QuarkChain 9. Específicamente, para cada fragmento, el último bloque B y el último fragmento dentro de ese Se registra el bloque desde el cual se aplicaron los recibos. Cuando el nuevo fragmento esté creado, los recibos se aplican en orden primero a partir de los fragmentos restantes en B, y luego en bloques que siguen a B, hasta que el nuevo fragmento esté lleno. En condiciones normales circunstancias con una carga equilibrada, generalmente resultará en todos los recibos que se está aplicando (y por lo tanto, el último fragmento del último bloque se registrará para cada trozo), pero durante los momentos en que la carga no está equilibrada, y un particular Shard recibe una cantidad desproporcionada de recibos, esta técnica les permite procesarse respetando los límites en el número de transacciones incluidas. Tenga en cuenta que si dicha carga desequilibrada permanece durante mucho tiempo, el retraso desde la creación del recibo hasta que la aplicación pueda seguir creciendo indefinidamente. uno forma de abordarlo es descartar cualquier transacción que genere un recibo dirigido a un fragmento que tiene un retraso de procesamiento que excede alguna constante (por ejemplo, una época). Considere la figura 20. En el bloque B, el fragmento 4 no puede procesar todos los recibos, por lo que solo procesa el origen de los recibos desde hasta el fragmento 3 en el bloque A, y lo registra. En el bloque C se incluyen los recibos hasta el fragmento 5 del bloque B, y luego, en el bloque D, el fragmento se pone al día y procesa todos los recibos restantes en bloque B y todos los recibos del bloque C. 3.7 Validación de fragmentos Un fragmento producido para un fragmento en particular (o un bloque de fragmentos producido para una cadena de fragmentos particular en el modelo con cadenas de fragmentos) solo puede ser validado por el 9Vea el episodio de la pizarra con QuarkChain aquí: https://www.youtube.com/watch? v=opEtG6NM4x4, en el que se analiza el enfoque de las transacciones entre fragmentos, entre otros cosasFigura 20: Procesamiento de recibos retrasados participantes que mantienen el estado. Pueden ser productores de bloques, validators, o simplemente testigos externos que descargaron el estado y validaron el fragmento en donde almacenan activos. En este documento asumimos que la mayoría de los participantes no pueden almacenar al Estado una gran parte de los fragmentos. Vale la pena mencionar, sin embargo, que hay blockchains fragmentados que están diseñados con la suposición de que la mayoría de los participantes tienen capacidad para almacenar el estado y validar la mayoría de los fragmentos, como QuarkChain. Dado que solo una fracción de los participantes tiene el estado para validar el fragmento fragmentos, es posible corromper adaptativamente solo a los participantes que tienen la estado y aplicar una transición de estado no válida. Se propusieron múltiples diseños de fragmentación que muestrean validators cada pocos días, y dentro de un día cualquier bloque en la cadena de fragmentos que tenga más de 2/3 de firmas de los validator asignados a dicho fragmento se considera inmediatamente final. Con tal enfoque un adversario adaptativo sólo necesita corromper 2n/3+1 de los validators en una cadena de fragmentos para aplicar una transición de estado no válida, que, Aunque probablemente sea difícil de lograr, no es un nivel de seguridad suficiente para un público. blockchain. Como se analizó en la sección 2.3, el enfoque común es permitir una cierta ventana de tiempo después de que se crea un bloque para cualquier participante que tenga estado (ya sea es un productor de bloques, un validator o un observador externo) para cuestionar su validez. Estos participantes se llaman pescadores. Para que un pescador pueda impugnar un bloque no válido, se debe garantizar que dicho bloque esté disponible para ellos. La disponibilidad de datos en Nightshade se analiza en la sección 3.4. En Nightshade, una vez que se produce un bloque, los fragmentos no fueron validados por cualquiera excepto el productor de fragmentos real. En particular, el productor de bloques que sugirió que el bloque naturalmente no tenía el estado para la mayoría de los fragmentos, yno pudo validar los fragmentos. Cuando se produce el siguiente bloque, contiene certificaciones (consulte la sección 3.2) de múltiples productores de bloques y validators, pero dado que la mayoría de los productores de bloques y validators no mantienen el estado Además, para la mayoría de los fragmentos, un bloque con solo un fragmento no válido recopilará significativamente más de la mitad de las certificaciones y seguirá estando en la lista más pesada. cadena. Para abordar este problema, permitimos que cualquier participante que mantenga el estado de un fragmento para presentar un desafío en la cadena por cualquier fragmento no válido producido en ese fragmento. 3.7.1 Desafío de validez estatal Una vez que un participante detecta que un fragmento en particular no es válido, debe proporcionar una prueba de que el fragmento no es válido. Dado que la mayoría de los participantes de la red no mantienen el estado del fragmento en el que se encuentra el fragmento no válido producida, la prueba debe tener suficiente información para confirmar que el bloque es inválido sin tener el estado. Establecemos un límite Ls de la cantidad de estado (en bytes) que una sola transacción Puede leer o escribir de forma acumulativa. Cualquier transacción que toque más de Ls. El estado se considera inválido. Recuerde de la sección 3.5 que el trozo en un bloque particular B sólo contiene las transacciones a aplicar, pero no la nueva raíz estatal. La raíz del estado incluida en el fragmento del bloque B es el estado root antes de aplicar dichas transacciones, pero después de aplicar las transacciones de el último fragmento en el mismo fragmento antes del bloque B. Un actor malicioso que desea aplicar una transición de estado no válida incluiría una raíz de estado incorrecta en el bloque B que no corresponde al estado raíz que resulta de aplicar las transacciones en el fragmento anterior. Ampliamos la información que un productor de fragmentos incluye en el fragmento. En lugar de simplemente incluir el estado después de aplicar todas las transacciones, en su lugar incluye una raíz de estado después de aplicar cada conjunto contiguo de transacciones que leer y escribir colectivamente Ls bytes de estado. Con esta información para el pescador para crear un desafío que una transición de estado se aplica incorrectamente es suficiente encontrar la primera raíz de estado no válida e incluir solo Ls bytes de estado que se ven afectados por las transacciones entre la última raíz del estado (que fue válido) y la raíz del estado actual con las pruebas de merkle. Entonces cualquier participante puede validar las transacciones en el segmento y confirmar que el fragmento es inválido. De manera similar, si el productor del fragmento intentara incluir transacciones que leyeran y escribir más de Ls bytes de estado, para el desafío basta con incluir los primeros Ls bytes que toca con las pruebas merkle, que serán suficientes para aplicar las transacciones y confirmar que hay un momento en el que se intenta Se realiza lectura o escritura de contenido más allá de Ls bytes.
3.7.2 Pescadores y transacciones rápidas entre fragmentos. Como se analizó en la sección 2.3, una vez que asumimos que los fragmentos (o fragmentos) bloques en el modelo con cadenas de fragmentos) pueden no ser válidos e introducir un desafío período, afecta negativamente la finalidad y, por lo tanto, la comunicación entre fragmentos. en En particular, el fragmento de destino de cualquier transacción entre fragmentos no puede estar seguro el fragmento o bloque de origen es definitivo hasta que finaliza el período de desafío (ver figura 21). Figura 21: Esperar el período de impugnación antes de aplicar un recibo La forma de abordarlo de manera que se realicen transacciones entre fragmentos. instantáneo es que el fragmento de destino no espere el período de desafío después de que se publique la transacción del fragmento de origen y aplique la transacción del recibo inmediatamente, pero luego revertir el fragmento de destino junto con el origen fragmento si más tarde se descubre que el fragmento o bloque original no es válido (consulte la figura 22). Esto se aplica de forma muy natural al diseño Nightshade en el que el fragmento Las cadenas no son independientes, sino que todos los fragmentos se publican. juntos en el mismo bloque de cadena principal. Si se determina que algún fragmento no es válido, el todo el bloque con ese fragmento se considera inválido y todos los bloques construidos en él encima. Ver figura 23. Ambos enfoques anteriores proporcionan atomicidad suponiendo que el desafío el período es lo suficientemente largo. Usamos el último enfoque, ya que proporcionar transacciones rápidas entre fragmentos en circunstancias normales supera los inconvenientes de el fragmento de destino retrocede debido a una transición de estado no válida en uno de los fragmentos de origen, lo cual es un evento extremadamente raro. 3.7.3 Ocultar validators La existencia de los desafíos ya reduce significativamente la probabilidad de corrupción adaptativa, ya que para finalizar una parte con un estado de transición inválidoFigura 22: Aplicar recibos inmediatamente y revertir el destino cadena si la cadena fuente tenía un bloque no válido Figura 23: Desafío del pescador en Nightshade El período de desafío el adversario adaptativo necesita corromper a todos los participantes. que mantienen el estado del fragmento, incluidos todos los validator. Estimar la probabilidad de que ocurra tal evento es extremadamente complejo, ya que no sharded blockchain ha estado activo el tiempo suficiente para intentar cualquier ataque de este tipo. Sostenemos que la probabilidad, aunque extremadamente baja, sigue siendo suficientemente grande para un sistema que se espera que ejecute transacciones multimillonarias y ejecutar operaciones financieras a nivel mundial. Hay dos razones principales para esta creencia: 1. La mayoría de los validators de las cadenas de Prueba de Participación y mineros del
Las cadenas de prueba de trabajo están incentivadas principalmente por las ventajas financieras. si un adversario adaptativo les ofrece más dinero que el retorno esperado de operar honestamente, es razonable esperar que muchos validators aceptará la oferta. 2. Muchas entidades validan las cadenas de prueba de participación de manera profesional, y Se espera que un gran porcentaje de la participación en cualquier cadena sea de dichas entidades. El número de tales entidades es lo suficientemente pequeño para una adversario adaptativo para conocer a la mayoría de ellos personalmente y tener una buena comprensión de su inclinación a corromperse. Damos un paso más para reducir la probabilidad de corrupción adaptativa al ocultar qué validator están asignados a cada fragmento. La idea es remotamente similar a la forma en que Algorand [5] oculta validators. Es fundamental tener en cuenta que incluso si los validator están ocultos, como en Algorand o como se describe a continuación, la corrupción adaptativa todavía es posible en teoría. mientras El adversario adaptativo no conoce a los participantes que crearán o validarán. un bloque o un trozo, los propios participantes saben que realizarán tal tarea y tener una prueba criptográfica de ello. Así, el adversario puede difundir su intención de corromper y pagar a cualquier participante que proporcione tal prueba criptográfica. Sin embargo, observamos que dado que el adversario no conocen los validator que están asignados al fragmento que quieren corromper, no tienen otra opción que transmitir su intención de corromper un fragmento en particular a toda la comunidad. En ese punto es económicamente benéfico para cualquier persona honesta. participante para activar un nodo completo que valide ese fragmento, ya que hay un alto posibilidad de que aparezca un bloque no válido en ese fragmento, lo cual es una oportunidad para crea un desafío y recolecta la recompensa asociada. Para no revelar los validators que están asignados a un fragmento en particular, hacemos lo siguiente (ver figura 24): Usando VRF para obtener la tarea. Al comienzo de cada época cada validator usa un VRF para obtener una máscara de bits de los fragmentos a los que está asignado validator. La máscara de bits de cada validator tendrá bits Sw (consulte la sección 3.3 para conocer la definición de SW). Luego, el validator recupera el estado de los fragmentos correspondientes y durante la época para cada bloque recibido valida los fragmentos que corresponden a los fragmentos a los que está asignado el validator. Regístrate en bloques en lugar de trozos. Dado que la asignación de fragmentos está oculta, validator no puede firmar fragmentos. En cambio, siempre firma en todo el bloque, por lo que no revela qué fragmentos valida. Específicamente, cuando validator recibe un bloque y valida todos los fragmentos, crea un mensaje que atestigua que todos los fragmentos en todos los fragmentos a los que está asignado el validator son válido (sin indicar de ninguna manera cuáles son esos fragmentos), o un mensaje que contiene una prueba de una transición de estado no válida si algún fragmento no es válido. Ver el sección 3.8 para obtener detalles sobre cómo se agregan dichos mensajes, sección 3.7.4 para los detalles sobre cómo evitar que validators se aprovechen de los mensajes de otros validators, y la sección 3.7.5 para obtener detalles sobre cómo recompensar y castigar validators en caso de que realmente se produzca una impugnación exitosa de una transición de estado no válida.Figura 24: Ocultando los validators en Nightshade 3.7.4 Comprometerse-Revelar Uno de los problemas comunes con validators es que un validator puede omitir la descarga del estado y validar los fragmentos y bloques, y en su lugar observar la red, ver lo que envían los otros validators y repetir sus mensajes. Un validator que sigue dicha estrategia no proporciona ningún beneficio adicional. seguridad para la red, pero recoge recompensas. Una solución común para este problema es que cada validator proporcione una prueba que realmente validaron el bloque, por ejemplo proporcionando un seguimiento único de aplicar la transición estatal, pero tales pruebas aumentan significativamente el costo de validación. Figura 25: comprometerse-revelar
En su lugar, hacemos que los validators se comprometan por primera vez con el resultado de la validación (ya sea el mensaje que da fe de la validez de los fragmentos, o la prueba de una invalidez transición de estado), espere un cierto período y solo entonces revele el resultado de validación real, como se muestra en la figura 25. El período de confirmación no se cruza con el período de revelación y, por lo tanto, un validator perezoso no puede imitar a los validators honestos. Además, si un validator deshonesto se comprometió con un mensaje que da fe de la validez de los fragmentos asignados, y al menos un fragmento no era válido, una vez que se demostrado que el fragmento no es válido, validator no puede evitar la reducción, ya que, Como mostramos en la sección 3.7.5, la única manera de no ser cortado en tal situación es presentar un mensaje que contiene una prueba de la transición de estado no válida que coincide con el compromiso. 3.7.5 Manejando desafíos Como se analizó anteriormente, una vez que un validator recibe un bloque con un fragmento no válido, Primero preparan una prueba de la transición de estado no válida (ver sección 3.7.1), luego comprometerse con dicha prueba (ver 3.7.4) y después de un período revelar el desafío. Una vez incluido el desafío revelado en un bloque, sucede lo siguiente: 1. Todas las transiciones de estado que ocurrieron desde el bloque que contiene el fragmento no válido hasta que se obtenga el bloque en el que se incluye el desafío revelado. anulado. El estado ante el bloque que incluye el desafío revelado se considera el mismo que el estado anterior al bloque que contenía el trozo inválido. 2. Dentro de un cierto período de tiempo cada validator debe revelar su máscara de bits de los fragmentos que validan. Dado que la máscara de bits se crea a través de un VRF, si fueron asignados al fragmento que tenía la transición de estado no válida, No puedo evitar revelarlo. Cualquier validator que no revele la máscara de bits se supone que está asignado al fragmento. 3. Cada validator que después de dicho período se encuentre asignado al fragmento, que se comprometió con algún resultado de validación para el bloque que contiene el fragmento inválido y que no reveló la prueba de transición de estado inválido que corresponde a su compromiso se reduce. 4. Cada validator recibe una nueva asignación de fragmentos y se programa una nueva época. para comenzar después de un tiempo suficiente para que todos los validators descarguen el estado, como se muestra en la figura 26. Tenga en cuenta que desde el momento en que los validator revelan los fragmentos que se les asignan hasta que comienza la nueva época, la seguridad del sistema se reduce desde el Se revela la asignación de fragmentos. Los participantes de la red deben mantenerlo. en mente al utilizar la red durante dicho período. 3.8 Agregación de firmas Para que un sistema con cientos de fragmentos funcione de forma segura, queremos tener en el orden de 10, 000 o más validators. Como se discutió en la sección 3.7, queremos que cadaFigura 26: Manejando el desafío validator para publicar un compromiso con un determinado mensaje y una firma en promedio una vez por bloque. Incluso si los mensajes de confirmación fueran los mismos, agregar tal La firma BLS y su validación habrían sido prohibitivamente costosas. pero naturalmente, los mensajes de confirmación y revelación no son los mismos en validators, y por lo tanto necesitamos alguna forma de agregar dichos mensajes y las firmas en un forma que permita una validación rápida posterior. El enfoque específico que utilizamos es el siguiente: Validadores que se unen a productores de bloques. Los productores de bloques son conocidos. algún tiempo antes de que comience la época, ya que necesitan algo de tiempo para descargar el estado antes de que comience la época y, a diferencia de los validators, los productores de bloques son no oculto. Cada productor de bloques tiene v validator ranuras. Los validadores envían propuestas fuera de la cadena a los productores de bloques para ser incluidos como uno de sus v validators. Si un productor de bloques desea incluir un validator, envía un transacción que contiene la solicitud inicial fuera de la cadena del validator, y el firma del productor del bloque que hace que validator se una al productor del bloque. Tenga en cuenta que los validators asignados a los productores de bloques no necesariamente valide los mismos fragmentos para los que el productor de bloques produce fragmentos. si un validator se aplicó para unir múltiples productores de bloques, solo la transacción de el primer productor de bloques tendrá éxito. Los productores de bloques recopilan compromisos. El productor de bloques recopila constantemente los mensajes de confirmación y revelación de los validator. Una vez que se acumula una cierta cantidad de dichos mensajes, el productor del bloque calcula un merkle árbol de estos mensajes, y envía a cada validator la raíz de merkle y el camino merkle a su mensaje. El validator valida el camino y se registra la raíz de merkle. Luego, el productor del bloque acumula una firma BLS en el raíz de merkle de validators, y publica solo la raíz de merkle y el firma acumulada. El productor del bloque también firma sobre la validez del firma múltiple utilizando una firma ECDSA barata. Si la firma múltiple no coincide con la raíz de merkle enviada o la máscara de bits de los validators participantes, es un comportamiento que se puede recortar. Al sincronizar la cadena, un participante puede optar por validar todas las firmas BLS de validators (lo cual es extremadamente costoso ya que implica agregar las claves públicas de validators), o sololas firmas ECDMA de los productores de bloques y se basan en el hecho de que el El productor de bloques no fue cuestionado ni recortado. Uso de transacciones en cadena y pruebas merkle para desafíos. eso Se puede observar que no tiene ningún valor revelar mensajes de validators si no Se detectó una transición de estado no válida. Sólo los mensajes que contienen la información real Es necesario revelar pruebas de una transición de estado inválida, y sólo para tales mensajes. es necesario demostrar que coinciden con el compromiso anterior. El mensaje necesita ser revelado con dos propósitos: 1. Para iniciar realmente la reversión de la cadena al momento anterior al transición de estado no válida (ver sección 3.7.5). 2. Para demostrar que el validator no intentó dar fe de la validez del trozo no válido. En cualquier caso debemos abordar dos cuestiones: 1. El compromiso real no se incluyó en la cadena, solo la raíz merkle del confirmar agregado con otros mensajes. El validator necesita utilizar el ruta merkle proporcionada por el productor del bloque y su compromiso original con demostrar que se comprometieron con el desafío. 2. Es posible que todos los validator asignados al fragmento con el valor no válido La transición de estado se asigna a productores de bloques corruptos que los están censurando. Para evitarlo, les permitimos enviar sus revelaciones. como una transacción regular en cadena y evitar la agregación. Esto último sólo se permite para las pruebas de transición de estado inválida, que son extremadamente raro y, por lo tanto, no debería generar spam en los bloques. La última cuestión que debe abordarse es que los productores de bloques pueden optar por no participar en la agregación de mensajes o censurar intencionalmente validators concretos. Lo hacemos económicamente desventajoso al hacer que el bloque Recompensa al productor proporcional al número de validators que se les asignen. nosotros También tenga en cuenta que dado que los productores de bloques entre épocas se cruzan en gran medida (ya que siempre son los primeros w participantes con la apuesta más alta), los validators pueden atenerse en gran medida a trabajar con los mismos productores de bloques, y así reducir el riesgo de ser asignados a un productor de bloques que los censuró en el pasado. 3.9 Cadena de instantáneas Dado que los bloques de la cadena principal se producen con mucha frecuencia, descargar el historial completo podría resultar caro muy rápidamente. Es más, dado que cada El bloque contiene una firma BLS de una gran cantidad de participantes, solo la agregación de las claves públicas para verificar la firma podría resultar prohibitiva. caro también. Finalmente, dado que en un futuro previsible Ethereum 1.0 probablemente seguirá siendo uno de los blockchains más utilizados, que tiene una forma significativa de transferir activos desde
Cerca de Ethereum es un requisito y hoy se verifican las firmas BLS para garantizar La validez de bloques cercanos en el lado de Ethereum no es posible. Cada bloque de la cadena principal de Nightshade puede contener opcionalmente un Schnorr firma múltiple en el encabezado del último bloque que incluía dicho Schnorr multifirma. A estos bloques los llamamos bloques instantáneos. El primer bloque de cada época debe ser un bloque de instantáneas. Mientras trabajaba en una firma múltiple de este tipo, los productores de bloques también deben acumular las firmas BLS de los validators en el último bloque de instantáneas y agréguelas de la misma manera que se describe en sección 3.8. Dado que el conjunto de productores de bloques es constante a lo largo de la época, validar sólo los primeros bloques de instantáneas en cada época son suficientes suponiendo que en ningún momento punto, un gran porcentaje de productores de bloques y validators se confabularon y crearon un tenedor. El primer bloque de la época debe contener información suficiente para calcular los productores de bloques y validators para la época. Llamamos a la subcadena de la cadena principal que solo contiene la instantánea. bloquea una cadena de instantáneas. Crear una firma múltiple de Schnorr es un proceso interactivo, pero como Sólo es necesario realizarlo con poca frecuencia, cualquier proceso, por ineficiente que sea, será suficiente. Las firmas múltiples de Schnorr se pueden validar fácilmente en Ethereum, proporcionando así primitivas cruciales para una forma segura de realizar cross-blockchain comunicación. Para sincronizar con la cadena Near solo es necesario descargar toda la instantánea. bloquea y confirma que las firmas Schnorr son correctas (opcionalmente, también verifica las firmas BLS individuales de los validators), y luego solo sincroniza bloques de la cadena principal desde el último bloque de instantánea.
Nightshade
3.1 De cadeias de fragmentos a pedaços de fragmentos O modelo de sharding com shard chains e beacon chain é muito poderoso, mas tem certas complexidades. Em particular, a regra de escolha do fork precisa ser executada em cada cadeia separadamente, a regra de escolha do fork nas cadeias de fragmentos e no beacon a corrente deve ser construída de forma diferente e testada separadamente. No Nightshade modelamos o sistema como um único blockchain, no qual cada bloco contém logicamente todas as transações para todos os fragmentos e altera o estado completo de todos os fragmentos. Fisicamente, no entanto, nenhum participante baixa o estado completo ou o bloco lógico completo. Em vez disso, cada participante da rede apenas mantém o estado que corresponde aos fragmentos para os quais eles validam as transações, e a lista de todas as transações no bloco é dividida em físicas pedaços, um pedaço por fragmento. Sob condições ideais, cada bloco contém exatamente um pedaço por fragmento por bloco, que corresponde aproximadamente ao modelo com cadeias de fragmentos em que o shard chains produzem blocos com a mesma velocidade que a beacon chain. No entanto, devido a atrasos na rede, alguns pedaços podem estar faltando, então, na prática, cada bloco contém um ou zero pedaços por fragmento. Consulte a seção 3.3 para obter detalhes sobre como blocos são produzidos. Figura 16: Um modelo com cadeias de fragmentos à esquerda e com uma cadeia tendo blocos divididos em pedaços à direita
3.2 Consenso As duas abordagens dominantes para o consenso nos blockchains hoje são as cadeia mais longa (ou mais pesada), na qual a cadeia que tem mais trabalho ou participação usado para construí-lo é considerado canônico, e BFT, em que para cada bloco alguns conjunto de validators alcança um consenso BFT. Nos protocolos propostos recentemente, esta última é uma abordagem mais dominante, uma vez que fornece finalidade imediata, enquanto na cadeia mais longa mais blocos precisam a ser construído no topo do bloco para garantir a finalidade. Muitas vezes por um significado segurança o tempo que leva para que um número suficiente de blocos seja construído leva em conta ordem de horas. Usar o consenso BFT em cada bloco também tem desvantagens, como: 1. O consenso BFT envolve uma quantidade considerável de comunicação. Enquanto avanços recentes permitem que o consenso seja alcançado em tempo linear em número de participantes (ver, por exemplo, [4]), ainda é perceptível uma sobrecarga por bloco; 2. É inviável que todos os participantes da rede participem do BFT consenso por bloco, portanto, geralmente apenas um subconjunto de participantes amostrados aleatoriamente chega ao consenso. Um conjunto amostrado aleatoriamente pode ser, em princípio, corrompido adaptativamente e, em teoria, uma bifurcação pode ser criada. O sistema ou precisa ser modelado para estar pronto para tal evento e, portanto, ainda ter uma regra de escolha de bifurcação além do consenso BFT ou ser projetado para fechar cair em tal evento. Vale ressaltar que alguns projetos, como Algorand [5], reduzem significativamente a probabilidade de corrupção adaptativa. 3. Mais importante ainda, o sistema para se 1 3 ou mais de todos os participantes são off-line. Assim, qualquer falha temporária na rede ou divisão da rede pode paralisar completamente o sistema. Idealmente, o sistema deve ser capaz de continuar a operar enquanto pelo menos metade dos participantes estiver online (mais pesado protocolos baseados em cadeia continuam operando mesmo que menos da metade dos participantes estejam online, mas a conveniência desta propriedade é mais discutível dentro da comunidade). Um modelo híbrido em que o consenso utilizado é algum tipo de consenso mais pesado cadeia, mas alguns blocos são finalizados periodicamente usando um gadget de finalização BFT mantendo as vantagens de ambos os modelos. Esses BFT gadgets de finalidade são Casper FFG [6] usado em Ethereum 2.0 8, Casper CBC (ver https://vitalik. ca/general/2018/12/05/cbc_casper.html) e GRANDPA (consulte https:// Medium.com/polkadot-network/d08a24a021b5) usado em Polkadot. Nightshade usa o consenso da cadeia mais pesada. Especificamente quando um bloco produtor produz um bloco (ver seção 3.3), ele pode coletar assinaturas de outros produtores de bloco e validators atestando o bloco anterior. Veja a seção 3.8 para obter detalhes sobre como um número tão grande de assinaturas é agregado. O peso 8 Veja também a sessão do quadro branco com Justin Drake para uma visão geral detalhada de Casper FFG e como ele está integrado ao consenso da cadeia mais pesada do GHOST aqui: https://www. youtube.com/watch?v=S262StTwkmode um bloco é então a aposta cumulativa de todos os signatários cujas assinaturas são incluído no bloco. O peso de uma corrente é a soma dos pesos dos blocos. No topo do consenso da cadeia mais pesada, usamos um gadget de finalidade que usa os atestados para finalizar os blocos. Para reduzir a complexidade do sistema, usamos um gadget de finalidade que não influencia de forma alguma a regra de escolha do fork, e, em vez disso, apenas introduz condições de corte extras, de modo que, uma vez que um bloco seja finalizado pelo gadget de finalidade, um fork é impossível, a menos que uma porcentagem muito grande da aposta total é reduzida. Casper CBC é um gadget de finalidade, e nós atualmente modelo com Casper CBC em mente. Também trabalhamos em um protocolo BFT separado chamado TxFlow. Na hora de ao escrever este documento, não está claro se o TxFlow será usado em vez do Casper CBC. Notamos, no entanto, que a escolha do dispositivo final é em grande parte ortogonal ao resto do design. 3.3 Produção de blocos No Nightshade existem duas funções: produtores de blocos e validators. Em qualquer ponto em que o sistema contém w produtores de blocos, w = 100 em nossos modelos e wv validators, em nosso modelo v = 100, wv = 10.000. O sistema é Prova de Participação, o que significa que tanto os produtores de blocos quanto os validators têm algum número de recursos internos moeda (referida como ”tokens”) bloqueada por um período de tempo muito superior ao tempo que gastam no desempenho de suas funções de construção e validação da cadeia. Tal como acontece com todos os sistemas de Prova de Participação, nem todos os produtores de blocos w e nem todos os wv validators são entidades diferentes, uma vez que isso não pode ser aplicado. Cada dos produtores de bloco w e dos wv validators, no entanto, têm um separado aposta. O sistema contém n fragmentos, n = 1000 em nosso modelo. Como mencionado em seção 3.1, no Nightshade não há shard chains, em vez disso, todos os produtores de blocos e validators estão construindo um único blockchain, que chamamos de cadeia principal. O estado da cadeia principal é dividido em n fragmentos, e cada bloco produtor e validator a qualquer momento apenas baixaram localmente um subconjunto de o estado que corresponde a algum subconjunto dos fragmentos, e apenas processar e validar transações que afetam essas partes do estado. Para se tornar um produtor de blocos, um participante da rede bloqueia alguns grandes quantidade de tokens (uma aposta). A manutenção da rede é feita em épocas, onde uma época é um período de tempo da ordem de dias. Os participantes com as maiores apostas no início de uma época específica são o bloco produtores daquela época. Cada produtor de bloco é atribuído a fragmentos sw (digamos sw = 40, o que tornaria sww/n = 4 produtores de blocos por fragmento). O bloco o produtor baixa o estado do fragmento ao qual foi atribuído antes da época começa e, ao longo da época, coleta transações que afetam esse fragmento, e os aplica ao estado. Para cada bloco b na cadeia principal, e para cada fragmento s, há um dos atribuiu produtores de blocos a s, que é responsável por produzir a parte de b relacionada para o fragmento. A parte de b relacionada ao shard s é chamada de chunk e contém o lista das transações do shard a serem incluídas em b, bem como o merkleraiz do estado resultante. b acabará por conter apenas um cabeçalho muito pequeno de o pedaço, ou seja, a raiz merkle de todas as transações aplicadas (veja a seção 3.7.1 para detalhes exatos) e a raiz Merkle do estado final. Ao longo do restante do documento, frequentemente nos referimos ao produtor do bloco que é responsável por produzir um pedaço em um determinado momento para um determinado fragmento como produtor de pedaços. O produtor de pedaços é sempre um dos produtores de blocos. Os produtores de blocos e os produtores de pedaços giram cada bloco de acordo a um horário fixo. Os produtores de blocos têm um pedido e produzem repetidamente blocos nessa ordem. Por exemplo se houver 100 produtores de blocos, o primeiro bloco produtores é responsável pela produção dos blocos 1, 101, 201 etc, o segundo é responsável pela produção de 2, 102, 202 etc). Como a produção de pedaços, ao contrário da produção de blocos, exige a manutenção o estado, e para cada fragmento apenas os produtores de blocos sww/n mantêm o estado por fragmento, correspondentemente apenas os produtores de blocos sww/n giram para criar pedaços. Por exemplo com as constantes acima com quatro produtores de blocos atribuídos a cada fragmento, cada produtor de bloco criará pedaços uma vez a cada quatro blocos. 3.4 Garantindo a disponibilidade dos dados Para garantir a disponibilidade dos dados, usamos uma abordagem semelhante à de Polkadot descrito na seção 2.5.3. Depois que um produtor de bloco produz um pedaço, ele cria uma versão codificada para eliminação com um código de bloco ideal (w, ⌊w/6 + 1⌋) do pedaço. Eles então enviam um pedaço do pedaço codificado para eliminação (chamamos esses pedaços partes de pedaços, ou apenas partes) para cada produtor de bloco. Calculamos uma árvore Merkle que contém todas as partes como as folhas e as o cabeçalho de cada pedaço contém a raiz merkle dessa árvore. As peças são enviadas para validators por meio de mensagens onepart. Cada uma dessas mensagens contém o cabeçalho do bloco, o ordinal da parte e o conteúdo da parte. O mensagem também contém a assinatura do produtor do bloco que produziu o chunk e o caminho merkle para provar que a parte corresponde ao cabeçalho e é produzido pelo produtor de bloco adequado. Uma vez que um produtor de bloco recebe um bloco da cadeia principal, ele primeiro verifica se ele tenha mensagens únicas para cada pedaço incluído no bloco. Caso contrário, o bloco não é processado até que as mensagens onepart ausentes sejam recuperadas. Uma vez recebidas todas as mensagens onepart, o produtor do bloco busca o partes restantes dos pares e reconstrói os pedaços para os quais eles mantêm o estado. O produtor do bloco não processa um bloco da cadeia principal se por pelo menos um pedaço incluído no bloco eles não têm a mensagem onepart correspondente, ou se pelo menos um shard para o qual eles mantêm o estado eles não podem reconstruir todo o pedaço. Para que um determinado pedaço esteja disponível basta que ⌊w/6⌋+1 do bloco os produtores têm suas partes e as servem. Assim, enquanto o número de atores maliciosos não excedem ⌊w/3⌋nenhuma cadeia que tenha mais da metade do bloco os produtores que o constroem podem ter pedaços indisponíveis.Figura 17: Cada bloco contém um ou zero pedaços por fragmento, e cada pedaço é codificado para eliminação. Cada parte do pedaço codificado para eliminação é enviada para um determinado produtor de bloco através de uma mensagem especial onepart 3.4.1 Lidando com produtores de blocos preguiçosos Se um produtor de bloco tiver um bloco para o qual falta uma mensagem onepart, ele pode optar por ainda assiná-lo, porque se o bloco acabar sendo encadeado, maximizará a recompensa para o produtor do bloco. Não há risco para o bloqueio produtor, uma vez que é impossível provar posteriormente que o produtor do bloco não tinha a mensagem de uma parte. Para resolver isso, tornamos cada pedaço produtor ao criar o pedaço para escolha uma cor (vermelho ou azul) para cada parte do futuro bloco codificado e armazene a máscara de bits da cor atribuída no pedaço antes de ser codificada. Cada parte mensagem então contém a cor atribuída à peça, e a cor é usada quando calcular a raiz merkle das partes codificadas. Se o produtor do pedaço se desviar do protocolo, isso pode ser facilmente comprovado, já que a raiz merkle não correspondem a mensagens de uma parte ou às cores nas mensagens de uma parte que corresponder à raiz merkle não corresponderá à máscara no pedaço. Quando um produtor de bloco assina um bloco, ele inclui uma máscara de bits de todos os peças vermelhas que receberam pelos pedaços incluídos no bloco. Publicando um máscara de bits incorreta é um comportamento que pode ser cortado. Se um produtor de bloco não tiver recebido um mensagem única, eles não têm como saber a cor da mensagem e portanto, têm 50% de chance de serem cortados se tentarem assinar cegamente o bloco. 3.5 Pedido de transição de estado Os produtores de pedaços escolhem apenas quais transações incluir no pedaço, mas não aplique a transição de estado quando produzirem um pedaço. Correspondentemente,
o cabeçalho do bloco contém a raiz merkle do estado merkelizado de antes as transações no bloco são aplicadas. As transações só são aplicadas quando um bloco completo que inclui o pedaço é processado. Um participante só processa um bloco se 1. O bloco anterior foi recebido e processado; 2. Para cada pedaço, o participante não mantém o estado, pois possui vi a mensagem única; 3. Para cada pedaço, o participante mantém o estado, pois tem o pedaço inteiro. Depois que o bloco estiver sendo processado, para cada fragmento para o qual o participante mantém o estado, eles aplicam as transações e calculam o novo estado a partir da aplicação das transações, após o que elas estarão prontas para produzir os pedaços para o próximo bloco, se eles forem atribuídos a qualquer shard, uma vez que eles têm a raiz merkle do novo estado merkelizado. 3.6 Transações e recebimentos entre fragmentos Se uma transação precisar afetar mais de um fragmento, ela precisará ser consecutivamente executado em cada fragmento separadamente. A transação completa é enviada para o primeiro fragmento afetado, e uma vez que a transação é incluída no pedaço para tal fragmento, e é aplicado depois que o pedaço é incluído em um bloco, ele gera um chamado recibo transação, que é roteada para o próximo shard no qual a transação precisa ser executado. Se forem necessárias mais etapas, a execução da transação de recebimento gera uma nova transação de recebimento e assim por diante. 3.6.1 Vida útil da transação de recebimento É desejável que a transação de recebimento seja aplicada no bloco imediatamente seguinte ao bloco em que foi gerada. A transação de recebimento é apenas gerado após o bloco anterior ter sido recebido e aplicado pelos produtores do bloco que mantêm o fragmento de origem e precisa ser conhecido no momento em que o pedaço para o próximo bloco é produzido pelos produtores de bloco do destino fragmento. Assim, o recebimento deve ser comunicado do fragmento de origem ao fragmento de destino no curto período entre esses dois eventos. Seja A o último bloco produzido que contém uma transação t que gera um recibo r. Seja B o próximo bloco produzido (ou seja, um bloco que tem A como seu bloco anterior) que queremos conter r. Seja t no fragmento a e r no fragmento b. O tempo de vida do recibo, também representado na figura 18, é o seguinte: Produzir e armazenar os recibos. O CPA do produtor de pedaços para shard a recebe o bloco A, aplica a transação t e gera o recibo r. cpa em seguida, armazena todos esses recibos produzidos em seu armazenamento interno persistente indexado pelo ID do fragmento de origem.Distribuindo as receitas. Quando o cpa estiver pronto para produzir o pedaço para fragmento a para o bloco B, eles buscam todos os recibos gerados pela aplicação das transações do bloco A para o fragmento a e os incluem no bloco do fragmento a no bloco B. Uma vez gerado esse pedaço, cpa produz seu apagamento codificado versão e todas as mensagens onepart correspondentes. cpa sabe quais produtores de blocos mantêm o estado completo para quais fragmentos. Para um determinado produtor de blocos bp cpa inclui os recebimentos resultantes da aplicação de transações do bloco A para o fragmento a que possui qualquer um dos fragmentos com os quais bp se preocupa como destino na mensagem onepart quando eles distribuíram o pedaço para o fragmento A no bloco B (veja a figura 17, que mostra os recibos incluídos na mensagem onepart). Recebendo os recibos. Lembre-se de que os participantes (produtores de bloco e validators) não processam blocos até que tenham mensagens de uma parte para cada pedaço incluído no bloco. Assim, no momento em que qualquer participante em particular aplica o bloco B, ele possui todas as mensagens de uma parte que correspondem a pedaços em B e, portanto, eles têm todas as receitas recebidas que possuem os fragmentos o participante mantém o estado como destino. Ao aplicar o transição de estado para um fragmento específico, o participante aplica ambos os recibos que eles coletaram para o fragmento nas mensagens únicas, bem como todos as transações incluídas no próprio pedaço. Figura 18: A vida útil de uma transação de recebimento 3.6.2 Lidando com muitos recibos É possível que o número de recibos direcionados a um fragmento específico em um determinado bloco é muito grande para ser processado. Por exemplo, considere a figura 19, em em que cada transação em cada fragmento gera um recibo direcionado ao fragmento 1. No próximo bloco, o número de recibos que o fragmento 1 precisa processar é comparável à carga que todos os fragmentos combinados processaram durante o manuseio o bloco anterior.
Figura 19: Se todos os recibos forem direcionados ao mesmo fragmento, o fragmento poderá não ter a capacidade de processá-los Para resolver isso usamos uma técnica semelhante à usada no QuarkChain 9. Especificamente, para cada fragmento, o último bloco B e o último fragmento s dentro desse é registrado o bloco a partir do qual os recebimentos foram aplicados. Quando o novo fragmento for criado, os recibos são aplicados em ordem primeiro a partir dos fragmentos restantes em B, e depois nos blocos que seguem B, até que o novo pedaço esteja cheio. Sob normal circunstâncias com uma carga equilibrada, geralmente resultará em todos os recebimentos sendo aplicado (e assim o último fragmento do último bloco será gravado para cada pedaço), mas durante momentos em que a carga não está equilibrada e um determinado shard recebe muitas receitas desproporcionalmente, esta técnica permite que eles ser processado respeitando os limites do número de transações incluídas. Observe que se tal carga desequilibrada permanecer por muito tempo, o atraso de a criação de recibos até que a aplicação possa continuar crescendo indefinidamente. Um maneira de resolver isso é descartar qualquer transação que crie um recibo direcionado a um fragmento que possui um atraso de processamento que excede alguma constante (por exemplo, uma época). Considere a figura 20. No bloco B, o fragmento 4 não pode processar todos os recibos, portanto, ele processa apenas a origem de recibos de até o fragmento 3 no bloco A, e registra isso. No bloco C estão incluídos os recibos até o fragmento 5 do bloco B, e então, no bloco D, o fragmento alcança, processando todos os recibos restantes em bloco B e todas as receitas do bloco C. 3.7 Validação de pedaços Um pedaço produzido para um shard específico (ou um bloco de shard produzido para uma cadeia de shard específica no modelo com cadeias de shard) só pode ser validado pelo 9Veja o episódio do quadro branco com QuarkChain aqui: https://www.youtube.com/watch? v=opEtG6NM4x4, em que a abordagem para transações entre fragmentos é discutida, entre outros coisasFigura 20: Processamento de recibos atrasado participantes que mantêm o estado. Eles podem ser produtores de blocos, validators, ou apenas testemunhas externas que baixaram o estado e validaram o fragmento em quais eles armazenam ativos. Neste documento assumimos que a maioria dos participantes não consegue armazenar o estado para uma grande fração dos fragmentos. Vale ressaltar, porém, que existem blockchains fragmentados que são projetados com a suposição de que a maioria dos participantes tem capacidade de armazenar o estado e validar a maioria dos os fragmentos, como QuarkChain. Como apenas uma fração dos participantes tem estado para validar o fragmento pedaços, é possível corromper adaptativamente apenas os participantes que têm o estado e aplicar uma transição de estado inválida. Vários designs de fragmentação foram propostos para amostrar validators a cada poucos dias e dentro de um dia qualquer bloco na cadeia de fragmentos que tenha mais de 2/3 de assinaturas dos validators atribuídos a tal fragmento é imediatamente considerada final. Com tal abordagem, um adversário adaptativo só precisa corromper 2n/3+1 dos validators em uma cadeia de fragmentos para aplicar uma transição de estado inválida, que, embora seja provavelmente difícil de conseguir, não é um nível de segurança suficiente para um público blockchain. Conforme discutido na seção 2.3, a abordagem comum é permitir uma certa janela de tempo após a criação de um bloco para qualquer participante que tenha estado (seja é um produtor de bloco, um validator ou um observador externo) para desafiar sua validade. Esses participantes são chamados de Pescadores. Para que um pescador possa desafiar um bloco inválido, deve-se garantir que tal bloco esteja disponível para eles. A disponibilidade de dados no Nightshade é discutida na seção 3.4. No Nightshade, uma vez produzido um bloco, os pedaços não foram validados pelo qualquer um, exceto o próprio produtor do pedaço. Em particular, o produtor de blocos que sugeriu que o bloco naturalmente não tinha o estado para a maioria dos fragmentos, enão foi capaz de validar os pedaços. Quando o próximo bloco é produzido, ele contém atestados (ver seção 3.2) de múltiplos produtores de blocos e validators, mas como a maioria dos produtores de blocos e validators não mantêm o estado também para a maioria dos shards, um bloco com apenas um pedaço inválido coletará significativamente mais da metade dos atestados e continuará sendo o bloco mais pesado. cadeia. Para resolver esse problema, permitimos que qualquer participante que mantenha o estado de um fragmento para enviar um desafio na cadeia para qualquer pedaço inválido produzido naquele fragmento. 3.7.1 Desafio de validade do estado Depois que um participante detecta que um determinado pedaço é inválido, ele precisa fornecer uma prova de que o pedaço é inválido. Como a maioria dos participantes da rede não mantém o estado do fragmento no qual o pedaço inválido está produzido, a prova precisa ter informações suficientes para confirmar que o bloco é inválido sem ter o estado. Definimos um limite Ls da quantidade de estado (em bytes) que uma única transação pode ler ou escrever cumulativamente. Qualquer transação que toque mais de Ls estado é considerado inválido. Lembre-se da seção 3.5 que o pedaço em um determinado bloco B contém apenas as transações a serem aplicadas, mas não a nova raiz do estado. A raiz de estado incluída no pedaço do bloco B é o estado root antes de aplicar tais transações, mas depois de aplicar as transações de o último pedaço no mesmo fragmento antes do bloco B. Um ator malicioso que deseja aplicar uma transição de estado inválida incluiria uma raiz de estado incorreta no bloco B que não corresponde à raiz de estado resultante da aplicação as transações no bloco anterior. Estendemos as informações que um produtor de pedaços inclui no pedaço. Em vez de incluir apenas o estado depois de aplicar todas as transações, inclui uma raiz de estado após aplicar cada conjunto contíguo de transações que ler e escrever coletivamente Ls bytes de estado. Com essas informações para pescador criar o desafio de que uma transição de estado seja aplicada incorretamente, é suficiente para encontrar a primeira raiz de estado inválida e incluir apenas Ls bytes de estado que são afetados pelas transações entre a última raiz de estado (que foi válido) e a raiz do estado atual com as provas Merkle. Então qualquer participante pode validar as transações no segmento e confirmar que o pedaço está inválido. Da mesma forma, se o produtor do bloco tentasse incluir transações que leem e escrever mais de Ls bytes de estado, para o desafio basta incluir os primeiros Ls bytes que ele toca com as provas merkle, o que será suficiente para aplicar as transações e confirmar que há um momento em que uma tentativa de é feita a leitura ou gravação de conteúdo além de Ls bytes.
3.7.2 Pescadores e transações rápidas entre fragmentos Conforme discutido na seção 2.3, uma vez que assumimos que os pedaços de fragmento (ou fragmentos blocos no modelo com cadeias de fragmentos) podem ser inválidos e apresentar um desafio período, isso afeta negativamente a finalidade e, portanto, a comunicação entre fragmentos. Em em particular, o fragmento de destino de qualquer transação entre fragmentos não pode ser certo o fragmento ou bloco de origem é final até que o período de desafio termine (ver figura 21). Figura 21: Aguardando o período de desafio antes de aplicar um recibo A maneira de lidar com isso de uma forma que torne as transações entre fragmentos Instantâneo é para o fragmento de destino não esperar pelo período do desafio após a transação do fragmento de origem ser publicada e aplicar a transação de recebimento imediatamente, mas depois reverta o fragmento de destino junto com o fragmento de origem fragmento se posteriormente o pedaço ou bloco de origem for considerado inválido (veja a figura 22). Isso se aplica muito naturalmente ao design do Nightshade, no qual o fragmento as cadeias não são independentes, mas em vez disso, os fragmentos são todos publicados juntos no mesmo bloco da cadeia principal. Se algum pedaço for considerado inválido, o bloco inteiro com esse pedaço é considerado inválido e todos os blocos construídos nele topo disso. Veja a figura 23. Ambas as abordagens acima fornecem atomicidade, assumindo que o desafio período é suficientemente longo. Usamos a última abordagem, uma vez que fornecer transações cruzadas rápidas em circunstâncias normais supera a inconveniência de o fragmento de destino sendo revertido devido a uma transição de estado inválida em um dos os fragmentos de origem, o que é um evento extremamente raro. 3.7.3 Escondendo validators A existência dos desafios já reduz significativamente a probabilidade de corrupção adaptativa, já que para finalizar um pedaço com uma transição de estado inválida posteFigura 22: Aplicando recibos imediatamente e revertendo o destino cadeia se a cadeia de origem tiver um bloco inválido Figura 23: Desafio do pescador em Nightshade o período de desafio que o adversário adaptativo precisa para corromper todos os participantes que mantêm o estado do fragmento, incluindo todos os validators. Estimar a probabilidade de tal evento é extremamente complexo, uma vez que não sharded blockchain está ativo há tempo suficiente para que qualquer ataque desse tipo seja tentado. Argumentamos que a probabilidade, embora extremamente baixa, ainda é suficientemente grande para um sistema que deverá executar milhões de transações e executar operações financeiras em todo o mundo. Existem duas razões principais para esta crença: 1. A maioria dos validators das redes de Prova de Participação e mineradores do
As cadeias de prova de trabalho são incentivadas principalmente pela vantagem financeira. Se um adversário adaptativo oferece-lhes mais dinheiro do que o retorno esperado de operar honestamente, é razoável esperar que muitos validators aceitará a oferta. 2. Muitas entidades validam cadeias de Prova de Participação profissionalmente e espera-se que uma grande percentagem da participação em qualquer cadeia seja de tais entidades. O número de tais entidades é suficientemente pequeno para uma adversário adaptativo para conhecer a maioria deles pessoalmente e ter uma boa compreensão de sua inclinação para serem corrompidos. Damos um passo adiante na redução da probabilidade de corrupção adaptativa, ocultando quais validators estão atribuídos a qual fragmento. A ideia é remotamente semelhante à maneira como Algorand [5] esconde validators. É fundamental observar que mesmo que os validators estejam ocultos, como em Algorand ou conforme descrito abaixo, a corrupção adaptativa ainda é, em teoria, possível. Enquanto o adversário adaptativo não conhece os participantes que irão criar ou validar um bloco ou pedaço, os próprios participantes sabem que irão realizar tal tarefa e ter uma prova criptográfica disso. Assim, o adversário pode transmitir sua intenção de corromper e pagar a qualquer participante que forneça tal prova criptográfica. Notamos, no entanto, que como o adversário não conhecem os validators atribuídos ao fragmento que desejam corromper, eles não têm outra escolha a não ser transmitir sua intenção de corromper um fragmento específico para toda a comunidade. Nesse ponto, é economicamente benéfico para qualquer pessoa honesta. participante para criar um nó completo que valide esse fragmento, já que há um alto chance de um bloco inválido aparecer naquele fragmento, o que é uma oportunidade para crie um desafio e receba a recompensa associada. Para não revelar os validators atribuídos a um fragmento específico, fazemos o seguinte (ver figura 24): Usando VRF para obter a tarefa. No início de cada época cada validator usa um VRF para obter uma máscara de bits dos fragmentos aos quais validator está atribuído. A máscara de bits de cada validator terá bits Sw (veja seção 3.3 para a definição de Sw). O validator então busca o estado dos fragmentos correspondentes e durante a época para cada bloco recebido valida os pedaços que correspondem aos fragmentos aos quais validator está atribuído. Assine em blocos em vez de pedaços. Como a atribuição de fragmentos está oculta, validator não pode assinar fragmentos. Em vez disso, ele sempre assina por completo bloco, não revelando assim quais fragmentos ele valida. Especificamente, quando validator recebe um bloco e valida todos os pedaços, ele cria uma mensagem que atesta que todos os pedaços em todos os fragmentos aos quais validator está atribuído são válido (sem indicar de forma alguma quais são esses fragmentos) ou uma mensagem que contém uma prova de uma transição de estado inválida se algum pedaço for inválido. Veja o seção 3.8 para detalhes sobre como essas mensagens são agregadas, seção 3.7.4 para os detalhes sobre como evitar que validators pegue carona em mensagens de outros validators e seção 3.7.5 para detalhes sobre como recompensar e punir validators caso um desafio de transição de estado inválido bem-sucedido realmente aconteça.Figura 24: Escondendo os validators no Nightshade 3.7.4 Comprometer-Revelar Um dos problemas comuns com validators é que um validator pode pular o download do estado e realmente validar os pedaços e blocos e, em vez disso, observe a rede, veja o que os outros validators enviam e repita seus mensagens. Um validator que segue tal estratégia não fornece nenhum extra segurança para a rede, mas coleta recompensas. Uma solução comum para este problema é cada validator fornecer uma prova que eles realmente validaram o bloco, por exemplo, fornecendo um rastreamento exclusivo de aplicar a transição de estado, mas tais provas aumentam significativamente o custo de validação. Figura 25: Confirmar-revelar
Em vez disso, fazemos com que os validators primeiro se comprometam com o resultado da validação (seja a mensagem que atesta a validade dos pedaços, ou a prova de um inválido transição de estado), aguarde um determinado período, e só então revele o resultado real da validação, conforme mostrado na figura 25. O período de commit não se cruza com o período de revelação e, portanto, um validator preguiçoso não pode copiar validators honestos. Além disso, se um validator desonesto se comprometeu com uma mensagem que atesta a validade dos pedaços atribuídos, e pelo menos um pedaço era inválido, uma vez que é mostrado que o pedaço é inválido, o validator não pode evitar a redução, pois, como mostramos na seção 3.7.5, a única maneira de não ser cortado em tal situação é apresentar uma mensagem que contenha uma prova da transição de estado inválida que corresponde ao commit. 3.7.5 Lidando com desafios Conforme discutido acima, uma vez que um validator recebe um bloco com um pedaço inválido, eles primeiro preparam uma prova da transição de estado inválida (ver seção 3.7.1), depois comprometa-se com tal prova (ver 3.7.4) e, após algum período, revele o desafio. Uma vez que o desafio revelado é incluído em um bloco, acontece o seguinte: 1. Todas as transições de estado que aconteceram no bloco que contém o pedaço inválido até que o bloco no qual o desafio revelado está incluído seja obtido anulado. O estado antes do bloco que inclui o desafio revelado é considerado o mesmo que o estado antes do bloco que continha o pedaço inválido. 2. Dentro de um determinado período de tempo cada validator deve revelar sua bitmask dos fragmentos que eles validam. Como a máscara de bits é criada através de um VRF, se eles foram atribuídos ao fragmento que tinha a transição de estado inválida, eles não pode evitar revelá-lo. Qualquer validator que não revele a máscara de bits é considerado atribuído ao fragmento. 3. Cada validator que após esse período for atribuído ao shard, que se comprometeu com algum resultado de validação para o bloco que contém o pedaço inválido e que não revelou a prova de transição de estado inválida que corresponde ao seu commit é cortado. 4. Cada validator recebe uma nova atribuição de fragmentos e uma nova época é agendada para começar depois de algum tempo suficiente para que todos os validators baixem o estado, conforme mostrado na figura 26. Observe que a partir do momento em que os validators revelam os fragmentos aos quais são atribuídos até que a nova época comece, a segurança do sistema é reduzida, uma vez que o a atribuição de fragmentos é revelada. Os participantes da rede precisam mantê-la em mente ao usar a rede durante esse período. 3.8 Agregação de Assinatura Para que um sistema com centenas de fragmentos opere com segurança, queremos ter no ordem de 10.000 ou mais validators. Conforme discutido na seção 3.7, queremos que cadaFigura 26: Lidando com o desafio validator para publicar um commit para uma determinada mensagem e uma assinatura em média uma vez por bloco. Mesmo que as mensagens de commit fossem as mesmas, agregar tal A assinatura BLS e sua validação teriam sido proibitivamente caras. Mas naturalmente, as mensagens de confirmação e revelação não são as mesmas em validators, e, portanto, precisamos de alguma forma de agregar essas mensagens e as assinaturas em um maneira que permite uma validação rápida posteriormente. A abordagem específica que usamos é a seguinte: Validadores juntando-se aos produtores de blocos. Os produtores de blocos são conhecidos algum tempo antes do início da época, pois eles precisam de algum tempo para baixar o estado antes do início da época e, ao contrário dos validators, os produtores de blocos são não escondido. Cada produtor de bloco possui v validator slots. Validadores enviam propostas fora da cadeia aos produtores de blocos para serem incluídos como um de seus v validators. Se um produtor de bloco desejar incluir um validator, ele enviará um transação que contém a solicitação inicial fora da cadeia do validator e o assinatura do produtor do bloco que faz com que validator se junte ao produtor do bloco. Observe que os validators atribuídos aos produtores de blocos não necessariamente valide os mesmos fragmentos para os quais o produtor do bloco produz pedaços. Se um validator aplicado para ingressar em vários produtores de blocos, apenas a transação de o primeiro produtor de bloco terá sucesso. Os produtores de blocos coletam commits. O produtor do bloco coleta constantemente as mensagens de commit e revelação dos validators. Uma vez que um certo número dessas mensagens é acumulado, o produtor do bloco calcula um Merkle árvore dessas mensagens e envia para cada validator a raiz merkle e o merkle caminho para sua mensagem. O validator valida o caminho e faz login a raiz de merkle. O produtor do bloco então acumula uma assinatura BLS no raiz merkle de validators e publica apenas a raiz merkle e o assinatura acumulada. O produtor do bloco também assina a validade do multiassinatura usando uma assinatura ECDSA barata. Se a assinatura múltipla não corresponder à raiz merkle enviada ou à máscara de bits dos validators participantes, é um comportamento que pode ser cortado. Ao sincronizar a cadeia, um participante pode optar por validar todas as assinaturas BLS dos validators (o que é extremamente caro, pois envolve a agregação de chaves públicas de validators), ou apenasas assinaturas ECDMA dos produtores de blocos e contam com o fato de que o o produtor do bloco não foi desafiado e cortado. Usando transações on-chain e provas Merkle para desafios. Isso pode-se notar que não há valor em revelar mensagens de validators se não transição de estado inválida foi detectada. Somente as mensagens que contêm o real provas de transição de estado inválida precisam ser reveladas, e apenas para tais mensagens é preciso mostrar que eles correspondem ao commit anterior. A mensagem precisa ser revelado para dois propósitos: 1. Para realmente iniciar a reversão da cadeia para o momento anterior ao transição de estado inválida (ver seção 3.7.5). 2. Para provar que o validator não tentou atestar a validade do pedaço inválido. Em ambos os casos, precisamos abordar duas questões: 1. O commit real não foi incluído na cadeia, apenas a raiz merkle do commit agregado com outras mensagens. O validator precisa usar o caminho merkle fornecido pelo produtor do bloco e seu compromisso original com provar que eles se comprometeram com o desafio. 2. É possível que todos os validators atribuídos ao fragmento com o inválido transição de estado foi atribuída a produtores de blocos corrompidos que estão censurando-os. Para contornar isso, permitimos que eles enviem suas revelações como uma transação regular on-chain e ignorar a agregação. Este último só é permitido para as provas de transição de estado inválida, que são extremamente raro e, portanto, não deve resultar em spam nos blocos. A questão final que precisa ser abordada é que os produtores de blocos podem optar por não participar da agregação de mensagens ou censurar intencionalmente determinados validators. Tornamo-lo economicamente desvantajoso, ao tornar o bloco recompensa do produtor proporcional ao número de validators atribuídos a eles. Nós observe também que, uma vez que os produtores de blocos entre épocas se cruzam amplamente (já que são sempre os principais participantes com a aposta mais alta), os validators podem em grande parte, limitar-se a trabalhar com os mesmos produtores de blocos e, assim, reduzir o risco de serem atribuídos a um produtor de blocos que os censurou no passado. 3.9 Cadeia de instantâneos Como os blocos da cadeia principal são produzidos com muita frequência, o download o histórico completo pode ficar caro muito rapidamente. Além disso, uma vez que cada bloco contém uma assinatura BLS de um grande número de participantes, apenas a agregação das chaves públicas para verificar a assinatura pode se tornar proibitiva caro também. Finalmente, uma vez que em qualquer futuro previsível Ethereum 1.0 provavelmente permanecerá um dos blockchains mais usados, tendo uma maneira significativa de transferir ativos de
Perto de Ethereum é um requisito, e hoje verificar assinaturas BLS para garantir A validade de quase blocos no lado de Ethereum não é possível. Cada bloco na cadeia principal do Nightshade pode conter opcionalmente um Schnorr multiassinatura no cabeçalho do último bloco que incluía tal Schnorr multiassinatura. Chamamos esses blocos de blocos instantâneos. O primeiro bloco de cada época deve ser um bloco de instantâneo. Enquanto trabalhava em tal assinatura múltipla, os produtores de blocos também devem acumular as assinaturas BLS dos validators no último bloco de instantâneo e agregue-os da mesma maneira descrita em seção 3.8. Como o conjunto de produtores de blocos é constante ao longo da época, validando apenas os primeiros blocos de instantâneos em cada época são suficientes, assumindo que em nenhum momento apontam que uma grande porcentagem de produtores de blocos e validators conspiraram e criaram um garfo. O primeiro bloco da época deve conter informações suficientes para calcular os produtores de blocos e validators para a época. Chamamos a subcadeia da cadeia principal que contém apenas o instantâneo bloqueia uma cadeia de instantâneos. Criar uma multiassinatura Schnorr é um processo interativo, mas como só precisa executá-lo com pouca frequência, qualquer processo, não importa quão ineficiente, será suficiente. As multiassinaturas Schnorr podem ser facilmente validadas em Ethereum, fornecendo assim primitivas cruciais para uma maneira segura de realizar cross-blockchain comunicação. Para sincronizar com a cadeia Near, basta baixar todos os instantâneos blocos e confirme se as assinaturas Schnorr estão corretas (opcionalmente também verificando as assinaturas BLS individuais dos validators) e, em seguida, apenas sincronizando blocos da cadeia principal do último bloco de snapshot.
Conclusión
En este documento analizamos enfoques para crear blockchains fragmentados y cubrió dos desafíos principales con los enfoques existentes, a saber, la validez del estado y disponibilidad de datos. Luego presentamos Nightshade, un diseño de fragmentación que poderes NEAR Protocolo. El diseño es un trabajo en progreso, si tiene comentarios, preguntas o comentarios en este documento, vaya a https://near.chat.
Conclusão
Neste documento discutimos abordagens para construir blockchains fragmentados e cobriu dois grandes desafios com as abordagens existentes, nomeadamente a validade do estado e disponibilidade de dados. Em seguida, apresentamos o Nightshade, um design de fragmentação que poderes NEAR Protocolo. O design está em andamento, se você tiver comentários, perguntas ou feedback neste documento, vá para https://near.chat.