No último dia de 2023, Vitalik partilhou o roteiro da Ethereum para 2023 no Twitter, resumindo o progresso da Ethereum ao longo do ano. A secção do roteiro "The Verge" descreve como a tecnologia da Ethereum pode verificar os estados da blockchain de forma mais simples e eficiente. Um conceito fundamental mencionado lá são as Árvores Verkle. Então, o que são Árvores Verkle, por que a Ethereum precisa delas e como as Árvores Verkle resolvem problemas? O objetivo deste artigo é responder a estas questões para os leitores sem aprofundar demasiado em criptografia e matemática, ajudando aqueles com alguma compreensão da Ethereum a entender rapidamente o conceito das Árvores Verkle.
A tecnologia de consulta verificável é amplamente pesquisada no campo das bases de dados tradicionais, sendo principalmente utilizada para resolver problemas de confiança com bases de dados externas. Em muitos cenários, os proprietários de dados podem optar por não armazenar os dados eles próprios, mas sim confiar suas necessidades de base de dados a um terceiro para fornecer serviços de base de dados (como bases de dados na nuvem). No entanto, como terceiros nem sempre são confiáveis, a credibilidade dos resultados da consulta que eles devolvem aos utilizadores é difícil de garantir. As soluções atuais de consulta verificável para bases 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 utilizada em bases de dados tradicionais, maioritariamente construída sobre estruturas como Árvores de Merkle ou estruturas acumulativas similares. Com a evolução das ferramentas criptográficas, muitos investigadores começaram gradualmente a explorar o uso de técnicas de computação verificável para lidar com questões relacionadas com consultas não confiáveis. Alguns esquemas de computação verificável baseados em protocolos de Prova de Conhecimento Zero, como SNARKs, podem indiretamente suportar consultas verificáveis para bases de dados externas. Estes 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 Verkle Tree 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.
As á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.
As árvores Merkle têm duas características importantes:
Num cenário de consulta verificável comum, existe um provador e um verificador. O provador precisa gerar uma prova e enviá-la ao verificador. Correspondendo à rede Ethereum, um cenário de aplicação típico é onde 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 de bloco é assegurada 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 detém 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 a azul. Assumindo que existam n peças de dados no conjunto, são necessários no máximo cálculos de hash 𝘭𝘰𝘨₂(𝘯) para verificar a correção de qualquer bloco de dados.
Os nós leves do Ethereum apenas sincronizam 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ção, árvore de recibos). Quando um nó leve consulta um nó completo para os dados de um nó folha específico na árvore, o nó completo devolve 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.
Baseando-se na fundação 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 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. Seja 𝑓 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 apontadores para 𝑓 nós filhos, mantém també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 for 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 pesquisa 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 estão completos.
Se uma Árvore de Merkle ingênua é usada para fornecer consultas verificáveis, o processo demorado de regeneração da 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 Radix (árvore compacta de prefixo) e uma Árvore de Merkle, permitindo que ela realize 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 introduzirá algumas definições básicas e fornecerá exemplos para ajudar os leitores a entender rapidamente o MPT.
A estrutura subjacente do Ethereum emprega uma base de dados chave-valor para armazenamento, o que significa que os dados são armazenados na forma de pares chave-valor. O MPT também é decomposto em pares chave-valor para armazenamento. Definimos a estrutura lógica dos nós MPT da seguinte forma:
No contexto da Árvore de Merkle Patricia (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 armazena na realidade 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. 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 chave-valor:
{
‘cab8’: ‘cão’,
‘cabe’: ‘gato’,
‘39’: ‘frango’,
'395': 'pato',
'56f0': 'cavalo'
}
Para encontrar os dados "pato" usando o caminho "395", começaria no hash raiz e seguiria pelos hashes A, C e D para finalmente chegar aos dados alvo. Aqui está um guia passo a passo:
Em cada etapa do caminho, o MPT alavanca 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 através 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 num MPT real, os caminhos e os dados seriam codificados e armazenados num formato específico, e tipos adicionais de nós (como nós de extensão e nós 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. São amplamente utilizados em cenários como provas de conhecimento zero e computação segura entre várias partes. Um esquema de compromisso básico é dividido em duas fases: a fase de compromisso 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 ith. Nos compromissos de vetor, o termo vinculativo significa que ninguém pode abrir a mesma posição para revelar mensagens diferentes.
Um esquema de compromisso vetorial geralmente consiste nos seguintes algoritmos:
Definição: Árvores Verkle = Compromissos de Vetor + Árvores de Merkle.
Por favor, note: Vitalik Buterin, o co-fundador do Ethereum, tem um blogpost especificamente dedicado a apresentar árvores Verkle. Este capítulo acrescenta algum contexto e conhecimento matemático baseado no seu blog. Alguns dos dados e ilustrações no texto seguinte são derivados do seu blog.
As Árvores Verkle (VTs) são caracterizadas por fornecer provas menores em comparação com as Árvores de Merkle. Para dados na escala de bilhões de entradas, uma árvore de Merkle pode gerar provas de cerca de 1KB de tamanho, enquanto as provas de árvore Verkle podem ter menos de 150 bytes. Este tamanho compacto de prova é vantajoso para implementar clientes sem estado”.
A estrutura de uma árvore Verkle é algo semelhante à da Árvore Merkle Patricia (MPT). Aqui está um exemplo da sua estrutura. Os nós de uma árvore Verkle podem ser: (i) Vazios, (ii) Nós folha contendo uma chave e o seu valor correspondente, ou (iii) Nós internos com um número fixo de nós filhos. Este 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 na forma 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 maior largura significa mais nós irmãos, o que poderia levar a tempos de atualização mais longos para o MPT e tamanhos de prova maiores. Por outro lado, para VT, uma largura de árvore mais ampla resulta em provas menores. A única restrição é que, se a largura for muito alta, 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, 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 vetoriais, que permitem provas compactas independentemente da largura da árvore. Esta técnica de compressão permite que as Verkle Trees dimensionem de forma mais eficiente em termos de tamanho de prova. O texto subsequente irá explicar com mais detalhe as funcionalidades mencionadas acima.
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 a vermelho no diagrama abaixo são os nós que precisam ser incluídos na prova retornada.
Nas árvores Verkle, não é necessário fornecer nós irmãos; em vez disso, só precisa de 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 a computação não é um hash convencional, mas usa compromissos vetoriais.
Após substituir a função hash por um algoritmo de geração de compromisso a partir de compromissos vetoriais, o chamado hash raiz agora é um compromisso raiz. Se os dados de algum nó forem adulterados, isso afetará o compromisso raiz.
Como gerar uma prova? Como mostrado no diagrama abaixo, só precisa de fornecer três subprovas, cada uma das quais pode provar que um nó no caminho existe numa posição específica dentro do 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 para o usuário são “compromissos KZG” e “compromissos polinomiais estilo à prova de balas (o primeiro tem um tamanho de compromisso de 48 bytes, enquanto o último tem 32 bytes).
Se utilizar compromissos e provas KZG, a prova para cada nó intermédio é apenas 96 bytes, o que representa uma poupança de espaço quase três vezes superior a 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.
Comparando 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 a “comprovação da relação 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 cobrirá a parte criptográfica da prova em princípio. Para o método específico, consulteesquema 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ómios, também conhecida como redução de grau de um polinómio?
Supondo que conhecemos um polinómio 𝑃(𝑥) e o seu valor 𝑦₁ em 𝑥₁, ou seja, 𝑃(𝑥₁) = 𝑦₁.
Agora, considere um novo polinómio 𝑃(𝑥) - 𝑦₁ , que tem um valor de zero em (𝑥 = 𝑥₁) , porque 𝑃(𝑥₁) - 𝑦₁ =𝑦₁ - 𝑦₁ = 0.
Portanto, o polinómio 𝑃(𝑥) - 𝑦₁ tem uma raiz em 𝑥 = 𝑥₁, o que significa que (𝑥 - 𝑥₁) é um factor de 𝑃(𝑥) - 𝑦₁.
Em outras palavras, podemos expressá-lo na seguinte forma: [ 𝑃(𝑥) - 𝑦₁ = (𝑥 - 𝑥₁ )𝑄(𝑥)]
𝑄(𝑥) é outro polinómio cujo grau é um a menos do que o de 𝑃(𝑥). Isto deve-se a (𝑥 -𝑥₁ ) ser um fator de primeiro grau, o que reduz o grau total do polinómio.
Como usar KZG para provar um único valor num vetor?
Tomemos o compromisso KZG10 como exemplo, para o polinómio 𝑃(𝑥), suponhamos que o seu compromisso polinomial é [ 𝑃(𝑠) ]₁ .
Como explicado anteriormente, para o polinómio 𝑃(𝑥), se 𝑃(𝑧) = 𝑦, então temos 𝑄(𝑥) = (𝑃(𝑥) - 𝑦)/(𝑥 - 𝑧)
Agora, o provador pode gerar uma prova de que o polinómio 𝑃(𝑥) satisfaz 𝑃(𝑧) = 𝑦 : calcular [ 𝑄(𝑠) ]₁ e enviá-lo ao verificador.
O verificador precisa verificar 𝑒( [ 𝑄(𝑠) ]₁, [ 𝑠 - 𝑧]₂ ) = 𝑒( [ 𝑃(𝑠) ]₁- [𝑦]₁, [1]₂) .
Como usar KZG para provar múltiplos valores num 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 a partir da perspetiva do algoritmo de compromisso 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 original e quociente para cada polinómio 𝑓ᵢ(𝑥) , resultando num total de 𝟐﹡𝑚 compromissos KZG. O verificador envia todos estes 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 forma de comprimir várias provas de compromisso.
Fusão das Provas
O provador envia a prova [ 𝑞( 𝑠 )]₁ ao 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 da prova na árvore Verkle, o objeto de dados verificável enviado ao verificador inclui o seguinte:
Note que 𝑥ᵢ e 𝑦ᵢ não precisam ser fornecidos explicitamente; todos 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 com largura de 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, então o tamanho do compromisso seria de 32 bytes.
As seguintes são as palavras originais do blog do Vitalik, adicionamos um parágrafo no final como suplemento.
As árvores Verkle são uma atualização poderosa para 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 hexarias que o Ethereum usa hoje (!!).
Eles exigem uma criptografia mais complexa para implementar, mas apresentam a oportunidade de grandes ganhos em escalabilidade. A médio prazo, as SNARKs podem melhorar ainda mais as coisas: podemos SNARK o verificador de prova Verkle já eficiente para reduzir o tamanho da testemunha para próximo de zero, ou voltar a provas SNARKed de Merkle se/quando as SNARKs ficarem muito melhores (por exemplo, através de GKR, ou funções de hash muito amigáveis para SNARK, ou ASICs). Mais adiante, o surgimento da computação quântica forçará uma mudança para provas de Merkle STARKed com hashes, pois torna as homomorfismos lineares em que as árvores Verkle dependem inseguras. Mas, por enquanto, eles nos dão os mesmos ganhos de escalabilidade que obteríamos com tecnologias mais avançadas, e já temos todas as ferramentas de que precisamos para implementá-las de forma eficiente.
Atualmente, muitos clientes Ethereum 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. É provável que seja implementada 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 mínimas de conhecimento de divulgação[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. Atas 16. Springer, 2013: 55-72.
No último dia de 2023, Vitalik partilhou o roteiro da Ethereum para 2023 no Twitter, resumindo o progresso da Ethereum ao longo do ano. A secção do roteiro "The Verge" descreve como a tecnologia da Ethereum pode verificar os estados da blockchain de forma mais simples e eficiente. Um conceito fundamental mencionado lá são as Árvores Verkle. Então, o que são Árvores Verkle, por que a Ethereum precisa delas e como as Árvores Verkle resolvem problemas? O objetivo deste artigo é responder a estas questões para os leitores sem aprofundar demasiado em criptografia e matemática, ajudando aqueles com alguma compreensão da Ethereum a entender rapidamente o conceito das Árvores Verkle.
A tecnologia de consulta verificável é amplamente pesquisada no campo das bases de dados tradicionais, sendo principalmente utilizada para resolver problemas de confiança com bases de dados externas. Em muitos cenários, os proprietários de dados podem optar por não armazenar os dados eles próprios, mas sim confiar suas necessidades de base de dados a um terceiro para fornecer serviços de base de dados (como bases de dados na nuvem). No entanto, como terceiros nem sempre são confiáveis, a credibilidade dos resultados da consulta que eles devolvem aos utilizadores é difícil de garantir. As soluções atuais de consulta verificável para bases 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 utilizada em bases de dados tradicionais, maioritariamente construída sobre estruturas como Árvores de Merkle ou estruturas acumulativas similares. Com a evolução das ferramentas criptográficas, muitos investigadores começaram gradualmente a explorar o uso de técnicas de computação verificável para lidar com questões relacionadas com consultas não confiáveis. Alguns esquemas de computação verificável baseados em protocolos de Prova de Conhecimento Zero, como SNARKs, podem indiretamente suportar consultas verificáveis para bases de dados externas. Estes 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 Verkle Tree 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.
As á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.
As árvores Merkle têm duas características importantes:
Num cenário de consulta verificável comum, existe um provador e um verificador. O provador precisa gerar uma prova e enviá-la ao verificador. Correspondendo à rede Ethereum, um cenário de aplicação típico é onde 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 de bloco é assegurada 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 detém 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 a azul. Assumindo que existam n peças de dados no conjunto, são necessários no máximo cálculos de hash 𝘭𝘰𝘨₂(𝘯) para verificar a correção de qualquer bloco de dados.
Os nós leves do Ethereum apenas sincronizam 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ção, árvore de recibos). Quando um nó leve consulta um nó completo para os dados de um nó folha específico na árvore, o nó completo devolve 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.
Baseando-se na fundação 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 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. Seja 𝑓 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 apontadores para 𝑓 nós filhos, mantém també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 for 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 pesquisa 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 estão completos.
Se uma Árvore de Merkle ingênua é usada para fornecer consultas verificáveis, o processo demorado de regeneração da 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 Radix (árvore compacta de prefixo) e uma Árvore de Merkle, permitindo que ela realize 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 introduzirá algumas definições básicas e fornecerá exemplos para ajudar os leitores a entender rapidamente o MPT.
A estrutura subjacente do Ethereum emprega uma base de dados chave-valor para armazenamento, o que significa que os dados são armazenados na forma de pares chave-valor. O MPT também é decomposto em pares chave-valor para armazenamento. Definimos a estrutura lógica dos nós MPT da seguinte forma:
No contexto da Árvore de Merkle Patricia (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 armazena na realidade 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. 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 chave-valor:
{
‘cab8’: ‘cão’,
‘cabe’: ‘gato’,
‘39’: ‘frango’,
'395': 'pato',
'56f0': 'cavalo'
}
Para encontrar os dados "pato" usando o caminho "395", começaria no hash raiz e seguiria pelos hashes A, C e D para finalmente chegar aos dados alvo. Aqui está um guia passo a passo:
Em cada etapa do caminho, o MPT alavanca 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 através 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 num MPT real, os caminhos e os dados seriam codificados e armazenados num formato específico, e tipos adicionais de nós (como nós de extensão e nós 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. São amplamente utilizados em cenários como provas de conhecimento zero e computação segura entre várias partes. Um esquema de compromisso básico é dividido em duas fases: a fase de compromisso 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 ith. Nos compromissos de vetor, o termo vinculativo significa que ninguém pode abrir a mesma posição para revelar mensagens diferentes.
Um esquema de compromisso vetorial geralmente consiste nos seguintes algoritmos:
Definição: Árvores Verkle = Compromissos de Vetor + Árvores de Merkle.
Por favor, note: Vitalik Buterin, o co-fundador do Ethereum, tem um blogpost especificamente dedicado a apresentar árvores Verkle. Este capítulo acrescenta algum contexto e conhecimento matemático baseado no seu blog. Alguns dos dados e ilustrações no texto seguinte são derivados do seu blog.
As Árvores Verkle (VTs) são caracterizadas por fornecer provas menores em comparação com as Árvores de Merkle. Para dados na escala de bilhões de entradas, uma árvore de Merkle pode gerar provas de cerca de 1KB de tamanho, enquanto as provas de árvore Verkle podem ter menos de 150 bytes. Este tamanho compacto de prova é vantajoso para implementar clientes sem estado”.
A estrutura de uma árvore Verkle é algo semelhante à da Árvore Merkle Patricia (MPT). Aqui está um exemplo da sua estrutura. Os nós de uma árvore Verkle podem ser: (i) Vazios, (ii) Nós folha contendo uma chave e o seu valor correspondente, ou (iii) Nós internos com um número fixo de nós filhos. Este 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 na forma 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 maior largura significa mais nós irmãos, o que poderia levar a tempos de atualização mais longos para o MPT e tamanhos de prova maiores. Por outro lado, para VT, uma largura de árvore mais ampla resulta em provas menores. A única restrição é que, se a largura for muito alta, 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, 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 vetoriais, que permitem provas compactas independentemente da largura da árvore. Esta técnica de compressão permite que as Verkle Trees dimensionem de forma mais eficiente em termos de tamanho de prova. O texto subsequente irá explicar com mais detalhe as funcionalidades mencionadas acima.
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 a vermelho no diagrama abaixo são os nós que precisam ser incluídos na prova retornada.
Nas árvores Verkle, não é necessário fornecer nós irmãos; em vez disso, só precisa de 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 a computação não é um hash convencional, mas usa compromissos vetoriais.
Após substituir a função hash por um algoritmo de geração de compromisso a partir de compromissos vetoriais, o chamado hash raiz agora é um compromisso raiz. Se os dados de algum nó forem adulterados, isso afetará o compromisso raiz.
Como gerar uma prova? Como mostrado no diagrama abaixo, só precisa de fornecer três subprovas, cada uma das quais pode provar que um nó no caminho existe numa posição específica dentro do 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 para o usuário são “compromissos KZG” e “compromissos polinomiais estilo à prova de balas (o primeiro tem um tamanho de compromisso de 48 bytes, enquanto o último tem 32 bytes).
Se utilizar compromissos e provas KZG, a prova para cada nó intermédio é apenas 96 bytes, o que representa uma poupança de espaço quase três vezes superior a 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.
Comparando 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 a “comprovação da relação 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 cobrirá a parte criptográfica da prova em princípio. Para o método específico, consulteesquema 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ómios, também conhecida como redução de grau de um polinómio?
Supondo que conhecemos um polinómio 𝑃(𝑥) e o seu valor 𝑦₁ em 𝑥₁, ou seja, 𝑃(𝑥₁) = 𝑦₁.
Agora, considere um novo polinómio 𝑃(𝑥) - 𝑦₁ , que tem um valor de zero em (𝑥 = 𝑥₁) , porque 𝑃(𝑥₁) - 𝑦₁ =𝑦₁ - 𝑦₁ = 0.
Portanto, o polinómio 𝑃(𝑥) - 𝑦₁ tem uma raiz em 𝑥 = 𝑥₁, o que significa que (𝑥 - 𝑥₁) é um factor de 𝑃(𝑥) - 𝑦₁.
Em outras palavras, podemos expressá-lo na seguinte forma: [ 𝑃(𝑥) - 𝑦₁ = (𝑥 - 𝑥₁ )𝑄(𝑥)]
𝑄(𝑥) é outro polinómio cujo grau é um a menos do que o de 𝑃(𝑥). Isto deve-se a (𝑥 -𝑥₁ ) ser um fator de primeiro grau, o que reduz o grau total do polinómio.
Como usar KZG para provar um único valor num vetor?
Tomemos o compromisso KZG10 como exemplo, para o polinómio 𝑃(𝑥), suponhamos que o seu compromisso polinomial é [ 𝑃(𝑠) ]₁ .
Como explicado anteriormente, para o polinómio 𝑃(𝑥), se 𝑃(𝑧) = 𝑦, então temos 𝑄(𝑥) = (𝑃(𝑥) - 𝑦)/(𝑥 - 𝑧)
Agora, o provador pode gerar uma prova de que o polinómio 𝑃(𝑥) satisfaz 𝑃(𝑧) = 𝑦 : calcular [ 𝑄(𝑠) ]₁ e enviá-lo ao verificador.
O verificador precisa verificar 𝑒( [ 𝑄(𝑠) ]₁, [ 𝑠 - 𝑧]₂ ) = 𝑒( [ 𝑃(𝑠) ]₁- [𝑦]₁, [1]₂) .
Como usar KZG para provar múltiplos valores num 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 a partir da perspetiva do algoritmo de compromisso 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 original e quociente para cada polinómio 𝑓ᵢ(𝑥) , resultando num total de 𝟐﹡𝑚 compromissos KZG. O verificador envia todos estes 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 forma de comprimir várias provas de compromisso.
Fusão das Provas
O provador envia a prova [ 𝑞( 𝑠 )]₁ ao 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 da prova na árvore Verkle, o objeto de dados verificável enviado ao verificador inclui o seguinte:
Note que 𝑥ᵢ e 𝑦ᵢ não precisam ser fornecidos explicitamente; todos 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 com largura de 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, então o tamanho do compromisso seria de 32 bytes.
As seguintes são as palavras originais do blog do Vitalik, adicionamos um parágrafo no final como suplemento.
As árvores Verkle são uma atualização poderosa para 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 hexarias que o Ethereum usa hoje (!!).
Eles exigem uma criptografia mais complexa para implementar, mas apresentam a oportunidade de grandes ganhos em escalabilidade. A médio prazo, as SNARKs podem melhorar ainda mais as coisas: podemos SNARK o verificador de prova Verkle já eficiente para reduzir o tamanho da testemunha para próximo de zero, ou voltar a provas SNARKed de Merkle se/quando as SNARKs ficarem muito melhores (por exemplo, através de GKR, ou funções de hash muito amigáveis para SNARK, ou ASICs). Mais adiante, o surgimento da computação quântica forçará uma mudança para provas de Merkle STARKed com hashes, pois torna as homomorfismos lineares em que as árvores Verkle dependem inseguras. Mas, por enquanto, eles nos dão os mesmos ganhos de escalabilidade que obteríamos com tecnologias mais avançadas, e já temos todas as ferramentas de que precisamos para implementá-las de forma eficiente.
Atualmente, muitos clientes Ethereum 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. É provável que seja implementada 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 mínimas de conhecimento de divulgação[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. Atas 16. Springer, 2013: 55-72.