No último dia de 2023, Vitalik compartilhou o roteiro do Ethereum para 2023 no Twitter, resumindo o progresso do Ethereum ao longo do ano. A seção do roteiro 'The Verge' descreveu como a tecnologia do Ethereum poderia verificar os estados do blockchain de forma mais simples e eficiente. Um conceito central mencionado lá são as Árvores Verkle. Então, o que são as Árvores Verkle, por que o Ethereum precisa delas e como as Árvores Verkle resolvem problemas? O objetivo deste artigo é responder a essas perguntas para leitores sem aprofundar muito na criptografia e matemática, ajudando aqueles com algum entendimento do Ethereum a compreender rapidamente o conceito de Árvores Verkle.
A tecnologia de consulta verificável é amplamente pesquisada no campo de bancos de dados tradicionais, usada principalmente para resolver problemas de confiança com bancos de dados externos. Em muitos cenários, os proprietários de dados podem optar por não armazenar os dados por conta própria, mas sim confiar suas necessidades de banco de dados a um terceiro para fornecer serviços de banco de dados (como bancos de dados em nuvem). No entanto, como terceiros nem sempre são confiáveis, a credibilidade dos resultados da consulta que eles retornam aos usuários é difícil de garantir. As soluções atuais de consulta verificáveis para bancos de dados tradicionais geralmente se enquadram em duas categorias: aquelas baseadas em ADS (Estruturas de Dados Autenticadas) e aquelas baseadas em computação verificável.
ADS é uma técnica de consulta verificável extensivamente usada em bancos de dados tradicionais, na sua maioria construídos sobre estruturas como Árvores de Merkle ou estruturas acumulativas similares. Com a evolução das ferramentas criptográficas, muitos pesquisadores gradualmente começaram a explorar o uso de técnicas de computação verificável para abordar problemas com consultas não confiáveis. Alguns esquemas de computação verificável baseados em protocolos de Prova de Conhecimento Zero, como SNARKs, podem apoiar indiretamente consultas verificáveis para bancos de dados externos. Esses esquemas suportam uma ampla variedade de tipos de consulta e geram menos informações de verificação, mas têm custos computacionais mais elevados.
Atualmente, o Ethereum usa Árvores de Merkle para implementar consultas verificáveis, e a tecnologia de Árvore Verkle também é baseada na tecnologia de Árvore de Merkle. Portanto, vamos primeiro introduzir as Árvores de Merkle para ajudar os leitores a entender o papel das consultas verificáveis usando-as como exemplo.
Árvores de Merkle são uma estrutura semelhante a uma árvore comumente usada em criptografia, adequada para resolver problemas de integridade de dados. Abaixo está uma estrutura típica de Árvore de Merkle: os nós folha representam os dados originais ou seus valores de hash, e cada nó não folha (interno) contém o hash combinado de seus nós filhos.
Árvores de Merkle têm duas características importantes:
Em um cenário comum de consulta verificável, há um provador e um verificador. O provador precisa gerar uma prova e enviá-la para o verificador. Correspondendo à rede Ethereum, um cenário típico de aplicativo é quando um nó leve (um cliente que armazena apenas cabeçalhos de bloco) consulta dados de transação de um nó completo ou um nó de arquivo (clientes com todos os dados) e obtém uma prova de Merkle para verificar localmente se o resultado da consulta está correto.
A prova de Merkle consiste nas seguintes três partes:
Dentre estes, o hash raiz da árvore de Merkle precisa ser enviado antecipadamente ao verificador por meio de um meio confiável, e o verificador deve confiar neste valor. No Ethereum, a confiabilidade dos dados do bloco é garantida pelo algoritmo de consenso, e o hash raiz da árvore de Merkle está contido no cabeçalho do bloco.
Aqui está um exemplo específico: quando o provador precisa provar ao verificador que '4' é um bloco de dados existente no conjunto de dados, e o verificador possui o hash raiz confiável '1d25' da árvore de Merkle do conjunto de dados completo, então o provador só precisa fornecer todos os dados marcados em azul. Supondo que existam n peças de dados no conjunto, no máximo são necessários cálculos de hash de 𝘭𝘰𝘨₂(𝘯) para verificar a correção de qualquer bloco de dados.
Os nós leves do Ethereum sincronizam apenas os cabeçalhos de bloco, que contêm as raízes das Árvores de Merkle para vários conjuntos de dados (árvore de estado, árvore de transações, árvore de recibos). Quando um nó leve faz uma consulta a um nó completo para os dados de um nó folha específico na árvore, o nó completo retorna os dados originais juntamente com o caminho da prova de Merkle correspondente. Isso permite que o nó leve confie na correção do resultado da consulta.
Construindo sobre a base das Árvores de Merkle, elas podem ser combinadas e modificadas com outras estruturas de dados para alcançar novas características com base em diferentes objetivos. Para atender a vários cenários de consulta verificáveis, as Árvores de Merkle podem ser estendidas a várias estruturas de dados indexadas, como as Árvores de Merkle-B (MBT). Para a execução eficiente de operações como inserção, exclusão e consulta, a equipe do Ethereum propôs a Árvore de Merkle Patricia (MPT).
A árvore Merkle-B (MBT) é principalmente usada para lidar com consultas de intervalo verificáveis. Deixe 𝑓 ser o fan-out do MBT (o número de nós filhos para cada nó). Com base na estrutura da árvore B+, cada nó interno do MBT, além de armazenar 𝑓 — 1 chaves de índice e ponteiros para 𝑓 nós filhos, também mantém os valores de hash de todos os seus nós filhos de forma resumida. Abaixo está uma representação da estrutura dos nós folha e nós internos em um MBT.
Quando é necessário provar que os dados retornados de uma determinada consulta de intervalo estão em conformidade com o intervalo especificado, o servidor que calcula o Objeto de Verificação (VO) deve primeiro realizar duas operações de busca de cima para baixo para encontrar os limites esquerdo e direito. Também deve retornar todos os dados dentro deste limite, bem como os hashes de todos os ramos necessários para construir o caminho até o hash raiz.
A desvantagem desta estrutura de dados é que o VO retornado só pode provar que os resultados da consulta estão dentro do intervalo de consulta solicitado, mas não pode provar que os resultados retornados são completos.
Se uma Árvore de Merkle ingênua é usada para fornecer consultas verificáveis, o processo demorado de regenerar a raiz da árvore de Merkle após cada inserção ou exclusão de dados pode se tornar significativo. Além disso, isso requer a manutenção de árvores de busca de dados adicionais para armazenamento. A Árvore de Patricia de Merkle (MPT) combina atributos de uma Árvore de Radix (árvore de prefixo compacta) e uma Árvore de Merkle, permitindo que ela execute inserções, exclusões e consultas em tempo O(log(N)). Para uma compreensão completa do MPT, os leitores podem consultar artigos técnicos detalhados sobre o assunto. Este artigo apenas apresentará algumas definições básicas e fornecerá exemplos para ajudar os leitores a entender rapidamente o MPT.
A estrutura subjacente do Ethereum emprega um banco de dados de chave-valor para armazenamento, o que significa que os dados são armazenados na forma de pares de chave-valor. O MPT também é decomposto em pares de chave-valor para armazenamento. Definimos a estrutura lógica dos nós do MPT da seguinte forma:
No contexto da Árvore Patricia Merkle (MPT), o “índice” refere-se à chave de um par chave-valor, enquanto o “caminho” combinado com os “dados” constitui o valor do par chave-valor. O índice realmente armazena o hash do nó da árvore de Merkle, e o caminho corresponde à string de caminho usada na árvore de prefixos para encontrar o nó alvo. O Ethereum usa strings hexadecimais como strings de caminho e, portanto, a largura do MPT é 16. Os dados são os dados alvo correspondentes ao caminho.
Abaixo está um exemplo de um MPT que foi otimizado com prefixos comprimidos, armazenando os seguintes dados de par de chave-valor:
{
'cab8': 'cachorro',
'cabe': 'cat',
‘39’: ‘frango’,
«395»: «pato»,
‘56f0’: ‘cavalo’
}
Para encontrar os dados 'pato' usando o caminho '395', você começaria no hash raiz e seguiria pelos hashA, hashC e hashD para finalmente alcançar os dados alvo. Aqui está um guia passo a passo:
Em cada etapa do caminho, o MPT aproveita as propriedades tanto da Árvore Radix, para encontrar o caminho correto com base na chave, quanto da Árvore de Merkle, para garantir a integridade dos dados por meio de links de hash. Os "caminhos" na árvore são tipicamente representados com uma codificação hexadecimal, que corresponde ao fator de ramificação da árvore de 16. Cada nó no caminho inclui hash pointers suficientes (para nós filhos) e valores para verificar a integridade dos dados e navegar pela árvore.
Por favor, note que em uma MPT real, os caminhos e os dados seriam codificados e armazenados em um formato específico, e tipos adicionais de nós (como nós de extensão e nós de folha) ajudam a otimizar a estrutura para eficiência em diferentes cenários.
Os esquemas de compromisso[1] são primitivas criptográficas que garantem a privacidade e integridade dos dados. Eles são amplamente utilizados em cenários como provas de conhecimento zero e computação segura de várias partes. Um esquema de compromisso básico é dividido em duas etapas: a fase de comprometimento e a fase de revelação (ou abertura).
O Compromisso de Vetor é um tipo especial de esquema de compromisso proposto por Catalano et al. [2] que permite a um comprometente fazer um compromisso com um conjunto ordenado de mensagens 𝑚 = ⟨𝑚1 , 𝑚2 , …, 𝑚𝑞 ⟩ e revelar (abrir) em qualquer posição especificada para provar que a mensagem 𝑚𝑖 é a mensagem comprometida. Em compromissos de vetor, vinculação significa que ninguém pode abrir a mesma posição para revelar mensagens diferentes.
Um esquema de compromisso de vetor geralmente consiste nos seguintes algoritmos:
Definição: Verkle Trees = Compromissos de Vetor + Árvores de Merkle.
Por favor, note: Vitalik Buterin, o co-fundador da Ethereum, tem um blogpost especificamente dedicado a introduzir árvores Verkle. Este capítulo adiciona algum contexto e conhecimento matemático com base em seu blog. Alguns dos dados e ilustrações no texto a seguir são derivados de seu blog.
As Árvores Verkle (VTs) são caracterizadas por fornecer provas menores em comparação com as Árvores Merkle. Para dados na escala de bilhões de entradas, uma árvore Merkle pode gerar provas de cerca de 1KB, enquanto as provas de árvore Verkle podem ter menos de 150 bytes. Esse tamanho compacto de prova é vantajoso para implementarclientes sem estado”.
A estrutura de uma árvore Verkle é um pouco semelhante à da Árvore Merkle Patricia (MPT). Aqui está um exemplo de sua estrutura. Os nós de uma árvore Verkle podem ser: (i) Vazios, (ii) Nós folha contendo uma chave e seu valor correspondente, ou (iii) Nós internos com um número fixo de nós filhos. Esse número de filhos também é referido como a “largura” da árvore.
A diferença entre VT (Verkle Trees) e MPT (Merkle Patricia Trees) reside principalmente em como a largura da árvore (ou fan-out, que se refere ao número de nós filhos que um nó na árvore possui) afeta sua eficiência. No caso do MPT, se a largura for maior, tende a ser menos eficiente porque uma largura maior significa mais nós irmãos, o que poderia resultar em tempos de atualização mais longos para o MPT e tamanhos de prova maiores. Por outro lado, para o VT, uma largura maior da árvore resulta em provas menores. A única restrição é que, se a largura for muito grande, o tempo necessário para gerar uma prova pode se tornar mais longo.
No Ethereum’s @vbuterin/verkle_tree_eip">Propostas de design para VTs, é sugerida uma largura de 256, o que é significativamente maior do que os atuais 16 para MPT. Uma largura tão grande é viável em VTs devido ao uso de técnicas criptográficas avançadas, como compromissos de vetor, que permitem provas compactas independentemente da largura da árvore. Essa técnica de compressão permite que as Verkle Trees se expandam de forma mais eficiente em termos de tamanho de prova. O texto subsequente explicará as características mencionadas acima com mais detalhes.
Vamos ver como as provas são geradas em um MPT: A prova precisa incluir os valores de hash de todos os nós laterais (ou nós irmãos) no caminho do nó raiz para o nó folha alvo. Tomando “4ce” como exemplo, as partes marcadas em vermelho no diagrama abaixo são os nós que precisam ser incluídos na prova retornada.
Em árvores Verkle, você não precisa fornecer nós irmãos; em vez disso, você só precisa fornecer o caminho juntamente com alguns dados adicionais como evidência.
Então, como gerar compromissos para um VT? A função de hash usada para o cálculo não é um hash convencional, mas usa compromissos vetoriais.
Após substituir a função hash por um algoritmo de geração de comprometimento a partir de compromissos vetoriais, o chamado hash raiz agora é um compromisso raiz. Se os dados de algum nó forem adulterados, isso afetará ultimamente o compromisso raiz.
Como gerar uma prova? Como mostrado no diagrama abaixo, você só precisa fornecer três subprovas, cada uma das quais pode provar que um nó no caminho existe em uma determinada posição dentro de seu nó pai. Quanto maior a largura, menos camadas, e consequentemente, menos subprovas são necessárias.
Nas implementações práticas, são utilizados compromissos polinomiais (que podem ser implementados de forma simples e eficiente para compromissos de vetor), permitindo um compromisso com um polinômio. Os dois esquemas de compromisso polinomial mais amigáveis ao usuário são “compromissos KZG” e “compromissos polinomiais no estilo à prova de balas(o primeiro tem um tamanho de compromisso de 48 bytes, enquanto o último tem 32 bytes).
Se você empregar compromissos e provas KZG, a prova para cada nó intermediário é apenas 96 bytes, o que representa uma economia de espaço de quase três vezes em comparação com uma árvore de Merkle básica (assumindo uma largura de 256).
A complexidade temporal teórica para operações em árvores de Merkle e árvores de Verkle é a seguinte:
O esquema de prova Verkle introduzido até agora é bastante básico; na verdade, existem outras estratégias avançadas de otimização disponíveis.
Em comparação com a geração de uma prova para cada camada de compromissos em um caminho, a característica dos compromissos polinomiais pode ser utilizada para alcançar 'provar o relacionamento pai-filho entre todos os compromissos no caminho com uma prova de tamanho fixo, que pode incluir um número ilimitado de elementos.' Para entender especificamente como isso é realizado, é necessário introduzir algum conhecimento matemático para explicação. Este artigo envolverá algumas fórmulas matemáticas, mas não abordará a parte criptográfica da prova em princípio. Para o método específico, consulte esquema que implementa multiprovas através de avaliação aleatória.
Primeiro, vamos introduzir alguns conceitos básicos sobre polinômios em matemática: como realizamos a redução de polinômio, também conhecida como redução de grau de um polinômio?
Supondo que conhecemos um polinômio 𝑃(𝑥) e seu valor 𝑦₁ em 𝑥₁, ou seja, 𝑃(𝑥₁) = 𝑦₁.
Agora, considere um novo polinômio 𝑃(𝑥) - 𝑦₁ , que tem um valor zero em (𝑥 = 𝑥₁) , porque 𝑃(𝑥₁) - 𝑦₁ =𝑦₁ - 𝑦₁ = 0.
Portanto, o polinômio 𝑃(𝑥) - 𝑦₁ tem uma raiz em 𝑥 = 𝑥₁, o que significa que (𝑥 - 𝑥₁) é um fator de 𝑃(𝑥) - 𝑦₁.
Em outras palavras, podemos expressá-lo na seguinte forma: [ 𝑃(𝑥) - 𝑦₁ = (𝑥 - 𝑥₁ )𝑄(𝑥)]
𝑄(𝑥) é outro polinômio cujo grau é um a menos do que o de 𝑃(𝑥). Isso ocorre porque (𝑥 -𝑥₁ ) é um fator de primeiro grau, o que reduz o grau total do polinômio.
Como usar KZG para provar um único valor em um vetor?
Tomemos o compromisso KZG10 como exemplo, para o polinômio 𝑃(𝑥) , suponhamos que seu compromisso polinomial seja [ 𝑃(𝑠) ]₁ .
Como explicado anteriormente, para o polinômio 𝑃(𝑥) , se 𝑃(𝑧) = 𝑦 , então temos 𝑄(𝑥) = (𝑃(𝑥) - 𝑦 )/(𝑥 - 𝑧)
Agora, o provador pode gerar uma prova de que o polinômio 𝑃(𝑥) satisfaz 𝑃(𝑧) = 𝑦: calcule [ 𝑄(𝑠) ]₁ e envie para o verificador.
O verificador precisa verificar 𝑒( [ 𝑄(𝑠) ]₁, [ 𝑠 - 𝑧]₂ ) = 𝑒( [ 𝑃(𝑠) ]₁- [𝑦]₁, [1]₂) .
Como usar KZG para provar múltiplos valores em um vetor?
Podemos construir uma prova para demonstrar múltiplos valores em um vetor da seguinte forma:
Ao usar este método, independentemente do número de pontos de dados no mesmo vetor que precisam ser verificados, apenas uma prova de tamanho constante é necessária.
Agora vamos olhar para o esquema da Árvore Verkle sem otimização do ponto de vista do algoritmo de comprometimento KZG.
Usando o método de construção da seção "Como usar KZG para provar um único valor em um vetor", o verificador pode construir compromissos para os polinômios originais e de quociente para cada polinômio 𝑓ᵢ(𝑥), resultando em um total de 𝟐﹡𝑚 compromissos KZG. O verificador envia todos esses compromissos como prova para verificação.
No entanto, como mencionado anteriormente, este método requer a geração de várias provas, e o verificador também precisa realizar múltiplos cálculos de verificação. Precisamos encontrar uma maneira de comprimir múltiplas provas de comprometimento.
Unindo as Provas
O provador envia a prova [ 𝑞( 𝑠 )]₁ para o verificador para verificação.
A evidência produzida por este esquema consiste em um compromisso, duas provas e um valor, com tamanho de dados constante. Eventualmente, após a otimização da fusão de provas na árvore Verkle, o objeto de dados verificável enviado ao verificador inclui o seguinte:
Observe que 𝑥ᵢ e 𝑦ᵢ não precisam ser fornecidos explicitamente; todos eles podem ser calculados.
Quanto ao esquema de fusão de prova para árvores Verkle, o tamanho específico da prova gerada é o seguinte (A unidade da linha é bilhão):
Os dados acima pressupõem a utilização de uma árvore de largura 256, empregando o esquema de compromisso KZG (com um tamanho de compromisso de 48 bytes) e maximiza a utilização da árvore. Na prática, para distribuições de informações completamente aleatórias, a profundidade da árvore aumentaria cerca de 60%, e o tamanho de cada elemento aumentaria em 30 bytes. Se o esquema à prova de balas for usado, o tamanho do compromisso seria de 32 bytes.
A seguir estão as palavras originais do blog de vitalik, adicionamos um parágrafo no final como suplemento.
As árvores Verkle são uma atualização poderosa para as provas de Merkle que permitem tamanhos de prova muito menores. Em vez de precisar fornecer todos os “nós irmãos” em cada nível, o provador só precisa fornecer uma única prova que prove todos os relacionamentos pai-filho entre todos os compromissos ao longo dos caminhos de cada nó folha até a raiz. Isso permite que os tamanhos das provas diminuam em um fator de ~6-8 em comparação com as árvores Merkle ideais, e em um fator de mais de 20-30 em comparação com as árvores Patricia hexagonais que o Ethereum usa hoje (!!).
Eles exigem uma criptografia mais complexa para serem implementados, mas oferecem a oportunidade de grandes ganhos em escalabilidade. No médio prazo, os SNARKs podem melhorar ainda mais as coisas: podemos SNARK o verificador de prova Verkle já eficiente para reduzir o tamanho da testemunha para quase zero, ou voltar para as provas Merkle SNARKed se/quando os SNARKs melhorarem muito (por exemplo, através de GKR, ou funções de hash muito amigáveis aos SNARKs, ou ASICs). Mais adiante, o surgimento da computação quântica forçará uma mudança para provas Merkle STARKed com hashes, pois torna os homomorfismos lineares nos quais as árvores Verkle dependem inseguros. Mas, por enquanto, eles nos proporcionam os mesmos ganhos de escalabilidade que obteríamos com tecnologias mais avançadas, e já temos todas as ferramentas necessárias para implementá-las eficientemente.
Atualmente, muitos clientes do Ethereum já forneceram a implementação da árvore Verkle e redes de teste relacionadas. A comunidade ainda está discutindo o momento em que as Árvores Verkle serão lançadas na rede principal. Provavelmente será implementado em uma atualização de hard fork em 2024 ou 2025. Para obter informações detalhadas sobre as árvores Verkle no Ethereum, consulte https://verkle.info/ .
[1]. BRASSARD G, CHAUM D, CRÉPEAU C. Provas de conhecimento de divulgação mínima[J]. Journal of computer and system sciences, 1988, 37(2): 156–189.
[2]. CATALANO D, FIORE D. Compromissos de vetor e suas aplicações[C]//Criptografia de Chave Pública - PKC 2013: 16ª Conferência Internacional sobre Prática e Teoria em Criptografia de Chave Pública, Nara, Japão, 26 de fevereiro a 1 de março de 2013. Proceedings 16. Springer, 2013: 55–72.
No último dia de 2023, Vitalik compartilhou o roteiro do Ethereum para 2023 no Twitter, resumindo o progresso do Ethereum ao longo do ano. A seção do roteiro 'The Verge' descreveu como a tecnologia do Ethereum poderia verificar os estados do blockchain de forma mais simples e eficiente. Um conceito central mencionado lá são as Árvores Verkle. Então, o que são as Árvores Verkle, por que o Ethereum precisa delas e como as Árvores Verkle resolvem problemas? O objetivo deste artigo é responder a essas perguntas para leitores sem aprofundar muito na criptografia e matemática, ajudando aqueles com algum entendimento do Ethereum a compreender rapidamente o conceito de Árvores Verkle.
A tecnologia de consulta verificável é amplamente pesquisada no campo de bancos de dados tradicionais, usada principalmente para resolver problemas de confiança com bancos de dados externos. Em muitos cenários, os proprietários de dados podem optar por não armazenar os dados por conta própria, mas sim confiar suas necessidades de banco de dados a um terceiro para fornecer serviços de banco de dados (como bancos de dados em nuvem). No entanto, como terceiros nem sempre são confiáveis, a credibilidade dos resultados da consulta que eles retornam aos usuários é difícil de garantir. As soluções atuais de consulta verificáveis para bancos de dados tradicionais geralmente se enquadram em duas categorias: aquelas baseadas em ADS (Estruturas de Dados Autenticadas) e aquelas baseadas em computação verificável.
ADS é uma técnica de consulta verificável extensivamente usada em bancos de dados tradicionais, na sua maioria construídos sobre estruturas como Árvores de Merkle ou estruturas acumulativas similares. Com a evolução das ferramentas criptográficas, muitos pesquisadores gradualmente começaram a explorar o uso de técnicas de computação verificável para abordar problemas com consultas não confiáveis. Alguns esquemas de computação verificável baseados em protocolos de Prova de Conhecimento Zero, como SNARKs, podem apoiar indiretamente consultas verificáveis para bancos de dados externos. Esses esquemas suportam uma ampla variedade de tipos de consulta e geram menos informações de verificação, mas têm custos computacionais mais elevados.
Atualmente, o Ethereum usa Árvores de Merkle para implementar consultas verificáveis, e a tecnologia de Árvore Verkle também é baseada na tecnologia de Árvore de Merkle. Portanto, vamos primeiro introduzir as Árvores de Merkle para ajudar os leitores a entender o papel das consultas verificáveis usando-as como exemplo.
Árvores de Merkle são uma estrutura semelhante a uma árvore comumente usada em criptografia, adequada para resolver problemas de integridade de dados. Abaixo está uma estrutura típica de Árvore de Merkle: os nós folha representam os dados originais ou seus valores de hash, e cada nó não folha (interno) contém o hash combinado de seus nós filhos.
Árvores de Merkle têm duas características importantes:
Em um cenário comum de consulta verificável, há um provador e um verificador. O provador precisa gerar uma prova e enviá-la para o verificador. Correspondendo à rede Ethereum, um cenário típico de aplicativo é quando um nó leve (um cliente que armazena apenas cabeçalhos de bloco) consulta dados de transação de um nó completo ou um nó de arquivo (clientes com todos os dados) e obtém uma prova de Merkle para verificar localmente se o resultado da consulta está correto.
A prova de Merkle consiste nas seguintes três partes:
Dentre estes, o hash raiz da árvore de Merkle precisa ser enviado antecipadamente ao verificador por meio de um meio confiável, e o verificador deve confiar neste valor. No Ethereum, a confiabilidade dos dados do bloco é garantida pelo algoritmo de consenso, e o hash raiz da árvore de Merkle está contido no cabeçalho do bloco.
Aqui está um exemplo específico: quando o provador precisa provar ao verificador que '4' é um bloco de dados existente no conjunto de dados, e o verificador possui o hash raiz confiável '1d25' da árvore de Merkle do conjunto de dados completo, então o provador só precisa fornecer todos os dados marcados em azul. Supondo que existam n peças de dados no conjunto, no máximo são necessários cálculos de hash de 𝘭𝘰𝘨₂(𝘯) para verificar a correção de qualquer bloco de dados.
Os nós leves do Ethereum sincronizam apenas os cabeçalhos de bloco, que contêm as raízes das Árvores de Merkle para vários conjuntos de dados (árvore de estado, árvore de transações, árvore de recibos). Quando um nó leve faz uma consulta a um nó completo para os dados de um nó folha específico na árvore, o nó completo retorna os dados originais juntamente com o caminho da prova de Merkle correspondente. Isso permite que o nó leve confie na correção do resultado da consulta.
Construindo sobre a base das Árvores de Merkle, elas podem ser combinadas e modificadas com outras estruturas de dados para alcançar novas características com base em diferentes objetivos. Para atender a vários cenários de consulta verificáveis, as Árvores de Merkle podem ser estendidas a várias estruturas de dados indexadas, como as Árvores de Merkle-B (MBT). Para a execução eficiente de operações como inserção, exclusão e consulta, a equipe do Ethereum propôs a Árvore de Merkle Patricia (MPT).
A árvore Merkle-B (MBT) é principalmente usada para lidar com consultas de intervalo verificáveis. Deixe 𝑓 ser o fan-out do MBT (o número de nós filhos para cada nó). Com base na estrutura da árvore B+, cada nó interno do MBT, além de armazenar 𝑓 — 1 chaves de índice e ponteiros para 𝑓 nós filhos, também mantém os valores de hash de todos os seus nós filhos de forma resumida. Abaixo está uma representação da estrutura dos nós folha e nós internos em um MBT.
Quando é necessário provar que os dados retornados de uma determinada consulta de intervalo estão em conformidade com o intervalo especificado, o servidor que calcula o Objeto de Verificação (VO) deve primeiro realizar duas operações de busca de cima para baixo para encontrar os limites esquerdo e direito. Também deve retornar todos os dados dentro deste limite, bem como os hashes de todos os ramos necessários para construir o caminho até o hash raiz.
A desvantagem desta estrutura de dados é que o VO retornado só pode provar que os resultados da consulta estão dentro do intervalo de consulta solicitado, mas não pode provar que os resultados retornados são completos.
Se uma Árvore de Merkle ingênua é usada para fornecer consultas verificáveis, o processo demorado de regenerar a raiz da árvore de Merkle após cada inserção ou exclusão de dados pode se tornar significativo. Além disso, isso requer a manutenção de árvores de busca de dados adicionais para armazenamento. A Árvore de Patricia de Merkle (MPT) combina atributos de uma Árvore de Radix (árvore de prefixo compacta) e uma Árvore de Merkle, permitindo que ela execute inserções, exclusões e consultas em tempo O(log(N)). Para uma compreensão completa do MPT, os leitores podem consultar artigos técnicos detalhados sobre o assunto. Este artigo apenas apresentará algumas definições básicas e fornecerá exemplos para ajudar os leitores a entender rapidamente o MPT.
A estrutura subjacente do Ethereum emprega um banco de dados de chave-valor para armazenamento, o que significa que os dados são armazenados na forma de pares de chave-valor. O MPT também é decomposto em pares de chave-valor para armazenamento. Definimos a estrutura lógica dos nós do MPT da seguinte forma:
No contexto da Árvore Patricia Merkle (MPT), o “índice” refere-se à chave de um par chave-valor, enquanto o “caminho” combinado com os “dados” constitui o valor do par chave-valor. O índice realmente armazena o hash do nó da árvore de Merkle, e o caminho corresponde à string de caminho usada na árvore de prefixos para encontrar o nó alvo. O Ethereum usa strings hexadecimais como strings de caminho e, portanto, a largura do MPT é 16. Os dados são os dados alvo correspondentes ao caminho.
Abaixo está um exemplo de um MPT que foi otimizado com prefixos comprimidos, armazenando os seguintes dados de par de chave-valor:
{
'cab8': 'cachorro',
'cabe': 'cat',
‘39’: ‘frango’,
«395»: «pato»,
‘56f0’: ‘cavalo’
}
Para encontrar os dados 'pato' usando o caminho '395', você começaria no hash raiz e seguiria pelos hashA, hashC e hashD para finalmente alcançar os dados alvo. Aqui está um guia passo a passo:
Em cada etapa do caminho, o MPT aproveita as propriedades tanto da Árvore Radix, para encontrar o caminho correto com base na chave, quanto da Árvore de Merkle, para garantir a integridade dos dados por meio de links de hash. Os "caminhos" na árvore são tipicamente representados com uma codificação hexadecimal, que corresponde ao fator de ramificação da árvore de 16. Cada nó no caminho inclui hash pointers suficientes (para nós filhos) e valores para verificar a integridade dos dados e navegar pela árvore.
Por favor, note que em uma MPT real, os caminhos e os dados seriam codificados e armazenados em um formato específico, e tipos adicionais de nós (como nós de extensão e nós de folha) ajudam a otimizar a estrutura para eficiência em diferentes cenários.
Os esquemas de compromisso[1] são primitivas criptográficas que garantem a privacidade e integridade dos dados. Eles são amplamente utilizados em cenários como provas de conhecimento zero e computação segura de várias partes. Um esquema de compromisso básico é dividido em duas etapas: a fase de comprometimento e a fase de revelação (ou abertura).
O Compromisso de Vetor é um tipo especial de esquema de compromisso proposto por Catalano et al. [2] que permite a um comprometente fazer um compromisso com um conjunto ordenado de mensagens 𝑚 = ⟨𝑚1 , 𝑚2 , …, 𝑚𝑞 ⟩ e revelar (abrir) em qualquer posição especificada para provar que a mensagem 𝑚𝑖 é a mensagem comprometida. Em compromissos de vetor, vinculação significa que ninguém pode abrir a mesma posição para revelar mensagens diferentes.
Um esquema de compromisso de vetor geralmente consiste nos seguintes algoritmos:
Definição: Verkle Trees = Compromissos de Vetor + Árvores de Merkle.
Por favor, note: Vitalik Buterin, o co-fundador da Ethereum, tem um blogpost especificamente dedicado a introduzir árvores Verkle. Este capítulo adiciona algum contexto e conhecimento matemático com base em seu blog. Alguns dos dados e ilustrações no texto a seguir são derivados de seu blog.
As Árvores Verkle (VTs) são caracterizadas por fornecer provas menores em comparação com as Árvores Merkle. Para dados na escala de bilhões de entradas, uma árvore Merkle pode gerar provas de cerca de 1KB, enquanto as provas de árvore Verkle podem ter menos de 150 bytes. Esse tamanho compacto de prova é vantajoso para implementarclientes sem estado”.
A estrutura de uma árvore Verkle é um pouco semelhante à da Árvore Merkle Patricia (MPT). Aqui está um exemplo de sua estrutura. Os nós de uma árvore Verkle podem ser: (i) Vazios, (ii) Nós folha contendo uma chave e seu valor correspondente, ou (iii) Nós internos com um número fixo de nós filhos. Esse número de filhos também é referido como a “largura” da árvore.
A diferença entre VT (Verkle Trees) e MPT (Merkle Patricia Trees) reside principalmente em como a largura da árvore (ou fan-out, que se refere ao número de nós filhos que um nó na árvore possui) afeta sua eficiência. No caso do MPT, se a largura for maior, tende a ser menos eficiente porque uma largura maior significa mais nós irmãos, o que poderia resultar em tempos de atualização mais longos para o MPT e tamanhos de prova maiores. Por outro lado, para o VT, uma largura maior da árvore resulta em provas menores. A única restrição é que, se a largura for muito grande, o tempo necessário para gerar uma prova pode se tornar mais longo.
No Ethereum’s @vbuterin/verkle_tree_eip">Propostas de design para VTs, é sugerida uma largura de 256, o que é significativamente maior do que os atuais 16 para MPT. Uma largura tão grande é viável em VTs devido ao uso de técnicas criptográficas avançadas, como compromissos de vetor, que permitem provas compactas independentemente da largura da árvore. Essa técnica de compressão permite que as Verkle Trees se expandam de forma mais eficiente em termos de tamanho de prova. O texto subsequente explicará as características mencionadas acima com mais detalhes.
Vamos ver como as provas são geradas em um MPT: A prova precisa incluir os valores de hash de todos os nós laterais (ou nós irmãos) no caminho do nó raiz para o nó folha alvo. Tomando “4ce” como exemplo, as partes marcadas em vermelho no diagrama abaixo são os nós que precisam ser incluídos na prova retornada.
Em árvores Verkle, você não precisa fornecer nós irmãos; em vez disso, você só precisa fornecer o caminho juntamente com alguns dados adicionais como evidência.
Então, como gerar compromissos para um VT? A função de hash usada para o cálculo não é um hash convencional, mas usa compromissos vetoriais.
Após substituir a função hash por um algoritmo de geração de comprometimento a partir de compromissos vetoriais, o chamado hash raiz agora é um compromisso raiz. Se os dados de algum nó forem adulterados, isso afetará ultimamente o compromisso raiz.
Como gerar uma prova? Como mostrado no diagrama abaixo, você só precisa fornecer três subprovas, cada uma das quais pode provar que um nó no caminho existe em uma determinada posição dentro de seu nó pai. Quanto maior a largura, menos camadas, e consequentemente, menos subprovas são necessárias.
Nas implementações práticas, são utilizados compromissos polinomiais (que podem ser implementados de forma simples e eficiente para compromissos de vetor), permitindo um compromisso com um polinômio. Os dois esquemas de compromisso polinomial mais amigáveis ao usuário são “compromissos KZG” e “compromissos polinomiais no estilo à prova de balas(o primeiro tem um tamanho de compromisso de 48 bytes, enquanto o último tem 32 bytes).
Se você empregar compromissos e provas KZG, a prova para cada nó intermediário é apenas 96 bytes, o que representa uma economia de espaço de quase três vezes em comparação com uma árvore de Merkle básica (assumindo uma largura de 256).
A complexidade temporal teórica para operações em árvores de Merkle e árvores de Verkle é a seguinte:
O esquema de prova Verkle introduzido até agora é bastante básico; na verdade, existem outras estratégias avançadas de otimização disponíveis.
Em comparação com a geração de uma prova para cada camada de compromissos em um caminho, a característica dos compromissos polinomiais pode ser utilizada para alcançar 'provar o relacionamento pai-filho entre todos os compromissos no caminho com uma prova de tamanho fixo, que pode incluir um número ilimitado de elementos.' Para entender especificamente como isso é realizado, é necessário introduzir algum conhecimento matemático para explicação. Este artigo envolverá algumas fórmulas matemáticas, mas não abordará a parte criptográfica da prova em princípio. Para o método específico, consulte esquema que implementa multiprovas através de avaliação aleatória.
Primeiro, vamos introduzir alguns conceitos básicos sobre polinômios em matemática: como realizamos a redução de polinômio, também conhecida como redução de grau de um polinômio?
Supondo que conhecemos um polinômio 𝑃(𝑥) e seu valor 𝑦₁ em 𝑥₁, ou seja, 𝑃(𝑥₁) = 𝑦₁.
Agora, considere um novo polinômio 𝑃(𝑥) - 𝑦₁ , que tem um valor zero em (𝑥 = 𝑥₁) , porque 𝑃(𝑥₁) - 𝑦₁ =𝑦₁ - 𝑦₁ = 0.
Portanto, o polinômio 𝑃(𝑥) - 𝑦₁ tem uma raiz em 𝑥 = 𝑥₁, o que significa que (𝑥 - 𝑥₁) é um fator de 𝑃(𝑥) - 𝑦₁.
Em outras palavras, podemos expressá-lo na seguinte forma: [ 𝑃(𝑥) - 𝑦₁ = (𝑥 - 𝑥₁ )𝑄(𝑥)]
𝑄(𝑥) é outro polinômio cujo grau é um a menos do que o de 𝑃(𝑥). Isso ocorre porque (𝑥 -𝑥₁ ) é um fator de primeiro grau, o que reduz o grau total do polinômio.
Como usar KZG para provar um único valor em um vetor?
Tomemos o compromisso KZG10 como exemplo, para o polinômio 𝑃(𝑥) , suponhamos que seu compromisso polinomial seja [ 𝑃(𝑠) ]₁ .
Como explicado anteriormente, para o polinômio 𝑃(𝑥) , se 𝑃(𝑧) = 𝑦 , então temos 𝑄(𝑥) = (𝑃(𝑥) - 𝑦 )/(𝑥 - 𝑧)
Agora, o provador pode gerar uma prova de que o polinômio 𝑃(𝑥) satisfaz 𝑃(𝑧) = 𝑦: calcule [ 𝑄(𝑠) ]₁ e envie para o verificador.
O verificador precisa verificar 𝑒( [ 𝑄(𝑠) ]₁, [ 𝑠 - 𝑧]₂ ) = 𝑒( [ 𝑃(𝑠) ]₁- [𝑦]₁, [1]₂) .
Como usar KZG para provar múltiplos valores em um vetor?
Podemos construir uma prova para demonstrar múltiplos valores em um vetor da seguinte forma:
Ao usar este método, independentemente do número de pontos de dados no mesmo vetor que precisam ser verificados, apenas uma prova de tamanho constante é necessária.
Agora vamos olhar para o esquema da Árvore Verkle sem otimização do ponto de vista do algoritmo de comprometimento KZG.
Usando o método de construção da seção "Como usar KZG para provar um único valor em um vetor", o verificador pode construir compromissos para os polinômios originais e de quociente para cada polinômio 𝑓ᵢ(𝑥), resultando em um total de 𝟐﹡𝑚 compromissos KZG. O verificador envia todos esses compromissos como prova para verificação.
No entanto, como mencionado anteriormente, este método requer a geração de várias provas, e o verificador também precisa realizar múltiplos cálculos de verificação. Precisamos encontrar uma maneira de comprimir múltiplas provas de comprometimento.
Unindo as Provas
O provador envia a prova [ 𝑞( 𝑠 )]₁ para o verificador para verificação.
A evidência produzida por este esquema consiste em um compromisso, duas provas e um valor, com tamanho de dados constante. Eventualmente, após a otimização da fusão de provas na árvore Verkle, o objeto de dados verificável enviado ao verificador inclui o seguinte:
Observe que 𝑥ᵢ e 𝑦ᵢ não precisam ser fornecidos explicitamente; todos eles podem ser calculados.
Quanto ao esquema de fusão de prova para árvores Verkle, o tamanho específico da prova gerada é o seguinte (A unidade da linha é bilhão):
Os dados acima pressupõem a utilização de uma árvore de largura 256, empregando o esquema de compromisso KZG (com um tamanho de compromisso de 48 bytes) e maximiza a utilização da árvore. Na prática, para distribuições de informações completamente aleatórias, a profundidade da árvore aumentaria cerca de 60%, e o tamanho de cada elemento aumentaria em 30 bytes. Se o esquema à prova de balas for usado, o tamanho do compromisso seria de 32 bytes.
A seguir estão as palavras originais do blog de vitalik, adicionamos um parágrafo no final como suplemento.
As árvores Verkle são uma atualização poderosa para as provas de Merkle que permitem tamanhos de prova muito menores. Em vez de precisar fornecer todos os “nós irmãos” em cada nível, o provador só precisa fornecer uma única prova que prove todos os relacionamentos pai-filho entre todos os compromissos ao longo dos caminhos de cada nó folha até a raiz. Isso permite que os tamanhos das provas diminuam em um fator de ~6-8 em comparação com as árvores Merkle ideais, e em um fator de mais de 20-30 em comparação com as árvores Patricia hexagonais que o Ethereum usa hoje (!!).
Eles exigem uma criptografia mais complexa para serem implementados, mas oferecem a oportunidade de grandes ganhos em escalabilidade. No médio prazo, os SNARKs podem melhorar ainda mais as coisas: podemos SNARK o verificador de prova Verkle já eficiente para reduzir o tamanho da testemunha para quase zero, ou voltar para as provas Merkle SNARKed se/quando os SNARKs melhorarem muito (por exemplo, através de GKR, ou funções de hash muito amigáveis aos SNARKs, ou ASICs). Mais adiante, o surgimento da computação quântica forçará uma mudança para provas Merkle STARKed com hashes, pois torna os homomorfismos lineares nos quais as árvores Verkle dependem inseguros. Mas, por enquanto, eles nos proporcionam os mesmos ganhos de escalabilidade que obteríamos com tecnologias mais avançadas, e já temos todas as ferramentas necessárias para implementá-las eficientemente.
Atualmente, muitos clientes do Ethereum já forneceram a implementação da árvore Verkle e redes de teste relacionadas. A comunidade ainda está discutindo o momento em que as Árvores Verkle serão lançadas na rede principal. Provavelmente será implementado em uma atualização de hard fork em 2024 ou 2025. Para obter informações detalhadas sobre as árvores Verkle no Ethereum, consulte https://verkle.info/ .
[1]. BRASSARD G, CHAUM D, CRÉPEAU C. Provas de conhecimento de divulgação mínima[J]. Journal of computer and system sciences, 1988, 37(2): 156–189.
[2]. CATALANO D, FIORE D. Compromissos de vetor e suas aplicações[C]//Criptografia de Chave Pública - PKC 2013: 16ª Conferência Internacional sobre Prática e Teoria em Criptografia de Chave Pública, Nara, Japão, 26 de fevereiro a 1 de março de 2013. Proceedings 16. Springer, 2013: 55–72.