Le livre blanc NEAR
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.
Validité de l’état et disponibilité des données
L'idée centrale des blockchain fragmentés est que la plupart des participants opérant ou l'utilisation du réseau ne peut pas valider les blocs dans tous les fragments. Ainsi, chaque fois tout participant doit interagir avec un fragment particulier qu'il ne peut généralement pas téléchargez et validez tout l’historique du fragment. L’aspect partitionnement du sharding soulève cependant un potentiel important. problème : sans télécharger et valider tout l'historique d'un particulier fragment, le participant ne peut pas nécessairement être certain que l'état avec lequel il 5Cette section, à l'exception de la sous-section 2.5.3, a été publiée précédemment à https://near.ai/ fragment2. Si vous l'avez déjà lu, passez à la section suivante.
ils interagissent est le résultat d’une séquence valide de blocs et que cette séquence de blocs est en effet la chaîne canonique du fragment. Un problème qui n'existe pas exister dans un blockchain non fragmenté. Nous présenterons dans un premier temps une solution simple à ce problème qui a été proposée par de nombreux protocoles, puis analyser comment cette solution peut échouer et ce qui des tentatives ont été faites pour y remédier. 2.1 Rotation des validateurs La solution naïve de la validité d’état est illustrée à la figure 5 : disons que nous supposons que l'ensemble du système possède de l'ordre de milliers de validator, parmi lesquels pas plus de 20 % sont malveillants ou échoueront autrement (par exemple en ne parvenant pas à être en ligne pour produire un bloc). Alors si nous échantillonnons 200 validators, la probabilité de plus de 1 3, pour des raisons pratiques, peut être considéré comme étant nul. Figure 5 : Échantillonnage de validators 1 3 est un seuil important. Il existe une famille de protocoles de consensus, appelés BFT protocoles de consensus, qui garantissent que pendant moins de 1 3 de les participants échouent, soit en s'écrasant, soit en agissant d'une manière qui viole le protocole, le consensus sera atteint. Avec cette hypothèse de pourcentage honnête de validator, si l'ensemble actuel de validators dans un fragment nous fournit un bloc, la solution naïve suppose que le bloc est valide et qu'il est construit sur ce que les validator pensaient être la chaîne canonique pour ce fragment lorsqu'ils ont commencé la validation. Les validator appris la chaîne canonique de l'ensemble précédent de validator, qui par la même hypothèse construite au sommet du bloc qui était la tête de la chaîne canonique avant ça. Par induction toute la chaîne est valide, et puisqu'aucun ensemble de validators à tout moment produit des fourches, la solution naïve est aussi certaine que le courant chain est la seule chaîne du fragment. Voir la figure 6 pour une visualisation.
Figure 6 : Un blockchain avec chaque bloc finalisé via le consensus BFT Cette solution simple ne fonctionne pas si nous supposons que les validator peuvent être corrompu de manière adaptative, ce qui n’est pas une hypothèse déraisonnable6. De manière adaptative corrompre un seul fragment dans un système comportant 1 000 fragments est beaucoup moins cher que de corrompre tout le système. Par conséquent, la sécurité du protocole diminue linéairement avec le nombre de fragments. Pour avoir la certitude de la validité de un bloc, nous devons savoir qu'à aucun moment de l'histoire aucun fragment du système n'a une majorité de validators sont de connivence ; avec des adversaires adaptatifs, nous n'avons plus une telle certitude. Comme nous l'avons vu dans la section 1.5, les validator de connivence peuvent exercer deux comportements malveillants de base : créer des forks et produire des blocs invalides. Les forks malveillants peuvent être résolus par des blocs réticulés à la chaîne Beacon qui est généralement conçue pour avoir une sécurité nettement supérieure à celle de Beacon. les chaînes d'éclats. Cependant, produire des blocs invalides est beaucoup plus compliqué. problème difficile à résoudre. 2.2 Validité de l'État Considérons la figure 7 sur laquelle le fragment n°1 est corrompu et un acteur malveillant produit bloc B invalide. Supposons que dans ce bloc B 1000 tokens aient été frappés à partir de minces diffusé sur le compte d’Alice. L'acteur malveillant produit alors un bloc C valide (dans un sens que les transactions en C sont appliquées correctement) au-dessus de B, obscurcissant le bloc B invalide et initie une transaction entre fragments vers le fragment n°2 qui transfère ces 1 000 token sur le compte de Bob. A partir de ce moment le mal Les token créés résident sur un blockchain par ailleurs entièrement valide dans le fragment n°2. Voici quelques approches simples pour résoudre ce problème : 6Lire ceci article pour détails sur comment adaptatif la corruption peut être porté dehors : https://medium.com/nearprotocol/d859adb464c8. Pour plus détails sur adaptatif la corruption, lire https://github.com/ethereum/wiki/wiki/Sharding-FAQ# quels-sont-les-modèles-de-sécurité-dans lesquels-nous-opérons-Figure 7 : Une transaction entre fragments d'une chaîne qui a un bloc invalide 1. Pour validators du Shard #2 pour valider le bloc à partir duquel la transaction est initiée. Cela ne fonctionnera pas même dans l'exemple ci-dessus, puisque le bloc C semble être tout à fait valable. 2. Pour les validator dans le fragment n°2 pour valider un grand nombre de blocs précédant le bloc à partir duquel la transaction est initiée. Naturellement, pour n'importe quel nombre de blocs N validés par le fragment récepteur du malware Les validator peuvent créer N+1 blocs valides au-dessus du bloc invalide qu'ils ont produit. Une idée prometteuse pour résoudre ce problème serait d'organiser les fragments dans un graphe non orienté dans lequel chaque fragment est connecté à plusieurs autres fragments, et autoriser uniquement les transactions entre fragments entre fragments voisins (par exemple, voici comment Le sharding de Vlad Zamfir fonctionne pour l’essentiel7, et une idée similaire est utilisée dans l’ouvrage de Kadena. Toile de chaîne [1]). Si une transaction entre fragments est nécessaire entre des fragments qui sont et non des voisins, une telle transaction est acheminée via plusieurs fragments. Dans cette conception un validator dans chaque fragment devrait valider à la fois tous les blocs de leur fragment ainsi que tous les blocs de tous les fragments voisins. Considérons une figure ci-dessous avec 10 fragments, chacun ayant quatre voisins, et pas deux fragments nécessitant plus plus de deux sauts pour une communication entre fragments illustrée à la figure 8. Le fragment n°2 valide non seulement ses propres blockchain, mais également les blockchain de tous les voisins, y compris Shard #1. Donc si un acteur malveillant sur le Shard #1 tente de créer un bloc B invalide, puis de construire le bloc C par-dessus et lancez une transaction entre fragments, une telle transaction entre fragments ne se déroulera pas puisque Shard #2 aura validé tout l'historique du Shard #1 qui le fera identifier le bloc B invalide. 7En savoir plus sur le design ici : https://medium.com/nearprotocol/37e538177ed9
Figure 8 : Une transaction entre fragments non valide dans un système de type chainweb qui être détecté Même si corrompre un seul fragment n'est plus une attaque viable, corrompre un seul fragment n'est plus une attaque viable. quelques fragments restent un problème. Sur la figure 9 un adversaire corrompt les deux Shard
1 et Shard #2 exécutent avec succès une transaction entre fragments avec Shard #3
avec des fonds provenant d'un bloc B invalide : Figure 9 : Une transaction entre fragments non valide dans un système de type chainweb qui ne pas être détecté Le fragment n°3 valide tous les blocs du fragment n°2, mais pas du fragment n°1, et n'a aucun moyen de détecter le bloc malveillant. Il existe deux directions principales pour résoudre correctement la validité d’état : les pêcheurs
et des preuves cryptographiques de calcul. 2.3 Pêcheur L'idée derrière la première approche est la suivante : chaque fois qu'un en-tête de bloc est communiqué entre les chaînes à quelque fin que ce soit (comme la réticulation avec le chaîne de balises, ou une transaction entre fragments), il y a une période de temps pendant lequel tout validator honnête peut fournir une preuve que le blocage est invalide. Là existe diverses constructions qui permettent des preuves très succinctes que les blocs sont invalide, donc la surcharge de communication pour les nœuds de réception est bien moindre que celui de recevoir un bloc complet. Avec cette approche tant qu’il y aura au moins un validator honnête dans le fragment, le système est sécurisé. Figure 10 : Pêcheur C’est l’approche dominante (en plus de prétendre que le problème n’existe pas) parmi les protocoles proposés aujourd’hui. Cette approche comporte cependant deux inconvénients majeurs : 1. La période de contestation doit être suffisamment longue pour l'honnête validator pour reconnaître qu'un bloc a été produit, le télécharger, le vérifier entièrement et préparer le défi si le bloc est invalide. L'introduction d'une telle période permettrait ralentir considérablement les transactions entre fragments. 2. L’existence du protocole de challenge crée un nouveau vecteur d’attaques lorsque des nœuds malveillants spamment avec des défis non valides. Une solution évidente à ce problème est d'obliger les challengers à déposer une certaine quantité de tokens qui sont rendus si le défi est valide. Il ne s'agit là que d'une solution partielle, car elle pourrait toujours être bénéfique pour l'adversaire de spammer le système (et de graver les dépôts) avec des défis invalides, par exemple pour empêcher ledéfi d'un honnête validator de passer à travers. Ces attaques sont appelés attaques de deuil. Voir la section 3.7.2 pour savoir comment contourner ce dernier point. 2.4 Arguments succincts et non interactifs de la connaissance La deuxième solution à la corruption de plusieurs fragments consiste à utiliser une sorte de construction cryptographique qui permet de prouver qu'un certain calcul (tel qu'un comme le calcul d'un bloc à partir d'un ensemble de transactions) a été effectué correctement. De telles constructions existent, par ex. zk-SNARK, zk-STARK et quelques autres, et certains sont aujourd'hui activement utilisés dans les protocoles blockchain pour les paiements privés, notamment ZCash. Le principal problème de ces primitives est qu’elles sont notoirement lents à calculer. Par ex. Protocole Coda, qui utilise zk-SNARK spécifiquement pour prouver que tous les blocs du blockchain sont valides, dit en un des entretiens que cela peut prendre 30 secondes par transaction pour créer une preuve (ce nombre est probablement plus petit maintenant). Il est intéressant de noter qu’une preuve n’a pas besoin d’être calculée par une partie de confiance, puisque la preuve atteste non seulement de la validité du calcul pour lequel elle est construite, mais aussi de la validité de la preuve elle-même. Ainsi, le calcul de ces preuves peut être divisé parmi un ensemble de participants avec une redondance significativement moindre qu'elle ne le serait nécessaire d'effectuer des calculs sans confiance. Il permet également aux participants qui calculent les zk-SNARK pour qu'ils fonctionnent sur du matériel spécial sans réduire le décentralisation du système. Les défis des zk-SNARK, outre les performances, sont : 1. Dépendance à des primitives cryptographiques moins recherchées et moins éprouvées ; 2. « Déchets toxiques » — les zk-SNARK dépendent d'une configuration fiable dans laquelle un groupe des personnes effectuent des calculs puis rejettent les calculs intermédiaires. valeurs de ce calcul. Si tous les participants à la procédure sont de connivence et conservez les valeurs intermédiaires, de fausses preuves peuvent être créées ; 3. Complexité supplémentaire introduite dans la conception du système ; 4. Les zk-SNARK ne fonctionnent que pour un sous-ensemble de calculs possibles, donc un protocole avec un langage smart contract Turing-complet ne serait pas en mesure d'utiliser SNARK pour prouver la validité de la chaîne. 2.5 Disponibilité des données Le deuxième problème que nous aborderons est la disponibilité des données. Généralement les nœuds exploitant un blockchain particulier sont séparés en deux groupes : les nœuds complets, ceux qui téléchargent chaque bloc complet et valident chaque transaction, et Light Les nœuds, ceux qui téléchargent uniquement les en-têtes de bloc et utilisent les preuves Merkle pour les pièces de l’État et des transactions qui les intéressent, comme le montre la figure 11.
Figure 11 : Arbre Merkle Désormais, si une majorité de nœuds complets s'entendent, ils peuvent produire un bloc, valide ou invalide, et envoie son hash aux nœuds légers, mais ne divulgue jamais le contenu complet du bloc. Ils peuvent en bénéficier de différentes manières. Par exemple, considérons la figure 12 : Figure 12 : Problème de disponibilité des données Il y a trois blocs : le précédent, A, est produit par des validator honnêtes ; le courant, B, a validators de connivence ; et le suivant, C, sera également produit par des validator honnêtes (le blockchain est représenté dans le coin inférieur droit). Vous êtes un commerçant. Les validators du bloc actuel (B) reçu A des validator précédents, calculé un bloc dans lequel vous recevez de l'argent,et vous a envoyé un en-tête de ce bloc avec une preuve Merkle de l'état dans lequel vous avez de l'argent (ou une preuve Merkle d'une transaction valide qui envoie l'argent à vous). Confiant que la transaction est finalisée, vous fournissez le service. Cependant, les validator ne distribuent jamais l'intégralité du contenu du bloc B à n'importe qui. En tant que tel, les validator honnêtes du bloc C ne peuvent pas récupérer le bloc, et sont obligés soit de bloquer le système, soit de construire au-dessus de A, vous privant en tant que marchand d'argent. Lorsque nous appliquons le même scénario au sharding, les définitions de full et le nœud léger s'applique généralement par fragment : validators dans chaque fragment téléchargé tous les bloquer ce fragment et valider chaque transaction dans ce fragment, mais d'autres nœuds du système, y compris ceux qui capturent l'état des chaînes de fragments dans le chaîne de balises, téléchargez uniquement les en-têtes. Ainsi, les validator dans la partition sont effectivement des nœuds complets pour cette partition, tandis que les autres participants du système, y compris la chaîne de balises, fonctionnent comme des nœuds lumineux. Pour que l’approche du pêcheur dont nous avons discuté ci-dessus fonctionne, des validator honnêtes doivent pouvoir télécharger des blocs qui sont réticulés à la chaîne de balises. Si des validator malveillants ont croisé l'en-tête d'un bloc invalide (ou l'ont utilisé pour lancer une transaction cross-shard), mais n'a jamais distribué le bloc, l'honnête Les validator n'ont aucun moyen de créer un défi. Nous aborderons trois approches pour résoudre ce problème qui complètent les uns les autres. 2.5.1 Preuves de garde Le problème le plus immédiat à résoudre est de savoir si un bloc est disponible une fois il est publié. Une idée proposée est d'avoir des notaires qui alternent entre les fragments plus souvent que les validator dont le seul travail est de télécharger un bloquer et attester du fait qu’ils ont pu le télécharger. Ils peuvent être tournés plus fréquemment car ils n'ont pas besoin de télécharger l'intégralité de l'état du fragment, contrairement aux validator qui ne peuvent pas être tournés fréquemment car ils doivent télécharger l'état du fragment à chaque rotation, comme indiqué sur la figure 13. Le problème de cette approche naïve est qu’il est impossible de prouver par la suite si le notaire a pu ou non télécharger le bloc, donc un notaire peuvent choisir de toujours attester qu'ils ont pu télécharger le bloc sans même en essayant de le récupérer. Une solution à ce problème est que les notaires fournissent des preuves ou de mettre en jeu une certaine quantité de tokens attestant que le bloc était téléchargé. Une de ces solutions est discutée ici : https://ethresear.ch/t/ Obligations de garde conviviales pour l'agrégation 1 bit/2236. 2.5.2 Codes d'effacement Lorsqu'un nœud léger particulier reçoit un hash d'un bloc, pour augmenter le nombre de nœuds sûr que le bloc est disponible, il peut tenter d'en télécharger quelques-uns au hasard. morceaux du bloc. Ce n'est pas une solution complète, car à moins que les nœuds légers téléchargez collectivement l'intégralité du bloc que les producteurs de blocs malveillants peuvent choisir
Figure 13 : Les validateurs doivent télécharger l'état et ne peuvent donc pas être pivotés fréquemment pour retenir les parties du bloc qui n'ont été téléchargées par aucun nœud léger, rendant ainsi toujours le bloc indisponible. Une solution consiste à utiliser une construction appelée Erasure Codes pour permettre pour récupérer le bloc complet même si seule une partie du bloc est disponible, comme indiqué sur la figure 14. Figure 14 : Merkle tree construit sur des données codées à effacement Polkadot et Ethereum Serenity ont tous deux des conceptions autour de cette idée qui fournir un moyen aux nœuds légers d'être raisonnablement sûrs que les blocs sont disponibles. L’approche Ethereum Sérénité a une description détaillée dans [2].2.5.3 L'approche de Polkadot en matière de disponibilité des données Dans Polkadot, comme dans la plupart des solutions fragmentées, chaque fragment (appelé parachain) capture ses blocs sur la chaîne de balises (appelée chaîne de relais). Disons qu'il y a 2f + 1 validators sur la chaîne de relais. Les producteurs de blocs de parachain, appelés les assembleurs, une fois le bloc parachain produit, calculent une version codée par effacement du bloc qui se compose de 2f +1 parties de telle sorte que toutes les parties f soient suffisantes pour reconstruire le bloc. Ils distribuent ensuite une part à chaque validator sur le chaîne de relais. Une chaîne de relais particulière validator ne signerait que sur une chaîne de relais bloquer s'ils ont leur part pour chaque bloc de parachain qui est instantané sur tel bloc de chaîne de relais. Ainsi, si un bloc de chaîne relais a des signatures de 2f + 1 validators, et tant que pas plus de f d'entre eux ont violé le protocole, chacun le bloc de parachain peut être reconstruit en récupérant les pièces des validators qui suivent le protocole. Voir la figure 15. Figure 15 : Disponibilité des données de Polkadot 2.5.4 Disponibilité des données à long terme Notez que toutes les approches évoquées ci-dessus attestent seulement du fait qu'un bloc a été publié et est disponible dès maintenant. Les blocs peuvent devenir indisponibles ultérieurement pour diverses raisons : nœuds mis hors ligne, nœuds effaçant intentionnellement l'historique. données, et autres. Un livre blanc digne de mention qui aborde ce problème est Polyshard [3], qui utilise des codes d'effacement pour rendre les blocs disponibles sur plusieurs fragments, même si plusieurs les fragments perdent complètement leurs données. Malheureusement, leur approche spécifique nécessite tous les fragments pour télécharger des blocs de tous les autres fragments, ce qui est prohibitif cher. La disponibilité à long terme n'est pas un problème aussi urgent : puisqu'aucun participant dans le système devrait être capable de valider toutes les chaînes dans tous les
fragments, la sécurité du protocole fragmenté doit être conçue de manière à manière dont le système est sécurisé même si certains anciens blocs de certains fragments deviennent totalement indisponible.
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.
Nightshade
3.1 Des chaînes de fragments aux fragments de fragments Le modèle de partage avec des chaînes de fragments et une chaîne de balises est très puissant mais présente certaines complexités. En particulier, la règle de choix de fork doit être exécutée dans chaque chaîne séparément, la règle de choix des fourches dans les chaînes de fragments et la balise La chaîne doit être construite différemment et testée séparément. Dans Nightshade, nous modélisons le système comme un seul blockchain, dans lequel chaque Le bloc contient logiquement toutes les transactions pour tous les fragments et modifie le état complet de tous les fragments. Mais physiquement, aucun participant ne télécharge le état complet ou le bloc logique complet. Au lieu de cela, chaque participant du réseau uniquement maintient l'état qui correspond aux fragments pour lesquels ils valident les transactions, et la liste de toutes les transactions du bloc est divisée en transactions physiques morceaux, un morceau par fragment. Dans des conditions idéales, chaque bloc contient exactement un morceau par fragment et par bloc, ce qui correspond à peu près au modèle avec des chaînes de fragments dans lequel le les chaînes de fragments produisent des blocs à la même vitesse que la chaîne de balise. Cependant, en raison des retards du réseau, certains morceaux peuvent manquer, donc en pratique, chaque bloc contient un ou zéro fragment par fragment. Voir la section 3.3 pour plus de détails sur la façon des blocs sont produits. Figure 16 : Un modèle avec des chaînes d'éclats à gauche et avec une chaîne ayant blocs divisés en morceaux à droite
3.2 Consensus Les deux approches dominantes du consensus dans les blockchain aujourd'hui sont la chaîne la plus longue (ou la plus lourde), dans laquelle la chaîne qui a le plus de travail ou d'enjeux utilisé pour le construire est considéré comme canonique, et BFT, dans lequel pour chaque bloc certains un ensemble de validator parviennent à un consensus BFT. Dans les protocoles proposés récemment, cette dernière approche est plus dominante, car il fournit une finalité immédiate, alors que dans la chaîne la plus longue, davantage de blocs ont besoin à construire au sommet du bloc pour assurer la finalité. Souvent pour un but significatif sécurité, le temps nécessaire pour construire un nombre suffisant de blocs prend le temps ordre des heures. L'utilisation du consensus BFT sur chaque bloc présente également des inconvénients, tels que : 1. Le consensus BFT implique une quantité considérable de communication. Tandis que les avancées récentes permettent d’atteindre le consensus dans un temps linéaire en nombre des participants (voir par exemple [4]), la surcharge par bloc est toujours perceptible ; 2. Il n'est pas possible que tous les participants du réseau participent au BFT consensus par bloc, donc généralement seul un sous-ensemble de participants échantillonné au hasard atteint le consensus. Un ensemble échantillonné aléatoirement peut, en principe, être corrompu de manière adaptative, et un fork peut en théorie être créé. Le système l'un ou l'autre doit être modélisé pour être prêt à un tel événement, et donc toujours avoir une règle de choix de fourchette en plus du consensus BFT, ou être conçu pour fermer dans un tel événement. Il convient de mentionner que certains modèles, tels que Algorand [5], réduisent considérablement la probabilité de corruption adaptative. 3. Plus important encore, le système se bloque si 1 3 ou plus de tous les participants sont hors ligne. Ainsi, tout problème de réseau temporaire ou division du réseau peut complètement bloquer le système. Idéalement, le système doit pouvoir continuer à fonctionner tant qu’au moins la moitié des participants sont en ligne (le plus lourd les protocoles basés sur des chaînes continuent de fonctionner même si moins de la moitié des participants sont en ligne, mais l'opportunité de cette propriété est plus discutable au sein de la communauté). Un modèle hybride dans lequel le consensus utilisé est en quelque sorte le plus lourd chaîne, mais certains blocs sont périodiquement finalisés à l'aide d'un gadget de finalité BFT pour conserver les avantages des deux modèles. De tels gadgets BFT finalités sont Casper FFG [6] utilisé dans Ethereum 2.0 8, Casper CBC (voir https://vitalik. ca/general/2018/12/05/cbc_casper.html) et GRANDPA (voir https:// medium.com/polkadot-network/d08a24a021b5) utilisé dans Polkadot. Nightshade utilise le consensus de chaîne le plus lourd. Plus précisément lorsqu'un bloc producteur produit un bloc (voir section 3.3), il peut recueillir les signatures de d'autres producteurs de blocs et des validator attestant du bloc précédent. Voir la rubrique 3.8 pour plus de détails sur la manière dont un si grand nombre de signatures est regroupé. Le poids 8Voir également la séance sur tableau blanc avec Justin Drake pour un aperçu approfondi de Casper FFG, et comment il est intégré au consensus de la chaîne la plus lourde GHOST ici : https://www. youtube.com/watch?v=S262StTwkmod'un bloc est alors la mise cumulée de tous les signataires dont les signatures sont inclus dans le bloc. Le poids d'une chaîne est la somme des poids des blocs. En plus du consensus en chaîne le plus lourd, nous utilisons un gadget de finalité qui utilise les attestations pour finaliser les blocs. Pour réduire la complexité du système, nous utilisons un gadget de finalité qui n’influence en rien la règle de choix du fork, et à la place, il n'introduit que des conditions de réduction supplémentaires, telles qu'une fois qu'un bloc est finalisé par le gadget de finalité, un fork est impossible à moins qu'un très grand pourcentage de la mise totale est réduite. Casper CBC est un gadget tellement définitif, et nous modèle actuellement avec Casper CBC à l’esprit. Nous travaillons également sur un protocole BFT distinct appelé TxFlow. Au moment de en écrivant ce document, il n'est pas clair si TxFlow sera utilisé à la place de Casper Radio-Canada. On constate cependant que le choix de la finalité du gadget est largement orthogonal au reste du design. 3.3 Production de blocs Dans Nightshade, il y a deux rôles : les producteurs de blocs et les validator. À tout moment point où le système contient w producteurs de blocs, w = 100 dans nos modèles, et wv validators, dans notre modèle v = 100, wv = 10 000. Le système est une preuve de participation, ce qui signifie que les producteurs de blocs et les validator ont un certain nombre de monnaie (appelée « tokens ») verrouillée pendant une durée dépassant largement la durée le temps qu'ils passent à accomplir leurs tâches de construction et de validation de la chaîne. Comme pour tous les systèmes Proof of Stake, tous les producteurs de blocs w et non tous les wv validator sont des entités différentes, puisque cela ne peut pas être appliqué. Chacun des producteurs de blocs w et des wv validators, cependant, ont un enjeu. Le système contient n fragments, n = 1000 dans notre modèle. Comme mentionné dans section 3.1, dans Nightshade, il n'y a pas de chaînes de fragments, à la place, tous les producteurs de blocs et validator construisent un seul blockchain, que nous appelons le chaîne principale. L'état de la chaîne principale est divisé en n fragments, et chaque bloc producteur et validator à tout moment n'ont téléchargé localement qu'un sous-ensemble de l'état qui correspond à un sous-ensemble de fragments, et uniquement le processus et valider les transactions qui affectent ces parties de l’État. Pour devenir producteur de blocs, un participant du réseau verrouille de gros montant de tokens (une mise). La maintenance du réseau se fait par époques, où une époque est une période de temps de l’ordre des jours. Les participants avec les enjeux les plus importants au début d'une époque particulière sont le bloc producteurs pour cette époque. Chaque producteur de blocs est affecté à des fragments sw (par exemple sw = 40, ce qui ferait sww/n = 4 producteurs de blocs par fragment). Le bloc le producteur télécharge l'état du fragment auquel il est affecté avant l'époque commence et, tout au long de l'époque, collecte les transactions qui affectent ce fragment, et les applique à l'État. Pour chaque bloc b de la chaîne principale et pour chaque fragment s, il y a l'un des assigné des producteurs de blocs à s qui est responsable de produire la partie de b liée au tesson. La partie de b liée au fragment s est appelée un morceau et contient le liste des transactions pour le fragment à inclure dans b, ainsi que le merkleracine de l’état résultant. b ne contiendra finalement qu'un tout petit en-tête de le chunk, à savoir la racine merkle de toutes les transactions appliquées (voir section 3.7.1 pour les détails exacts), et la racine Merkle de l’état final. Dans le reste du document, nous faisons souvent référence au producteur de blocs. qui est chargé de produire un morceau à un moment donné pour un fragment particulier en tant que producteur de morceaux. Le producteur de morceaux est toujours l'un des producteurs de blocs. Les producteurs de blocs et les producteurs de morceaux font tourner chaque bloc en fonction à un horaire fixe. Les producteurs de blocs ont une commande et produisent à plusieurs reprises blocs dans cet ordre. Par ex. s'il y a 100 producteurs de blocs, le premier bloc les producteurs sont responsables de la production des blocs 1, 101, 201 etc, le second est responsable de la production 2, 102, 202 etc.). Puisque la production de morceaux, contrairement à la production de blocs, nécessite le maintien l'état, et pour chaque fragment, seuls les producteurs de blocs sww/n maintiennent l'état par fragment, en conséquence, seuls les producteurs de blocs sww/n tournent pour créer morceaux. Par ex. avec les constantes ci-dessus avec quatre producteurs de blocs affectés à chaque fragment, chaque producteur de blocs créera des morceaux une fois tous les quatre blocs. 3.4 Assurer la disponibilité des données Pour garantir la disponibilité des données, nous utilisons une approche similaire à celle de Polkadot décrit à la section 2.5.3. Une fois qu'un producteur de blocs produit un morceau, il crée une version codée par effacement avec un code de bloc optimal (w, ⌊w/6 + 1⌋) du morceau. Ils envoient ensuite un morceau du morceau codé à effacement (nous appelons ces morceaux morceaux, ou juste des pièces) à chaque producteur de blocs. Nous calculons un arbre Merkle qui contient toutes les parties comme les feuilles, et le l'en-tête de chaque morceau contient la racine merkle de cet arbre. Les pièces sont envoyées aux validator via des messages onepart. Chacun de ces messages contient l'en-tête du bloc, l'ordinal de la partie et le contenu de la partie. Le Le message contient également la signature du producteur du bloc qui a produit le chunk et le chemin merkle pour prouver que la pièce correspond à l'en-tête et est produit par le producteur de blocs approprié. Une fois qu'un producteur de blocs reçoit un bloc de chaîne principale, il vérifie d'abord s'il avoir des messages en une partie pour chaque morceau inclus dans le bloc. Sinon, le bloc n'est pas traité tant que les messages en une partie manquants n'ont pas été récupérés. Une fois tous les messages en une partie reçus, le producteur de blocs récupère le parties restantes des pairs et reconstruit les morceaux pour lesquels ils détiennent l'État. Le producteur de blocs ne traite pas un bloc de la chaîne principale si pour au moins un morceau inclus dans le bloc, ils n'ont pas le message en une partie correspondant, ou si pour au moins un fragment pour lequel ils maintiennent l'état, ils ne peuvent pas reconstruire le morceau entier. Pour qu'un morceau particulier soit disponible, il suffit que ⌊w/6⌋+1 du bloc les producteurs ont leurs pièces et les servent. Ainsi, aussi longtemps que le nombre de les acteurs malveillants ne dépassent pas ⌊w/3⌋aucune chaîne comportant plus de la moitié du bloc les producteurs qui le construisent peuvent avoir des morceaux indisponibles.Figure 17 : Chaque bloc contient un ou zéro fragment par fragment, et chaque fragment est codé par effacement. Chaque partie du morceau codé d'effacement est envoyée à un producteur de blocs via un message spécial en une seule partie 3.4.1 Faire face aux producteurs de blocs paresseux Si un producteur de blocs possède un bloc pour lequel un message en une seule partie manque, il pourrait choisir de continuer à le signer, car si le bloc finit par être en chaîne, il maximisera la récompense pour le producteur de blocs. Il n'y a aucun risque pour le blocage producteur puisqu’il est impossible de prouver par la suite que le producteur du bloc n’avait pas le message en une partie. Pour résoudre ce problème, nous faisons en sorte que chaque morceau soit producteur lors de la création du morceau. choisissez une couleur (rouge ou bleu) pour chaque partie du futur morceau encodé, et stockez le masque de bits de la couleur attribuée dans le bloc avant qu'il ne soit codé. Chaque partie Le message contient alors la couleur attribuée à la pièce, et la couleur est utilisée lorsque calculer la racine merkle des parties codées. Si le producteur de morceaux s'écarte du protocole, cela peut être facilement prouvé, puisque soit la racine merkle ne sera pas correspondent aux messages en une partie, ou aux couleurs des messages en une partie qui correspondre à la racine merkle ne correspondra pas au masque dans le morceau. Lorsqu'un producteur de blocs signe sur un bloc, il inclut un masque de bits de tous les pièces rouges qu'ils ont reçues pour les morceaux inclus dans le bloc. Publier un un masque de bits incorrect est un comportement slashable. Si un producteur de blocs n'a pas reçu de message en une seule partie, ils n'ont aucun moyen de connaître la couleur du message, et ils ont donc 50% de chances d'être sabrés s'ils tentent de signer aveuglément le bloquer. 3.5 Demande de transition d'état Les producteurs de fragments choisissent uniquement les transactions à inclure dans le fragment, mais n'appliquez pas la transition d'état lorsqu'ils produisent un morceau. En conséquence,
l'en-tête du bloc contient la racine merkle de l'état merkelisé comme avant les transactions du bloc sont appliquées. Les transactions ne sont appliquées que lorsqu'un bloc complet incluant le morceau est traité. Un participant ne traite un blocage que si 1. Le bloc précédent a été reçu et traité ; 2. Pour chaque morceau, le participant ne conserve pas l'état car il l'a vu le message en une partie ; 3. Pour chaque morceau, le participant conserve l'état car il a le morceau complet. Une fois le bloc traité, pour chaque fragment pour lequel le participant maintient l'état pendant, ils appliquent les transactions et calculent le nouvel état dès que les transactions sont appliquées, après quoi elles sont prêtes à produire les morceaux du bloc suivant, s'ils sont affectés à un fragment, car ils ont la racine merkle du nouvel État merkelisé. 3.6 Transactions et reçus entre fragments Si une transaction doit affecter plusieurs fragments, elle doit être consécutivement exécuté dans chaque fragment séparément. La transaction complète est envoyée au premier fragment affecté, et une fois que la transaction est incluse dans le bloc pour ce fragment, et est appliqué une fois que le morceau est inclus dans un bloc, il génère ce qu'on appelle un reçu transaction, qui est acheminée vers le fragment suivant dans lequel la transaction doit être exécuté. Si plusieurs étapes sont nécessaires, l'exécution de la transaction de réception génère une nouvelle transaction de réception et ainsi de suite. 3.6.1 Durée de vie de la transaction de réception Il est souhaitable que la transaction de réception soit appliquée dans le bloc qui suit immédiatement le bloc dans lequel elle a été générée. La transaction de réception est uniquement généré après que le bloc précédent a été reçu et appliqué par les producteurs de blocs qui maintiennent le fragment d'origine et doit être connu au moment où le le morceau du bloc suivant est produit par les producteurs de blocs de la destination éclat. Ainsi, le reçu doit être communiqué du fragment source au fragment de destination dans le court laps de temps entre ces deux événements. Soit A le dernier bloc produit contenant une transaction t générant un reçu r. Soit B le prochain bloc produit (c'est-à-dire un bloc qui a A comme son bloc précédent) que nous voulons contenir r. Que ce soit dans le fragment a et r dans le fragment b. La durée de vie du reçu, également représentée sur la figure 18, est la suivante : Produire et conserver les reçus. Le CPA du producteur de morceaux pour le fragment a reçoit le bloc A, applique la transaction t et génère le reçu r. cpa stocke ensuite tous ces reçus produits dans son stockage persistant interne indexé par l'identifiant du fragment source.Distribution des reçus. Une fois que cpa est prêt à produire le morceau pour fragment a pour le bloc B, ils récupèrent tous les reçus générés en appliquant les transactions du bloc A pour le fragment a et les incluent dans le fragment pour shrad a dans le bloc B. Une fois ce morceau généré, cpa produit son code d'effacement version et tous les messages onepart correspondants. cpa sait quels blocs les producteurs maintiennent l'état complet pour quels fragments. Pour un producteur de blocs particulier bp cpa inclut les recettes résultant de l'application des transactions dans le bloc A pour le fragment a qui a l'un des fragments qui intéressent bp comme destination dans le message en une partie lorsqu'ils ont distribué le morceau pour le fragment a dans le bloc B (voir la figure 17, qui montre les reçus inclus dans le message en une partie). Réception des reçus. N'oubliez pas que les participants (les producteurs de blocs et les validator) ne traitent pas les blocs tant qu'ils n'ont pas reçu de messages en une seule partie. pour chaque morceau inclus dans le bloc. Ainsi, au moment où un participant particulier applique le bloc B, il dispose de tous les messages en une seule partie qui correspondent à morceaux en B, et ils ont donc tous les reçus entrants qui contiennent les fragments le participant conserve l'état comme destination. Lors de l'application du transition d'état pour un fragment particulier, le participant applique à la fois les reçus qu'ils ont collectés pour le fragment dans les messages en une seule partie, ainsi que tous les transactions incluses dans le morceau lui-même. Figure 18 : La durée de vie d'une transaction de réception 3.6.2 Gérer trop de reçus Il est possible que le nombre de reçus ciblant une partition particulière dans un un bloc particulier est trop volumineux pour être traité. Par exemple, considérons la figure 19, dans dont chaque transaction dans chaque fragment génère un reçu qui cible le fragment 1. Au bloc suivant, le nombre de reçus que le fragment 1 doit traiter est égal à comparable à la charge que tous les fragments combinés ont traitée lors de la manipulation le bloc précédent.
Figure 19 : Si tous les reçus ciblent la même partition, celle-ci n'aura peut-être pas la capacité de les traiter Pour résoudre ce problème, nous utilisons une technique similaire à celle utilisée dans QuarkChain 9. Plus précisément, pour chaque fragment, le dernier bloc B et le dernier fragment à l'intérieur de celui-ci. le bloc à partir duquel les recettes ont été appliquées est enregistré. Lorsque le nouveau fragment est créés, les reçus sont appliqués dans l'ordre en premier à partir des fragments restants en B, puis dans les blocs qui suivent B, jusqu'à ce que le nouveau morceau soit plein. Sous la normale Dans des circonstances avec une charge équilibrée, cela donnera généralement lieu à toutes les recettes étant appliqué (et donc le dernier fragment du dernier bloc sera enregistré pour chaque morceau), mais pendant les périodes où la charge n'est pas équilibrée, et un particulier Shard reçoit un nombre disproportionné de reçus, cette technique leur permet de être traitées en respectant les limites du nombre de transactions incluses. Notez que si une telle charge déséquilibrée persiste pendant une longue période, le délai entre la création du reçu jusqu'à ce que l'application puisse continuer à croître indéfiniment. Un La meilleure façon de résoudre ce problème est d'abandonner toute transaction qui crée un reçu ciblant un fragment qui a un délai de traitement qui dépasse une certaine constante (par exemple, une époque). Considérons la figure 20. Par le bloc B, le fragment 4 ne peut pas traiter tous les reçus, il ne traite donc que l'origine des reçus jusqu'au fragment 3 dans le bloc A, et l'enregistre. Dans le bloc C, les reçus jusqu'au fragment 5 dans le bloc B sont inclus, et puis par le bloc D, le fragment rattrape son retard, traitant tous les reçus restants dans le bloc B et toutes les recettes du bloc C. 3.7 Validation des fragments Un morceau produit pour une partition particulière (ou un bloc de partitions produit pour une chaîne de partitions particulière dans le modèle avec chaînes de partitions) ne peut être validé que par le 9Voir l'épisode du tableau blanc avec QuarkChain ici : https://www.youtube.com/watch? v=opEtG6NM4x4, dans lequel l'approche des transactions entre fragments est discutée, entre autres des chosesFigure 20 : Traitement des reçus en retard participants qui maintiennent l’État. Ils peuvent être des producteurs de blocs, des validator, ou simplement des témoins externes qui ont téléchargé l'état et validé le fragment dans dans lesquels ils stockent des actifs. Dans ce document, nous supposons que la majorité des participants ne peuvent pas stocker l’État pour une grande partie des fragments. Il convient cependant de mentionner qu'il existe des blockchain fragmentés conçus avec l'hypothèse que la plupart des participants ont la capacité de stocker l'état et de valider la plupart des les fragments, tels que QuarkChain. Puisque seule une fraction des participants dispose de l’état nécessaire pour valider le fragment morceaux, il est possible de corrompre de manière adaptative uniquement les participants qui ont le état et appliquez une transition d’état non valide. Plusieurs conceptions de partitionnement ont été proposées pour échantillonner les validator à intervalles de quelques jours, et dans la journée, tout bloc de la chaîne de fragments qui contient plus de 2/3 des signatures des validator attribués à ce fragment est immédiatement prise en compte finale. Avec une telle approche, un adversaire adaptatif n’a qu’à corrompre 2n/3+1 des validators dans une chaîne de fragments pour appliquer une transition d'état non valide, ce qui, bien qu'il soit probablement difficile à réaliser, le niveau de sécurité n'est-il pas suffisant pour un public blockchain. Comme indiqué dans la section 2.3, l'approche courante consiste à accorder un certain laps de temps après la création d'un bloc pour tout participant ayant un état (que ce soit c'est un producteur de blocs, un validator ou un observateur externe) pour contester sa validité. Ces participants sont appelés pêcheurs. Pour qu'un pêcheur puisse contester un blocage invalide, il faut s'assurer qu'un tel blocage est disponible pour eux. La disponibilité des données dans Nightshade est discutée à la section 3.4. Dans Nightshade, une fois qu'un bloc est produit, les morceaux n'étaient pas validés par n'importe qui sauf le véritable producteur de morceaux. En particulier, le producteur de blocs qui a suggéré que le bloc n'avait naturellement pas l'état pour la plupart des fragments, etn'a pas pu valider les morceaux. Lorsque le bloc suivant est produit, il contient les attestations (voir section 3.2) de plusieurs producteurs de blocs et validator, mais comme la majorité des producteurs de blocs et des validator ne maintiennent pas l'état pour la plupart des fragments également, un bloc avec un seul morceau invalide collectera significativement plus de la moitié des attestations et continuera à être sur le plus lourd. chaîne. Pour résoudre ce problème, nous autorisons tout participant qui maintient l'état de un fragment pour soumettre un défi en chaîne pour tout morceau non valide produit dans ce fragment éclat. 3.7.1 Défi de validité d’état Une fois qu'un participant détecte qu'un morceau particulier n'est pas valide, il doit fournir une preuve que ce morceau est invalide. Étant donné que la majorité des participants au réseau ne conservent pas l'état du fragment dans lequel se trouve le fragment invalide, produite, la preuve doit avoir suffisamment d’informations pour confirmer que le bloc est invalide sans avoir l'état. Nous fixons une limite Ls de la quantité d'état (en octets) qu'une seule transaction peuvent cumulativement lire ou écrire. Toute transaction qui touche plus de Ls l’état est considéré comme invalide. Rappelez-vous de la section 3.5 que le morceau dans un bloc B particulier ne contient que les transactions à appliquer, mais pas la nouvelle racine d'état. La racine d'état incluse dans le bloc du bloc B est l'état racine avant d'appliquer de telles transactions, mais après avoir appliqué les transactions de le dernier morceau du même fragment avant le bloc B. Un acteur malveillant qui souhaite appliquer une transition d'état invalide inclurait une racine d'état incorrecte dans le bloc B qui ne correspond pas à la racine d’état résultant de l’application les transactions du bloc précédent. Nous étendons les informations qu'un producteur de chunk inclut dans le chunk. Au lieu d'inclure simplement l'état après avoir appliqué toutes les transactions, il inclut une racine d'état après avoir appliqué chaque ensemble contigu de transactions qui lire et écrire collectivement Ls octets d’état. Avec ces informations pour le pêcheur pour créer un défi selon lequel une transition d'état est mal appliquée est suffisant pour trouver la première racine d’état non valide, et inclure seulement Ls octets de état qui sont affectés par les transactions entre la dernière racine d’état (qui était valide) et la racine de l'état actuel avec les preuves Merkle. Alors tout participant peut valider les transactions dans le segment et confirmer que le fragment est invalide. De même, si le producteur du bloc tentait d'inclure des transactions qui lisent et écrire plus de Ls octets d'état, pour le défi il suffit d'inclure les premiers Ls octets qu'il touche avec les preuves merkle, ce qui suffira à appliquer les transactions et confirmer qu'il y a un moment où une tentative de la lecture ou l'écriture de contenu au-delà de Ls octets est effectuée.
3.7.2 Pêcheurs et transactions rapides entre fragments Comme indiqué dans la section 2.3, une fois que nous supposons que les fragments (ou fragments) blocs dans le modèle avec des chaînes de fragments) peuvent être invalides et introduire un défi période, cela affecte négativement la finalité, et donc la communication entre fragments. Dans en particulier, le fragment de destination de toute transaction entre fragments ne peut pas être certain le morceau ou le bloc de fragments d'origine est définitif jusqu'à la fin de la période de défi (voir figure 21). Figure 21 : Attendre la période de contestation avant d'appliquer un récépissé La façon de résoudre ce problème de manière à ce que les transactions entre fragments soient effectuées Il est instantané que le fragment de destination n'attende pas la période de défi après la publication de la transaction du fragment source, et appliquez la transaction de réception immédiatement, puis restaurez le fragment de destination avec la source fragment si plus tard le morceau ou le bloc d'origine s'est avéré invalide (voir la figure 22). Cela s'applique très naturellement au design Nightshade dans lequel le fragment les chaînes ne sont pas indépendantes, mais les fragments de fragments sont tous publiés ensemble dans le même bloc de chaîne principal. Si un morceau s'avère invalide, le le bloc entier avec ce morceau est considéré comme invalide, et tous les blocs construits sur en haut. Voir la figure 23. Les deux approches ci-dessus fournissent une atomicité en supposant que le défi la période est suffisamment longue. Nous utilisons cette dernière approche car la fourniture de transactions cross-shard rapides dans des circonstances normales dépasse les inconvénients de la partition de destination est annulée en raison d'une transition d'état non valide dans l'un des les fragments sources, ce qui est un événement extrêmement rare. 3.7.3 Masquage des validator L’existence de défis réduit déjà considérablement la probabilité de corruption adaptative, puisque pour finaliser un morceau avec un post de transition d'état invalideFigure 22 : Appliquer immédiatement les reçus et annuler la destination chaîne si la chaîne source avait un bloc invalide Figure 23 : Défi pêcheur à Nightshade la période de défi dont l'adversaire adaptatif a besoin pour corrompre tous les participants qui maintiennent l'état du fragment, y compris tous les validator. L'estimation de la probabilité d'un tel événement est extrêmement complexe, car aucun le fragment blockchain est actif depuis suffisamment longtemps pour qu'une telle attaque puisse être tentée. Nous affirmons que la probabilité, bien qu’extrêmement faible, est néanmoins suffisamment important pour un système censé exécuter plusieurs millions de transactions et diriger des opérations financières à l’échelle mondiale. Il y a deux raisons principales à cette croyance : 1. La plupart des validator des chaînes Proof-of-Stake et des mineurs du
Les chaînes de preuve de travail sont principalement motivées par les avantages financiers. Si un adversaire adaptatif leur offre plus d’argent que le rendement attendu de fonctionner honnêtement, il est raisonnable de s'attendre à ce que de nombreux validator acceptera l'offre. 2. De nombreuses entités effectuent la validation des chaînes de preuve de participation de manière professionnelle, et on s'attend à ce qu'un pourcentage important des parts dans n'importe quelle chaîne soit de ces entités. Le nombre de ces entités est suffisamment petit pour une adversaire adaptatif pour apprendre à connaître la plupart d'entre eux personnellement et avoir une bonne compréhension de leur penchant à la corruption. Nous allons encore plus loin en réduisant la probabilité de corruption adaptative en masquant quels validator sont attribués à quelle partition. L'idée est un peu similaire à la façon dont Algorand [5] dissimule les validator. Il est essentiel de noter que même si les validator sont cachés, comme dans Algorand ou comme décrit ci-dessous, la corruption adaptative est toujours en théorie possible. Tandis que l'adversaire adaptatif ne connaît pas les participants qui vont créer ou valider un bloc ou un morceau, les participants eux-mêmes savent qu'ils joueront une telle tâche et en avoir une preuve cryptographique. Ainsi, l'adversaire peut diffuser leur intention de corrompre et payer tout participant qui fournira une telle preuve cryptographique. Notons cependant que puisque l’adversaire ne le fait pas connaissent les validator attribués au fragment qu'ils souhaitent corrompre, ils n'ont pas d'autre choix que de diffuser leur intention de corrompre un fragment particulier à la communauté entière. À ce stade, il est économiquement bénéfique pour tout honnête participant à lancer un nœud complet qui valide ce fragment, car il y a un niveau élevé chance qu'un bloc invalide apparaisse dans ce fragment, ce qui est une opportunité de créez un défi et collectez la récompense associée. Pour ne pas révéler les validator attribués à un fragment particulier, nous le faisons ce qui suit (voir figure 24) : Utiliser VRF pour obtenir la mission. Au début de chaque époque chacun validator utilise un VRF pour obtenir un masque de bits des fragments auxquels validator est affecté. Le masque de bits de chaque validator aura des bits Sw (voir la section 3.3 pour la définition de Sw). Le validator récupère ensuite l'état des fragments correspondants, et pendant l'époque pour chaque bloc reçu valide les morceaux qui correspondent aux fragments auxquels le validator est affecté. Connectez-vous sur des blocs plutôt que sur des morceaux. Étant donné que l'affectation des fragments est masquée, le validator ne peut pas signer sur les fragments. Au lieu de cela, il signe toujours sur l'ensemble bloquer, ne révélant ainsi pas quels fragments il valide. Plus précisément, lorsque le validator reçoit un bloc et valide tous les morceaux, soit il crée un message qui atteste que tous les morceaux de toutes les partitions auxquelles le validator est attribué sont valide (sans indiquer de quelque manière que ce soit quels sont ces fragments), ou un message qui contient une preuve d'une transition d'état invalide si un morceau est invalide. Voir le section 3.8 pour plus de détails sur la façon dont ces messages sont regroupés, section 3.7.4 pour les détails sur la façon d'empêcher les validator de s'appuyer sur les messages de autres validator, et la section 3.7.5 pour plus de détails sur la façon de récompenser et de punir validators si un défi de transition d'état invalide réussi se produit réellement.Figure 24 : Dissimulation des validator dans Nightshade 3.7.4 Commit-Révéler L'un des problèmes courants avec les validator est qu'un validator peut ignorer le téléchargement de l'état et valider réellement les morceaux et les blocs, et à la place observez le réseau, voyez ce que les autres validator soumettent et répétez leur messages. Un validator qui suit une telle stratégie n'apporte aucun supplément sécurité du réseau, mais collecte des récompenses. Une solution courante à ce problème consiste pour chaque validator à fournir une preuve qu'ils ont effectivement validé le blocage, par exemple en fournissant une trace unique d'appliquer la transition d'état, mais de telles preuves augmentent considérablement le coût de validation. Figure 25 : Révélation de validation
Au lieu de cela, nous faisons en sorte que les validator s'engagent d'abord sur le résultat de la validation (soit le message qui atteste de la validité des chunks, ou la preuve d'un invalide transition d'état), attendez une certaine période, et révélez ensuite seulement le résultat réel de la validation, comme le montre la figure 25. La période de validation ne croise pas la période de validation. la période de révélation, et donc un validator paresseux ne peut pas copier des validator honnêtes. De plus, si un validator malhonnête s'engageait dans un message attestant du validité des morceaux attribués, et au moins un morceau était invalide, une fois qu'il est montré que le morceau n'est pas valide, le validator ne peut pas éviter la coupure, car, comme nous le montrons dans la section 3.7.5, le seul moyen de ne pas se faire tailler dans une telle situation est de présenter un message contenant une preuve de la transition d'état invalide qui correspond au commit. 3.7.5 Relever les défis Comme indiqué ci-dessus, une fois qu'un validator reçoit un bloc avec un morceau invalide, ils préparent d’abord une preuve de la transition d’état invalide (voir section 3.7.1), puis s'engager sur une telle preuve (voir 3.7.4), et après un certain temps révéler le défi. Une fois le défi révélé inclus dans un bloc, voici ce qui se passe : 1. Toutes les transitions d'état survenues à partir du bloc contenant le morceau invalide jusqu'à ce que le bloc dans lequel le défi révélé est inclus soit obtenu nul. L'état avant le bloc qui inclut le défi révélé est considéré comme étant le même que l'état avant le bloc qui contenait le morceau invalide. 2. Dans un certain laps de temps, chaque validator doit révéler son masque de bits des fragments qu'ils valident. Puisque le masque de bits est créé via un VRF, si ils ont été affectés au fragment qui avait la transition d'état invalide, ils ne peut éviter de le révéler. Tout validator qui ne parvient pas à révéler le masque de bits est supposé être affecté au fragment. 3. Chaque validator qui, après cette période, est affecté au fragment, qui s'est engagé sur un résultat de validation pour le bloc contenant le morceau invalide et qui n'a pas révélé la preuve d'une transition d'état invalide qui correspond à leur commit est réduit. 4. Chaque validator reçoit une nouvelle affectation de fragments et une nouvelle époque est programmée pour démarrer après un certain temps suffisant pour que tous les validator téléchargent le état, comme le montre la figure 26. Notez qu'à partir du moment où les validator révèlent les fragments qui leur sont attribués jusqu'au début de la nouvelle époque, la sécurité du système est réduite puisque le L'affectation des fragments est révélée. Les participants du réseau doivent le conserver à l'esprit lors de l'utilisation du réseau pendant cette période. 3.8 Agrégation de signatures Pour qu'un système comportant des centaines de fragments fonctionne en toute sécurité, nous souhaitons disposer d'un commande de 10 000 validator ou plus. Comme indiqué dans la section 3.7, nous voulons que chaqueFigure 26 : Relever le défi validator pour publier un commit sur un certain message et une signature en moyenne une fois par bloc. Même si les messages de validation étaient les mêmes, l'agrégation d'un tel La signature BLS et sa validation auraient été d'un coût prohibitif. Mais naturellement, les messages de validation et de révélation ne sont pas les mêmes d'un validator à l'autre, et nous avons donc besoin d'un moyen de regrouper ces messages et les signatures dans un manière qui permet une validation rapide plus tard. L’approche spécifique que nous utilisons est la suivante : Les validateurs rejoignent les producteurs de blocs. Les producteurs de blocs sont connus quelque temps avant le début de l'époque, car ils ont besoin d'un certain temps pour télécharger le état avant le début de l'époque, et contrairement aux validator, les producteurs de blocs sont pas caché. Chaque producteur de blocs dispose de v validator emplacements. Les validateurs soumettent propositions hors chaîne aux producteurs de blocs pour être inclus comme l'un de leurs v validators. Si un producteur de blocs souhaite inclure un validator, il soumet un transaction qui contient la demande initiale hors chaîne du validator et le signature du producteur de blocs qui permet au validator de rejoindre le producteur de blocs. Notez que les validator attribués aux producteurs de blocs ne correspondent pas nécessairement valider les mêmes fragments pour lesquels le producteur de blocs produit des morceaux. Si un validator a demandé à rejoindre plusieurs producteurs de blocs, seule la transaction de le premier producteur de blocs réussira. Les producteurs de blocs collectent les commits. Le producteur de blocs collecte constamment les messages de validation et de révélation des validator. Une fois qu'un certain nombre de ces messages sont accumulés, le producteur de blocs calcule un merkle arbre de ces messages, et envoie à chaque validator la racine merkle et le chemin merkle vers leur message. Le validator valide le chemin et signalise la racine de merkle. Le producteur de blocs accumule ensuite une signature BLS sur le racine merkle des validators, et publie uniquement la racine merkle et le signature accumulée. Le producteur de blocs signe également la validité du multisignature utilisant une signature ECDSA bon marché. Si la multisignature ne fonctionne pas correspond à la racine merkle soumise ou au masque de bits des validators participants, c'est un comportement slashable. Lors de la synchronisation de la chaîne, un participant peut choisir de valider toutes les signatures BLS des validator (ce qui est extrêmement coûteux car cela implique d'agréger les clés publiques de validator), ou seulementles signatures ECDMA des producteurs de blocs et s'appuient sur le fait que le Le producteur de blocs n’a pas été contesté ni réduit. Utiliser des transactions en chaîne et des preuves Merkle pour les défis. Il On peut noter qu'il n'y a aucune valeur à révéler les messages des validator si aucun Une transition d'état invalide a été détectée. Seuls les messages contenant le contenu réel les preuves de transition d'état invalide doivent être révélées, et uniquement pour de tels messages il faut montrer qu'ils correspondent au commit précédent. Le message doit être révélé à deux fins : 1. Pour lancer réellement le rollback de la chaîne au moment précédant le transition d'état invalide (voir section 3.7.5). 2. Pour prouver que le validator n'a pas tenté d'attester de la validité du morceau invalide. Dans les deux cas, nous devons résoudre deux problèmes : 1. Le commit réel n'était pas inclus dans la chaîne, seule la racine merkle du commit agrégé avec d’autres messages. Le validator doit utiliser le chemin merkle fourni par le producteur de blocs et leur engagement initial à prouver qu'ils se sont engagés à relever le défi. 2. Il est possible que tous les validator attribués au fragment avec le code invalide la transition d'état est attribuée à des producteurs de blocs corrompus qui les censurent. Pour contourner ce problème, nous leur permettons de soumettre leurs révélations comme une transaction régulière sur la chaîne et contourner l'agrégation. Cette dernière n'est autorisée que pour les preuves de transition d'état invalide, qui sont extrêmement rare, et ne devrait donc pas entraîner le spam des blocs. Le dernier problème à résoudre est que les producteurs de blocs peuvent choisissez de ne pas participer à l’agrégation de messages ou de censurer intentionnellement des validator particuliers. Nous le rendons économiquement désavantageux, en faisant en sorte que le bloc récompense du producteur proportionnelle au nombre de validator qui leur est attribué. Nous notons également que puisque les producteurs de blocs entre les époques se croisent largement (puisque c'est toujours le top avec les participants avec l'enjeu le plus élevé), les validator peuvent s'en tenir en grande partie à travailler avec les mêmes producteurs de blocs, et ainsi réduire le risque d'être assigné à un producteur de blocs qui les a censurés dans le passé. 3.9 Chaîne d'instantanés Étant donné que les blocs de la chaîne principale sont produits très fréquemment, le téléchargement l’histoire complète pourrait devenir coûteuse très rapidement. De plus, puisque chaque le bloc contient une signature BLS d'un grand nombre de participants, la seule agrégation des clés publiques pour vérifier la signature pourrait devenir prohibitive cher aussi. Enfin, puisque dans un avenir prévisible, Ethereum 1.0 restera probablement un des blockchain les plus utilisés, offrant un moyen significatif de transférer des actifs de
Près de Ethereum est une exigence, et aujourd'hui, la vérification des signatures BLS pour garantir La validité des blocs proches du côté de Ethereum n’est pas possible. Chaque bloc de la chaîne principale Nightshade peut éventuellement contenir un Schnorr multisignature sur l'en-tête du dernier bloc contenant un tel Schnorr multisignature. Nous appelons ces blocs des blocs instantanés. Le tout premier bloc de chaque époque doit être un bloc d'instantané. En travaillant sur une telle multisignature, les producteurs de blocs doivent également cumuler les signatures BLS des validator sur le dernier bloc d'instantané et agrégez-les de la même manière que décrit dans paragraphe 3.8. Puisque l’ensemble des producteurs de blocs est constant tout au long de l’époque, valider seuls les premiers blocs d’instantanés de chaque époque suffisent en supposant qu’à aucun moment point un grand pourcentage de producteurs de blocs et de validators se sont entendus et ont créé une fourchette. Le premier bloc de l’époque doit contenir des informations suffisantes pour calculer les producteurs de blocs et les validator pour l'époque. Nous appelons la sous-chaîne de la chaîne principale qui contient uniquement l'instantané bloque une chaîne d'instantanés. La création d'une multisignature Schnorr est un processus interactif, mais puisque nous il suffit de l'exécuter rarement, quel que soit le processus, aussi inefficace soit-il. suffira. Les multisignatures Schnorr peuvent être facilement validées sur Ethereum, fournissant ainsi des primitives cruciales pour un moyen sécurisé d'effectuer des cross-blockchain communications. Pour synchroniser avec la chaîne Near, il suffit de télécharger tous les instantanés bloque et confirme que les signatures Schnorr sont correctes (éventuellement en vérifiant également les signatures BLS individuelles des validator), puis en synchronisant uniquement blocs de chaîne principaux du dernier bloc d’instantané.
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.
Conclusion
Dans ce document, nous avons discuté des approches pour créer des blockchain fragmentés et a couvert deux défis majeurs des approches existantes, à savoir la validité d'état et la disponibilité des données. Nous avons ensuite présenté Nightshade, un design de sharding qui pouvoirs NEAR Protocole. La conception est en cours de réalisation, si vous avez des commentaires, des questions ou des retours sur ce document, veuillez vous rendre à https://near.chat.