Parfin Insights

O Guia do Ethereum: Compreendendo as Estruturas do Ethereum

Data: 22/08/2023

O Ethereum é uma plataforma blockchain conhecida por sua capacidade de suportar contratos inteligentes e aplicações descentralizadas. Essa funcionalidade é alcançada por meio de várias estruturas de dados importantes que armazenam informações cruciais na rede.


Neste artigo, vamos explorar quatro dessas estruturas: o World State Trie, o Transaction Trie, as Receipts e o Account Storage Trie.

World State Trie

O World State Trie, também conhecido como Trie de Estado Global, é uma das estruturas de dados mais importantes no Ethereum. Ele atua como uma espécie de "fotografia" do estado atual de toda a rede. O trie armazena um mapeamento entre endereços de contas (EOAs e contratos inteligentes) e seus estados de conta correspondentes. Esses estados de conta incluem informações como saldo, nonce, código do contrato e o hash da trie de armazenamento associada.

Em termos simples, o World State Trie representa a situação atual de todos os ativos e informações relevantes na rede Ethereum. Cada bloco contém uma referência ao estado global atual, que permite que os nós da rede verifiquem as informações e validem transações.

                                                   

Transaction Trie

A Transaction Trie, ou Trie de Transações, é uma estrutura de dados que armazena todas as transações incluídas em um determinado bloco. Cada bloco tem sua própria Transaction Trie, que é usada para armazenar informações relacionadas às transações e sua ordem dentro do bloco.

As transações são agrupadas em blocos antes de serem adicionadas à Transaction Trie. Isso significa que cada bloco contém um conjunto de transações e, juntas, formam uma sequência de blocos conhecida como blockchain. O Transaction Trie é linkado com o World State Trie e outras tries por meio dos hashes dos blocos, garantindo a integridade e a imutabilidade dos dados.

                                  

Receipts

Receipts (Recibos) são uma estrutura de dados usada para registrar informações sobre a execução de cada transação em um bloco específico. Cada transação no bloco gera um recibo que contém detalhes sobre a execução da transação, incluindo logs de eventos, status de execução (bem-sucedido ou não) e informações adicionais relevantes.

Os recibos são essenciais para a contabilidade e a rastreabilidade das operações na rede Ethereum. Eles permitem que os desenvolvedores e usuários obtenham informações detalhadas sobre as transações e verifiquem o estado resultante após a execução.

Account Storage Trie

A Account Storage Trie, ou Trie de Armazenamento de Contas, é uma estrutura de dados usada para armazenar os dados associados a cada conta no Ethereum. Cada conta (seja um EOA ou um contrato inteligente) tem sua própria trie de armazenamento.

Essa trie é responsável por armazenar os valores-chave relacionados a uma conta específica. Por exemplo, as informações de saldo, nonce, código do contrato e outros dados relevantes são armazenados nessa estrutura.

É importante notar que, embora o banco de dados do World State Trie seja imutável e reflita o estado global da rede, o banco de dados de Account Storage Trie é mutável a cada bloco. Isso ocorre porque a execução de transações em cada bloco pode alterar os valores armazenados nas contas, refletindo assim as mudanças no estado das contas após cada bloco.

                          

Como uma transação altera os State Tries

Quando uma transação é criada e enviada na rede Ethereum, ela passa por um processo complexo de validação e execução que afeta os State Tries discutidos acima.

  1. Validação: Primeiro, a transação é verificada quanto à sua validade. Isso inclui a verificação de assinaturas criptográficas para garantir que a transação seja enviada pelo proprietário legítimo da conta e que há saldo suficiente para realizar a operação.

  2. Execução: Após a validação, a transação é executada pelos mineiros ou validadores. A execução envolve a atualização dos dados da Account Storage Trie e do World State Trie. Se a transação envolve a criação de um novo contrato inteligente, o código desse contrato é registrado na Account Storage Trie.

  3. Atualização dos Receipts e Transaction Trie: Durante a execução, os detalhes da transação são registrados nos Receipts, que fornecem informações sobre a operação executada, logs de eventos e outros dados relevantes. A transação também é adicionada à Transaction Trie do bloco, garantindo sua ordenação correta.

  4. Atualização do World State Trie: Após a execução de todas as transações em um bloco, o World State Trie é atualizado para refletir o novo estado global da rede, levando em conta todas as mudanças resultantes das transações executadas.

Ao final desse processo, o bloco é adicionado à blockchain, e as alterações nos State Tries se tornam parte do histórico imutável da rede Ethereum. Através desse mecanismo, o Ethereum mantém um registro seguro e confiável de todas as atividades realizadas na plataforma, permitindo a criação de aplicativos descentralizados e contratos inteligentes que operam em um ambiente confiável e transparente.

No cerne da funcionalidade do Ethereum encontra-se a Modified Merkle Patricia Trie, uma estrutura de dados que desempenha um papel crucial no armazenamento e acesso eficiente de informações na blockchain Ethereum.

O que é uma Trie?

Uma trie é uma estrutura de dados semelhante a uma árvore que permite o armazenamento e recuperação eficiente de pares de chave-valor. O termo "trie" vem da palavra "retrieval" (recuperação), pois ela é excelente em localizar rapidamente os prefixos comuns nas chaves. Cada nó em uma trie possui várias ramificações, e o caminho percorrido da raiz até um nó folha específico representa a chave associada a esse nó.

                               

A Evolução: Modified Merkle Patricia Trie

No Ethereum, a trie tradicional foi aprimorada e adaptada para atender aos requisitos específicos da plataforma blockchain. O resultado foi o desenvolvimento da "Modified Merkle Patricia Trie" (MPT), que se tornou a base para o armazenamento de dados no Ethereum. Várias tries no Ethereum, como a trie do estado global (world state trie), a trie de estado da conta (Account State trie), a trie de recibos (Receipt trie) e a trie de transações (Transaction trie), são implementações da MPT.

Cada uma dessas tries representa uma MPT separada com seu prefixo exclusivo, permitindo a organização e recuperação eficiente de dados relacionados a aspectos específicos da blockchain Ethereum.

Anatomia de uma Árvore de Modified Merkle Patricia Trie

                           

Para compreender o funcionamento interno da MPT, vamos examinar mais de perto sua estrutura. Cada nó na trie possui uma chave e um valor correspondente. A chave é o hash do nó, e o valor é o conteúdo armazenado dentro do nó. O estado do Ethereum, composto por pares de chave-valor, é representado como caminhos na MPT.

A MPT utiliza nibbles como a unidade para distinguir os valores das chaves. Cada nó na trie pode ter até 16 ramificações, permitindo uma representação compacta e o uso eficiente de memória.

Existem três tipos de nós na MPT:

  1. Nós de Ramificação (Branch Nodes): Um nó de ramificação contém uma matriz de 17 elementos, composta por um valor de nó e 16 ramificações. Esse tipo de nó é o mecanismo principal para bifurcar e navegar na trie.

  2. Nós Folha (Leaf Nodes): Um nó folha representa um par de chave-valor. O valor é o conteúdo do nó da MPT, e a chave é o hash do nó. Os nós folha são usados para armazenar dados específicos de chave-valor.

  3. Nós de Extensão (Extension Nodes): Os nós de extensão servem como nós otimizados na MPT. Eles são usados quando um nó de ramificação tem apenas um nó filho. Em vez de duplicar o caminho para cada ramificação, a MPT comprime-o em um nó de extensão, que contém o caminho e o hash do filho.

Distinguindo Nós Folha e Nós de Extensão

Na MPT, é essencial distinguir entre nós folha e nós de extensão. Para isso, um prefixo é adicionado ao caminho de cada nó. O prefixo é representado por um byte e depende do número de nibbles no caminho.

  • Se o nó é um nó folha e o caminho tem um número par de nibbles, é adicionado um prefixo de 0x20.

  • Se o caminho tem um número ímpar de nibbles, é adicionado um prefixo de 0x3 para nós folha.

  • Se o nó é um nó de extensão e o caminho tem um número par de nibbles, é adicionado um prefixo de 0x00.

  • Se o caminho tem um número ímpar de nibbles, é adicionado um prefixo de 0x1 para nós de extensão.

Essa mecanismo de adição de prefixos garante que os nós folha e nós de extensão sejam distinguidos de forma eficiente, tornando a representação dos caminhos consistente e confiável.

Atualizando a Trie

A atualização da trie segue algumas regras:

  • Ao encontrar um EmptyNode, ele é substituído por um novo LeafNode com o caminho restante da chave.

  • Ao encontrar um LeafNode, ele é convertido em um ExtensionNode, e um novo BranchNode é criado com dois ramos, apontando para o ExtensionNode e um novo LeafNode.

  • Ao encontrar um ExtensionNode, ele é convertido em outro ExtensionNode com um caminho mais curto, e um novo BranchNode é criado, apontando para o novo ExtensionNode.

Quando uma trie é criada, o nó raiz aponta para um EmptyNode.

                         

Adicionando a 1ª transação

Ao adicionar o par chave-valor da 1ª transação, um LeafNode é criado com os dados da transação armazenados nele. E o nó raiz é atualizado para apontar para esse LeafNode.

                        

Adicionando a 2ª transação

Ao adicionar a 2ª transação, o LeafNode na raiz será transformado em um BranchNode com duas ramificações apontando para os 2 LeafNodes. O LeafNode do lado direito contém os nibbles restantes (nibbles são um único caractere hexadecimal) - 1, e o valor para a 2ª transação.

E agora o nó raiz está apontando para o novo BranchNode.

                           

Adicionando a 3ª transação

Ao adicionar a 3ª transação, o LeafNode do lado esquerdo se transformará em um BranchNode, semelhante ao processo de adicionar a 2ª transação. Embora o nó raiz não tenha mudado, o hash raiz foi alterado, pois sua ramificação 0 está apontando para um nó diferente com hashes diferentes.

                               

Adicionando a 4ª transação

Adicionar a última transação é semelhante a adicionar a 3ª transação. Agora podemos verificar se o hash raiz é idêntico ao transactionRoot incluído no bloco.

                                  

Obtendo a Prova de Merkle para uma Transação

A Prova de Merkle para uma determinada transação é simplesmente o caminho até o LeafNode que armazena o valor da transação. Ao verificar a prova, é possível percorrer a trie a partir do hash da raiz, decodificar os nós, verificar os nibbles e repetir o processo até encontrar o nó que corresponde aos nibbles restantes. Se encontrado, o valor associado à chave está correto; se não encontrado, a prova de Merkle é inválida.

Solicite uma demo

A excelência do seu negócio merece o suporte único dos nossos especialistas

Qual é o seu objetivo?

Qual solução da Parfin desperta seu interesse?

Qual é sua estimativa de implementação?

Não encontrou o que procurava?

Selecione o tipo de sua instituição: