Não fique bêbado: práticas recomendadas para lidar com atualizações de clientes Constantinopla e Ethereum

As atualizações de software, sejam para corrigir falhas de segurança, corrigir bugs ou adicionar novos recursos, geralmente são boas para os aplicativos que usamos todos os dias, e não pensamos duas vezes em aplicá-los. Porém, as atualizações nas principais partes da infraestrutura também podem ser assustadoras quando introduzem alterações ou comportamento inesperado para aplicativos dependentes ou, em outros casos, quando a falta de atualização no prazo pode causar falhas. Esse problema afeta entidades pequenas e grandes e a blockchain não é exceção.

Na Alchemy, fornecemos uma infraestrutura Ethereum confiável, escalável e rápida como serviço para nossos clientes, para que eles não precisem lutar com a manutenção de nós e possam se concentrar na criação de seus aplicativos. No decorrer de nosso trabalho, aprendemos muitas lições (às vezes da maneira mais difícil!) Sobre como lidar melhor com garfos de rede e atualizações de clientes. Com o próximo hard fork de Constantinopla, pensamos que seria uma ótima oportunidade para compartilhar algumas de nossas melhores práticas.

Esta é a primeira de muitas postagens de blog que escreveremos sobre a execução da infraestrutura Ethereum de maneira confiável, com desempenho e escalabilidade.

Constantinopla

Constantinopla é a próxima atualização de todo o sistema da Ethereum e implementará cinco EIPs, que na verdade fazem parte de um roteiro maior para o Ethereum 2.0. Existem muitas postagens por aí que discutem mudanças específicas, mas o principal a ser observado é que, como se trata de um hard fork não contencioso, a comunidade adotará o novo fork, tornando inúteis os tokens e outros estados em nós não atualizados.

Como isso afeta você?

Para os desenvolvedores dapp, o principal argumento é que você precisará atualizar seu nó para uma versão compatível com Constantinopla ou será incompatível com o restante do bloco anterior da rede 7.080.000. É provável que os clientes da Ethereum estejam atualizados sobre os garfos rígidos da cadeia e lançem uma versão estável e compatível de seus clientes bem antes da data estimada dos garfos, por exemplo. geth e paridade. Se você estiver gerenciando seu próprio nó do cliente Ethereum, precisará atualizar seu cliente ethereum para uma versão compatível com o hard fork; a paridade seria 2.1.10-estável ou superior e geth seria 1.8.20 ou superior.

As atualizações de hard fork devem ser poucas e distantes, mas as atualizações do cliente Ethereum podem ser muito mais comuns. Se você estiver executando um serviço dependente da cadeia, manter seu cliente atualizado pode ser benéfico para corrigir falhas de segurança ou alavancar novas funcionalidades. No entanto, você deve ter cuidado para não introduzir problemas inesperados em seu aplicativo.

Melhores práticas

Se você estiver executando um serviço que requer interação regular com o blockchain Ethereum, algumas das melhores práticas essenciais o evitarão de possíveis erros catastróficos quando você atualizar seus nós. Abordaremos alguns cenários da vida real de atualizações que deram errado, que foram o ímpeto para esta postagem no blog.

Executando vários nós

É altamente recomendável executar vários nós como uma prática recomendada geral para manter a infraestrutura interna do Ethereum devido aos muitos benefícios, incluindo maior confiabilidade e escalabilidade. No entanto, isso pode introduzir problemas de consistência e idempotência em seu sistema, os quais abordaremos em uma postagem subsequente no blog.

Quando se trata de atualizações, a execução de vários nós oferece alguns benefícios adicionais:

  1. Nós extras servem como backups no caso de uma atualização dar errado e tornar um nó irrecuperável
  2. Alta disponibilidade e sem tempo de inatividade ao atualizar os nós de forma contínua
  3. Permite teste de regressão que compara nós atualizados aos nós originais para garantir o comportamento esperado

No cenário de um nó irrecuperável, um novo nó de arquivamento completo pode levar até duas semanas para sincronizar completamente. Sem um backup, essa é uma quantidade inaceitável de tempo de inatividade.

Exemplo 1: Migração de banco de dados com erros

Um problema que vimos ao atualizar a paridade de 1.X.X para 2.X.X foi a corrupção no banco de dados. A atualização incluiu uma migração de banco de dados interna que estava convertendo incorretamente os números de bloco no filtro de bloom, o que resultou em resultados vazios para solicitações getLog para blocos históricos. A perda de dados foi irreversível para que o nó não pudesse ser recuperado. Tivemos a sorte de obtê-lo através de testes internos em um nó canário, recorrendo a nossos nós não atualizados para manter nossos sistemas ativos e aguardamos até que o problema fosse resolvido pela equipe de paridade no 2.2.3-beta.

Testes rigorosos de regressão

Testes rigorosos são sempre fortemente recomendados para quaisquer alterações no seu sistema. Nesse sentido, ao atualizar seus nós, você deseja testar para garantir que seu aplicativo e infraestrutura continuem funcionando conforme o esperado. Fazer o contrário poderia expor seus usuários e seus sistemas a interrupções. Com vários nós em execução, a melhor maneira de garantir isso é testar seus nós estáveis ​​anteriores em relação a um nó canário atualizado. Se forem detectadas alterações recentes, assegure-se de que seus sistemas possam tratá-las com segurança antes de atualizar o restante do cluster.

Quanto aos testes de regressão, vamos direto à fonte, reproduzindo solicitações de produção em nossos nós. Isso pode ser feito manualmente para verificações únicas, mas, como apoiamos muitos projetos, construímos uma extensa estrutura de testes automatizados que mostra as solicitações ativas recentes, as repete em diferentes versões do cliente e compara os resultados. Isso nos permite verificar se nosso código pode interagir com segurança com os nós atualizados antes do envio para a produção. Essa estrutura também pode ser aproveitada para testes de regressão em alterações de código interno.

Exemplo 2: Alteração no formato da saída de resposta

Esse foi um problema interessante que encontramos quando um cliente recém-atualizado retornou uma resposta diferente em um erro de execução do EVM. A paridade 1.11.1-beta retornou uma resposta parecida com esta:

{“Jsonrpc”: ”2.0”, ”error”: {“code”: - 32015, ”message”: ”Erro de execução da VM.”, ”Data”: ”0x revertido},” id ”: 1}

Em vez de respostas de versões anteriores parecidas com esta:

{"Jsonrpc": "2,0", "id": 1, "resultado": "0x"}

A alteração do formato da resposta é realmente benéfica, pois acrescenta mais detalhes de execução ao chamador em vez de falhar silenciosamente, mas pode causar problemas se o código não tiver sido configurado para lidar com isso. Nesse cenário, a comparação das saídas de resposta pegou a mudança e simplesmente atualizamos nossos sistemas e alertamos nossos clientes para que não ficassem alarmados com a nova resposta e pudessem atualizar seus serviços para serem compatíveis.

Build On!

Esperamos que isso tenha sido útil e que essas práticas recomendadas tornem as atualizações de nós indolor para você no futuro. Eles nos ajudaram a garantir que as atualizações sempre ocorram sem problemas tanto para nossos próprios sistemas quanto para os clientes que confiam em nós. Sabemos o quão difíceis podem ser os meandros de manutenção e dimensionamento de nós e queremos espalhar os aprendizados que tivemos ao longo dos anos.

Se você estiver trabalhando em um projeto Ethereum e não quiser lidar com a sobrecarga de manutenção de nós, fale conosco! A Alchemy fornece a infraestrutura Ethereum mais rápida, escalonável e confiável como serviço, para que você possa se concentrar na criação do seu produto. Sob o capô, a Alchemy construiu uma nova infraestrutura revolucionária que já impulsiona os principais projetos de blockchain como Augur, as principais empresas de blockchain como CryptoKitties e os principais fundos de hedge (gerenciando mais de US $ 3 bilhões). Saiba mais em alchemyapi.io.