Baixar
Fechar menu -

Rumo a uma maior escalabilidade onchain com a Unitrie

A RSK foi criada em 2015 como uma sidechain do Bitcoin compatível com Ethereum. Em 2016, quando a sidechain RSK ainda estava em desenvolvimento, decidimos melhorar e simplificar seu design mediante a substituição de um dos principais componentes da Ethereum: a trie de contas, também chamada de trie de “estado mundial” no documento de especificação técnica da Ethereum. A trie de estado mundial é o principal banco de dados das blockchains tipo Ethereum, e a estrutura de dados sobre a qual se apoia é chamada de “Trie Patricia modificada segura”. Projetamos uma estrutura de dados de estado de substituição que evoluiu para o que hoje chamamos de Unitrie.

Sergio Lerner (RSK Labs) apresentando a Unitrie na laBitConf (2016)

Algumas das principais propriedades da Unitrie (original) são as seguintes:

  1. A árvore de base 16 é substituída por uma de base 2 (binária).
  2. Valores de comprimento arbitrário podem ser armazenados nas células de armazenamento.
  3. Todas as tries são combinadas e mesclam células de armazenamento de contratos com células de contas em uma única estrutura de dados maior chamada “Unitrie”.
  4. Os elos são aumentados com registros de data e hora da última atualização (campo “lastUpdateTimestamp”), como resultado, a Unitrie suporta aluguel de armazenamento e hibernação automática de nós.
  5. Os prefixos são armazenados no nó primário, para cada um de seus nós secundários. Isso permite eliminar nós folha por meio de hibernação, a fim de maximizar o descarte de dados. Além disso, evita o efeito colateral de leitura de outros nós no processamento de transações paralelas.
  6. As chaves são protegidas por um prefixo hash de 10 bytes (80 bits) com a finalidade de evitar o desequilíbrio da trie, mas ainda contêm a chave completa (pré-imagem de hash) após o prefixo hasheado.
  7. Os nós armazenam o tamanho de sua carga útil.
  8. Os nós armazenam a quantidade de bytes que são consumidos por sua subárvore.
  9. Se um nó for muito pequeno para ser armazenado de forma independente no banco de dados, ele será incorporado em seu nó primário. Isso economiza o resumo hash de 32 bytes usado para referenciar o nó.

Alguns benefícios da Unitrie são evidentes, mas outros são sutis. Aqui está uma lista das principais melhorias:

  • Simplificação do design geral.
  • Redução da complexidade das implementações e, portanto, redução do risco de erros de consenso.
  • Simplificação do design dos clientes Lightweight (leves).
  • Redução do tempo de sincronização de estado (também conhecida como fast-sync/warp-sync), ao torná-la mais paralelizável e resiliente a provedores de estado maliciosos.
  • Possibilidade de provas de fraude mais simples para clientes e pontes SPV.
  • Possibilidade de coleta mais simples do lixo de estado.
  • Possibilidade de alugar contratos por célula de armazenamento.
  • Possibilidade de hibernação e reativação por célula por armazenamento.
  • Possibilidade de execução paralela com detecção de colisões por célula de armazenamento.
  • Possibilidade de fazer consultas EXTCODESIZE rápidas, sem a necessidade de recuperar os dados do código.

O design da Unitrie foi proposto pela RSK Labs para a RSK Blockchain e apresentado brevemente na laBitConf, realizada nos dias 4 e 5 de novembro de 2016. No entanto, nossa principal prioridade na época, quando a mainnet RSK ainda não havia sido lançada, era manter uma maior compatibilidade com as ferramentas de desenvolvimento da Ethereum, por isso decidimos adiar a implementação da Unitrie e só implementamos duas mudanças críticas em sua estrutura de dados: o uso de base 2 no lugar de base 16, e o armazenamento de valores de comprimento arbitrários. O uso de base 2 permitiria a migração futura para a Unitrie mediante uma conversão dinâmica da trie, em vez de uma migração completa do banco de dados. Essa acabou por ser uma sábia decisão, já que agora estamos testando a migração rápida de toda a estrutura de árvore dinamicamente, preservando a maioria das partes estruturais.

No final de 2017, ficamos surpresos ao ver Vitalik propondo uma mudança semelhante para Ethereum nos fóruns da Ethereum. Ele também destacou os benefícios de se contar com uma árvore de estado combinada. Isso respaldou nossa tese inicial de que a unificação das tries era um projeto muito melhor.

Proposta de Vitalik para uma trie de estado combinada (2017)

Chegou a hora

Em janeiro de 2019, a RSK blockchain fez seu primeiro aniversário, que marcou um ano com 100% do tempo em atividade, então decidimos renovar nossos esforços de impulsionar a adoção da estrutura de dados Unitrie em uma atualização de rede posterior. Editamos e aperfeiçoamos nossas RSKIPs antigas e criamos novas RSKIPs e implementações de referência. Este artigo faz parte de nossos esforços para comunicar como a comunidade RSK se beneficiará com essa mudança proposta. Atualizamos a RSKIP16 e adicionamos RSKIP107, RSKIP108 e RSKIP109. RSKIP107 descreve como os nós trie são compactados quando armazenados. RSKIP108 descreve como os endereços de contas e os endereços de células de armazenamento são atribuídos às chaves trie. RSKIP109 redefine os custos de gravação de células de armazenamento para incentivar o uso de endereços de armazenamento mais curtos. Também implementamos e testamos todas juntas e observamos melhorias notáveis no desempenho dos nós e no consumo de memória, desde as atualizações de estado até a sincronização. No entanto, nem tudo correu bem durante os testes. Por exemplo, decidimos excluir da proposta a ideia de mover os prefixos dos nós da trie para os nós primários. O motivo foi que essa mudança dificulta a conversão rápida entre tries novas e antigas, tornando-a dependente de semelhanças nas estruturas das árvores.

Para reduzir o risco associado aos hard forks, acreditamos que a melhor estratégia é dividir as mudanças em duas atualizações de rede consecutivas. A primeira, no segundo trimestre de 2019, incluiria Unitrie, chaves protegidas por prefixo, cache de tamanho de carga útil, cache de tamanhos de árvore e compactação de nós em disco. A segunda, no quarto trimestre de 2019, incluiria os registros de data e hora da última atualização do aluguel de armazenamento. Estamos adiando os recursos relacionados ao aluguel de armazenamento porque a RSKIP relativa a esse tema ainda não é definitiva e porque as mudanças na segunda atualização de rede afetam apenas os novos nós de trie criados (não exige a migração da trie), enquanto a primeira atualização exige a migração completa da trie.

Uma atualização de rede única

A combinação total de nós de contas e de armazenamento em uma única árvore só pode ser realizada por meio de um hard fork, o que significa que a maioria dos mineradores precisa fazer a atualização para suportar essa mudança, e todos os nós completos também precisam ser atualizados a fim de permanecerem sincronizados. No entanto, a atualização da Unitrie não implica nenhuma modificação importante na economia da plataforma. Uma pequena redução no custo de armazenamento será aplicada, o que se deve a uma melhor correspondência entre o custo real de armazenamento e os valores cobrados. Essa mudança beneficiará todos os atores da comunidade. Além disso, as alterações não afetam a segurança ou a privacidade da plataforma. Note que a maioria das ferramentas de desenvolvimento e carteiras não acessam de maneira direta os dados internos do estado mundial, portanto não são afetadas por esse hard fork.

A desvantagem do mecanismo de atualização é que o antigo banco de dados de estado de nó completo não será mais compatível com o novo banco de dados. Criar um nó completo que seja compatível com a antiga trie e também com a nova é uma tarefa difícil, com poucos benefícios. A boa notícia é que, devido às muitas melhorias de desempenho, a nova sincronização completa durará apenas uma fração do tempo que durava anteriormente. Além disso, testamos a migração do banco de dados de estado para o novo formato na inicialização dos nós, de modo que os nós pudessem manter um tempo de atividade quase ininterrupto após a atualização do software.

A Unitrie

A Unitrie combina informações de contas com as células de armazenamento de todos os contratos. Ela armazena células de armazenamento de contratos como folhas de uma subárvore com raiz no nó correspondente ao endereço de armazenamento do contrato. Também divide as informações de contrato em vários subnós distintos da árvore. O diagrama simplificado a seguir mostra uma conta (controlada por ECDSA) que não possui nenhum nó secundário, um contrato que possui um nó secundário que armazena o código do contrato, e uma subárvore secundária que contém as células de armazenamento em si.

Exemplo de Unitrie de um estado de blockchain

A combinação de contas e armazenamento de contratos não é a única diferença, o mapeamento de chaves também muda. Vamos recapitular como funciona a trie de contas da Ethereum: para proteger a trie, utiliza-se o resumo hash do endereço da conta como a chave para recuperar um valor. Os nós da trie não são classificados por endereços de conta, mas por seus resumos hash. Essa transformação importante é executada para evitar que um invasor efetue um ataque de spam contra a estrutura de dados com valores que compartilham prefixos de chave crescentes que degenerariam a árvore até transformá-la em uma cadeia longa. Um ataque desse tipo poderia forçar um nó completo a executar determinadas consultas com maior lentidão ou a aumentar o tamanho de certas provas de inclusão da trie. Na Unitrie, as chaves são construídas a partir de um prefixo de resumo hash de 80 bits, seguido pelo endereço simples completo da conta. Apenas 80 bits são usados para distribuir as chaves pela trie e mantê-la probabilisticamente equilibrada. Dado que os efeitos do ataque de degeneração da árvore são mínimos, 80 bits são mais do que suficientes para desestimulá-lo. Tal ataque exigiria a criação de um hardware especial de forçamento de prefixo hash baseado em ASIC, que é muito semelhante a um minerador de prova de trabalho, e a fabricação de milhões dessas caixas de “mineração”. Se imaginarmos que as máquinas Bitcoin de última geração poderiam executar uma pesquisa arbitrária de pré-imagem de prefixos de 80 bits, o invasor precisaria gastar cerca de US$ 6 milhões em eletricidade para encontrar colisões nas 80 diferentes posições de 80 bits com a finalidade de degenerar ligeiramente a trie. No entanto, o efeito no tempo de processamento do bloco seria insignificante (devido aos caches), e uma prova de inclusão para uma conta desequilibrada aumentaria de tamanho em apenas 2 Kbytes.

Uma vantagem desse novo mapeamento é que ele preserva o endereço da conta e os endereços das células de armazenamento no estado, o que permite que muitos aplicativos de coleta de dados apresentem informações significativas ao usuário sem a necessidade de indexar toda a blockchain. O diagrama a seguir descreve a transformação dos endereços de conta e de armazenamento em uma chave de trie:

Transformação dos endereços de conta e de armazenamento em uma chave de trie

Para apresentar o panorama completo, mostramos como cada tipo de dado é mapeado na Unitrie:

Chave Valor Descrição
0x00

SHA3(account_addr)[0:9] account_addr

Rlp (nonce, quantidade, indicadores) estado de conta
0x00

SHA3(account_addr)[0:9] account_addr

0x80

matriz de bytes código de conta
0x00

SHA3(account_addr)[0:9] account_addr

0x00

0x00 espaço reservado para isolar a árvore de armazenamento
0x00

SHA3(account_addr)[0:9] account_addr

0x00

SHA3(storage_address)[0..9]

trimmed_storage_address

matriz de bytes valor na célula de armazenamento

O primeiro byte zero é usado para armazenar essa árvore em um espaço de nomes especial. Isso permite que melhorias futuras utilizem outros espaços de nomes sem que haja risco de colisão. Algumas das possíveis melhorias futuras que poderão consumir seus próprios espaços de nomes são:

  • armazenar um nó especial que se expanda para uma árvore (ou floresta) de todos os hashes de bloco anteriores para habilitar as provas de provas de trabalho (NiPowPow) e as listas de ignorados;
  • fazer referência a endereços de contas com chaves de maior comprimento (ou seja, 256 bits) para maior segurança;
  • fazer referência a endereços de contas usando endereços com hash duplo, conforme definido pela RSKIP32.

Existem muitas diferenças entre a Unitrie da RSKIP16 e a proposta de Vitalik. Uma diferença é que a Unitrie não armazena o nonce e a quantidade em nós diferentes, mas os mantém juntos. Há várias razões para isso:

  • A serialização e desserialização desses dois campos levam pouco tempo, portanto, uma divisão posterior provoca perda de eficiência devido ao aumento dos acessos ao disco para recuperar o estado da conta.
  • É preferível ter alguns dados no endereço específico do contrato para poder acompanhar as alterações do contrato no futuro.
  • As contas podem ser usadas para enviar “spam” à trie, por isso é importante reduzir o espaço consumido pelas contas.

O panorama da Unitrie RSKIP

A Unitrie está definida por 9 RSKIPs (Propostas de melhorias da RSK). Cada RSKIP descreve um componente específico da Unitrie: estrutura, armazenamento, mapeamento de chaves, aluguel de armazenamento, hibernação e custos de gás. O diagrama a seguir descreve essa separação:

RSKIPs relacionadas à Unitrie

Na primeira atualização de rede, apenas 4 RSKIPs serão implementadas, sendo as demais adiadas para a atualização de rede subsequente. Isso garante a minimização dos riscos de migração.

O que ficou de fora da Unitrie

Durante as discussões originais sobre a Unitrie, concluímos que dividir o prefixo dos dados do nó em dois nós diferentes ajudaria a manter a imutabilidade total dos ramos intactos da árvore e permitiria uma paralelização mais detalhada das atualizações da árvore. Chamamos esse esquema de trie PDB porque os nós podem ser de um de três tipos disjuntos: prefixo, dados ou ramo (branch). Como a mudança para uma árvore PDB requer mudanças estruturais profundas, foi deixada de fora da proposta da Unitrie. No entanto, a árvore PDB pode ser um tema para futuras pesquisas.

Exemplo de uma árvore PDB usada para armazenar o estado da blockchain

Agora vamos discutir com mais detalhes cada uma das vantagens da Unitrie da RSK.

Provas de associação mais curtas

Ao usar uma trie binária, em vez de uma trie de base 16, as provas de associação para as contas da trie da RSK são as mais breves possíveis, enquanto o tempo necessário para validar suas provas de associação está próximo do ideal. Isso permite que os nós leves descentralizados, executados em telefones celulares, consumam menos largura de banda e menos energia. No diagrama de exemplo a seguir, a trie de base 16 requer 30 ponteiros (anéis) e 3 nós (círculos) para provar a existência de um nó de destino (círculo azul). A trie de base 2 requer apenas 8 ponteiros e 8 nós. Quando transmitidos, os nós não exigem a transmissão de referências primárias, porque suas referências podem ser calculadas dinamicamente e, por conseguinte, a prova da trie binária requer 26% do espaço da trie de base 16.

Comparação entre as provas de associação de uma trie de base 16 e uma de base 2

Redução do tamanho do estado por meio da compactação de nós de contas

As contas que estão na Unitrie não precisam armazenar o resumo hash da raiz da trie de “armazenamento” nem o resumo hash do código, o que significa que quase 60% dos dados da conta são removidos do estado. Por exemplo, uma conta que armazena 1 RBTC consome cerca de 38 bytes, em vez dos 104 bytes consumidos na Ethereum. O diagrama a seguir mostra a economia de espaço aproximada resultante da remoção dos campos desnecessários.

Compactação de nós de conta por remoção de campos desnecessários

Redução do tamanho do estado por meio da incorporação de nós pequenos

No caso de nós secundários cujo tamanho é menor que ~44 bytes (valor exato a ser determinado), a Unitrie fornece a possibilidade de incorporá-los diretamente em nós primários. Esse recurso é descrito na RSKIP107.  Como a maioria das contas acaba tendo nós com tamanhos que variam de 31 a 41 bytes, isso significa que a maioria das contas será incorporada em nós primários. Isso reduz a sobrecarga da conta em 62%. A redução do tamanho das contas alcançada pela incorporação de nós em combinação com o encurtamento dos registros de contas chega a 81% e não apenas reduz o tempo de sincronização e os requisitos de recursos de um nó completo, mas também reduz os riscos de um ataque DoS por envio de spam ao estado com criações de contas. O diagrama de exemplo a seguir mostra como um nó que possui dois nós secundários na trie Ethereum é convertido em um único nó com seu nó secundário incorporado na Unitrie.

Incorporação de dois nós pequenos em seu nó primário

Redução do tamanho do estado e menor custo de gás mediante a compactação de chaves de células de armazenamento

Nossa RSKIP108 descreve como as células de armazenamento podem ser compactadas quando as chaves de armazenamento possuem prefixos longos de zero. As células que possuem endereços de um só byte e armazenam um único byte podem ser compactadas até alcançar 10% do tamanho não compactado, pois seu tamanho pequeno também permite a incorporação de nós. Para incentivar os usuários a usarem o armazenamento compactado, a RSKIP109  atualiza o custo das operações de gravação no armazenamento do contrato. Por exemplo, armazenar 0x01 no endereço 0x00 consumiria apenas 5460 unidades de gás, em vez de 20K, como na Ethereum. O diagrama a seguir descreve as diferentes chaves usadas na Ethereum e na Unitrie, para o endereço da célula de armazenamento 0x01.

Exemplo de compactação de chave de armazenamento

Melhor escalabilidade quando combinada com o processamento paralelo de transações

Nossa RSKIP04 propõe o processamento paralelo de transações com a finalidade de reduzir o tempo de processamento dos blocos. Ao reduzirmos o tempo de processamento dos blocos, podemos propagar os blocos mais rapidamente e melhorar o consenso. Isso também significa que podemos colocar mais transações nos blocos sem atrasar sua propagação. Em geral, a maior latência de propagação de blocos favorece os grandes pools de mineração em comparação aos menores, portanto, saber que estamos escalando sem reduzir a descentralização é um fato tranquilizador. No entanto, a blockchain só pode se beneficiar do processamento paralelo de transações se estas puderem ser divididas em conjuntos não sobrepostos em termos de acesso ao estados do contrato. Se todas as transações chamarem um único contrato de token, esse contrato forçará a serialização das transações e se tornará um gargalo. Uma solução, especificada na RSKIP59, é projetar os contratos de modo que as células de armazenamento de contratos sejam transferidas para os subcontratos, criando relações primário-secundário. Em seguida, os saldos de token de diferentes usuários são armazenados em contratos diferentes. Ainda assim, essa solução exige reprojetar e reimplementar os contratos para forçar o uso de padrões de design específicos que possibilitem a escalabilidade. No entanto, a Unitrie pode resolver o problema sem o obstáculo associado ao uso de novos padrões. A Unitrie permite a detecção simplificada de acessos simultâneos a células de armazenamento, em vez de apenas detectar acessos simultâneos a contratos completos. Isso significa que, desde que duas transações não gravem as mesmas células de armazenamento (ou uma delas leia uma célula que a outra tenha escrito), ambas podem ser executadas simultaneamente. Por exemplo, os contratos ERC20 normalmente alteram apenas as células relacionadas às contas de origem e destino, portanto, esses contratos obteriam capacidade de paralelização imediata com detecção em nível de célula. Embora a mesma funcionalidade também possa ser obtida sem a Unitrie, esta simplifica enormemente o algoritmo de detecção de colisões de gravação. Como exemplo, o diagrama a seguir descreve duas threads que processam transações. A primeira thread modifica uma célula de um contrato C (indicado pela seta violeta), que não é afetado pela thread 2. A thread 2, por sua vez, modifica duas outras células do mesmo contrato, o que não afeta a célula modificada pela thread 1.

Duas threads de execução modificando o mesmo armazenamento de contrato

Melhor imparcialidade quando combinada com aluguel de armazenamento

Uma consequência do design da Ethereum é que ele permite a arbitragem de gás, mediante a qual os usuários podem comprar antecipadamente e ocupar células de armazenamento sem armazenar nenhum dado útil, apenas para esvaziá-las posteriormente com a finalidade de recuperar parte do gás usado para comprá-las e vender esse gás a terceiros. Outra consequência indesejada é que a Ethereum exige um alto pagamento adiantado pelo uso de novas células de armazenamento, uma vez que esse pagamento é usado principalmente para o armazenamento perpétuo e a garantia de execução do par chave/valor.

O aluguel de armazenamento mitiga os dois problemas. A forma mais discutida e aceita de aluguel de armazenamento exige que os usuários que interagem com um contrato paguem uma taxa proporcional ao tempo que tal contrato esteve inativo e proporcional ao espaço de memória consumido pelo contrato durante o tempo de inatividade. A RSKIP61 propõe o uso de aluguel de armazenamento para evitar algumas consequências indesejáveis do design original da EVM que afetam a imparcialidade da plataforma. Embora proporcione equidade probabilística, é um método grosseiro e não funciona bem em casos extremos. Um contrato de propriedade coletiva que armazena milhões de pares chave/valor, mas que raramente é utilizado, colocará uma carga excessiva de aluguel de armazenamento no primeiro usuário que o utilizar após um longo período de inatividade. A Unitrie simplifica a tarefa de rastrear as datas e os horários de acesso mais recentes de células de armazenamento individuais, de modo que o aluguel de armazenamento se torne mais preciso, permitindo que um contrato pague apenas o aluguel das células envolvidas na execução de uma chamada. Essa simplificação, especificada na RSKIP113, é consequência do tratamento igualitário de todos os nós, a fim de que contas, códigos e células de armazenamento possam receber aluguel quando forem acessados.

Aumento da integridade com coleta simplificada de lixo de estado

A Coleta de Lixo do Estado é a remoção de dados de estado antigos que nunca serão referenciados novamente em condições normais porque foram sobrescritos. Em eventos excepcionais, como uma reorganização significativa da blockchain, esses dados podem ser recalculados mediante a re-execução dos blocos antigos a partir de um ponto de controle de estado previamente calculado. No entanto, a coleta de lixo na Ethereum não é trivial, porque deve ser aplicada a muitos bancos de dados (ou tries) separados, uma para cada contrato ativo. O uso da Unitrie faz com que a coleta de lixo seja aplicada a um único banco de dados, reduzindo os riscos de interrupções de thread que poderiam alterar o banco de dados durante a coleta de lixo e deixá-lo em um estado incoerente.

Sincronização de estado mais rápida e simples

Existem muitos aplicativos que precisam consultar o estado da blockchain em uma determinada altura de bloco, desde carteiras leves a pontes de blockchain. A estrutura binária da Unitrie fornece um consumo mínimo de espaço e um desempenho máximo para recuperar e provar a associação dos dados no estado. Também reduz a complexidade dos comandos de rede usados na transmissão de informações de estado.

No entanto, o mais importante é que a Untrie permite o download rápido e paralelo de informações de estado para executar os comandos de sincronização “Fast Sync” ou “Warp Sync”. Os nós podem recuperar informações de estado de maneira mais eficiente se todas as informações forem armazenadas em uma única trie. Como a Unitrie armazena a quantidade de bytes consumidos pela subárvore com raiz em cada nó, a estrutura de dados da Unitrie suporta consultas de intervalo de tamanho. Os pares podem usar essa funcionalidade para solicitar “pacotes” de um tamanho específico, a partir de qualquer deslocamento de bytes. Consequentemente, as solicitações podem ser paralelizadas de uma maneira bem equilibrada. Por exemplo, um nó pode coletar informações de estado de 10 nós e solicitar o intervalo de bytes de 0 a 100K para o primeiro, de 100 a 200K para o segundo e assim por diante. Isso permite a criação de um modo de sincronização que combina as vantagens da sincronização rápida (validação imediata dos dados retornados) com as vantagens da sincronização warp (recuperação simultânea de grandes blocos de dados de várias origens). O diagrama a seguir mostra um exemplo de Unitrie exibindo os tamanhos de subárvores de nós. A trie pode ser dividida em três blocos, cada um contendo quase a mesma quantidade de dados, e cada um a ser solicitado a um par diferente. Mesmo que o solicitante não conheça o conteúdo e os limites de cada bloco, os tamanhos dos blocos são conhecidos com antecedência. Cada bloco pode ser verificado de forma eficiente e independente quando recebido. Alguns nós internos são incluídos em mais de um bloco, para possibilitar a verificação.

Uma Unitrie de estado dividida em três blocos verificáveis de modo independente

Outra grande vantagem da Unitrie é que, ao armazenar o tamanho do nó da trie, o nó da rede pode exibir a porcentagem de conclusão da sincronização de estado e estimar o tempo restante para concluir a sincronização.

Redução do tamanho da Blockchain através de desduplicação automática de código

Ao combinar células de armazenamento e código em um único banco de dados endereçado ao conteúdo, os nós que contêm a mesma chave/valor são armazenados apenas uma vez no banco de dados. Isso fornece desduplicação de dados automática, que, no caso de um código de contrato, pode reduzir o tamanho da blockchain sem exigir um mecanismo de desduplicação separado ou usar técnicas de compactação de dados. Os nós de código na trie sempre conterão o mesmo prefixo (0x80); portanto, o mesmo código implica o mesmo nó hash e o mesmo armazenamento.

Execução mais rápida do EXTCODESIZE

Cada nó da Unitrie contém um campo que armazena em cache o tamanho dos dados armazenados nesse nó. Na trie da Ethereum, consultar o tamanho dos dados do nó força os dados a serem obtidos a partir do banco de dados. A Unitrie pode responder a consultas de tamanho, como as geradas pelo código de operação EXTCODESIZE, por meio de consultas a esse novo campo, e sem buscar o código no disco rígido. O código de operação EXTCODESIZE foi usado no passado para executar ataques DoS em certas implementações da Ethereum, e a Unitrie fornece imunidade a esse tipo de ataque.

Detalhes do método de atualização

Nenhuma blockchain jamais executou uma atualização que altere o banco de dados de estado quando esse banco de dados está confirmado no cabeçalho do bloco. Portanto, a atualização será a primeira desse tipo. Basicamente, a atualização ocorre em duas fases. A nova versão do software calculará a nova raiz da trie, mas continuará derivando a raiz anterior por meio de um algoritmo dinâmico que converte estruturalmente a nova trie de estado para a trie anterior enquanto trabalha, seguido por um hard fork em que a nova raiz de estado é verificada e confirmada, e a conversão dinâmica não ocorrerá mais. Na verdade, não apenas a trie de estado deve ser convertida, mas também as tries de transação e recebimento.

Vários eventos devem ocorrer para que a rede possa ser atualizada com sucesso. Uma nova versão do software de nó completo será lançada no tempo R. A nova versão contém pontos de controle periódicos desde o bloco gênesis até um bloco específico no tempo C. O tempo C ocorre antes do tempo R. Em seguida, há um intervalo em que os nós serão atualizados antes do hard fork no tempo H. O diagrama a seguir representa a linha do tempo:

A linha do tempo de uma atualização de rede para a Unitrie

Quando a nova versão (que chamaremos de 0.7.0) estiver instalada, o nó completo deverá reconstruir seu banco de dados de estado de acordo com as novas regras. Pode migrar o estado atual ou recalcular o estado mediante o reprocessamento de todos os blocos desde o gênese até a melhor ponta de cadeia. Para a atualização da RSK, optamos pelo reprocessamento. Isso garante que todos os bancos de dados de nós completos estejam perfeitamente sincronizados, mesmo que o banco de dados anterior tenha sido corrompido de alguma forma.

O evento C é escolhido de modo que ocorra cerca de duas semanas antes do hard fork. Os usuários devem atualizar seu software de nó completo após a data de lançamento R, mas antes da data do hard fork H. Durante o período C-H, os nós calcularão as raízes de estado de trie antigas e novas. A raiz de estado anterior será calculada dinamicamente a partir da nova trie de estado. Os nós leves (também conhecidos como  nós SPV) podem decidir não validar as raízes de estado durante esse breve intervalo, para reduzir a carga da CPU. Isso ocorre porque os nós leves, de qualquer modo, seguem a taxa de hash. Além disso, os nós podem reduzir a sobrecarga de validação durante esse período verificando uma em cada 10 confirmações de raízes de estado durante o intervalo C-H, por exemplo. No entanto, o primeiro bloco após o hard fork não irá mais calcular nem validar raízes de estado antigas. Se aceito pela comunidade, esperamos que o hard fork não traga nenhum inconveniente.

Resumo

A Unitrie, proposta pela RSK em 2016, é uma melhoria notável para o armazenamento de estado em blockchains baseadas em contas, tais como a RSK, e proporciona um desempenho muito melhor de nós completos. A Unitrie melhora a descentralização ao reduzir os recursos necessários para os nós completos, melhora a capacidade de processamento de transações porque permite uma melhor execução paralela, evita ataques DoS ao armazenar em cache os tamanhos de cargas e reduzir os tamanhos de contas, aumenta a equidade porque permite um melhor aluguel de armazenamento, e reduz o tempo de sincronização mediante a compactação do estado.

Sabemos que atualizar uma rede para usar a Unitrie é um desafio, mas achamos que chegou o momento de buscarmos essa mudança. A RSK Labs está finalizando o código de referência e adicionando os toques finais às RSKIPs enquanto a comunidade RSK está avaliando a mudança. Nos próximos meses, esperamos uma atualização de rede segura para ativar a Unitrie.