NOVO: Helius adquire a Light Protocol
Atualização v1.18 da Solana
Blog/Atualizações

Tudo o que você precisa saber sobre a atualização v1.18 da Solana

Developer Experience Engineer0xIchigo no X0xIchigo no LinkedIn0xIchigo no GitHub
19 min de leitura

Agradecemos muito a Rex St. John e Mike MacCana pela revisão deste artigo.

Introdução

A adoção da atualização 1.18 da Solana por uma supermaioria é um marco significativo. Ela traz uma série de melhorias e novos recursos para aprimorar o desempenho, a confiabilidade e a eficiência da rede. Uma das mudanças mais notáveis é a introdução de um agendador central. Esse novo agendador busca simplificar o processamento de transações e garantir cálculos de prioridade mais precisos e eficientes. Outras melhorias no ambiente de execução e nas implantações de programas, por exemplo, ajudam a oferecer um desempenho mais confiável mesmo durante os períodos de pico de carga da rede.

Este artigo explora as atualizações e melhorias trazidas pela versão 1.18. Abordaremos as motivações por trás dessas mudanças, os detalhes dos novos recursos e o impacto esperado na evolução da rede. Seja você operador de validador, desenvolvedor ou usuário comum da Solana, esta visão abrangente da atualização 1.18 fornecerá as informações necessárias para entender e aproveitar os benefícios dessas novas melhorias.

Primeiro, precisamos falar sobre a Anza, uma empresa de desenvolvimento recém-criada que está impulsionando essas mudanças, e sobre seu papel no desenvolvimento contínuo da Solana.

O que é a Anza?

A Anza é uma empresa de desenvolvimento de software recém-criada por ex-executivos e engenheiros de núcleo da Solana Labs. Sua criação representa uma iniciativa estratégica para fortalecer o ecossistema da Solana, com o objetivo de melhorar sua confiabilidade, descentralização e robustez da rede. A Anza foi fundada para aprimorar o ecossistema da Solana por meio do desenvolvimento de infraestrutura crítica, da contribuição para protocolos importantes e do incentivo à inovação de novas ferramentas.

A equipe fundadora inclui Jeff Washington, Stephen Akridge, Jed Halfon, Amber Christiansen, Pankaj Garg, Jon Cinque e vários engenheiros de núcleo da Solana Labs.

A Anza está focada em desenvolver e aperfeiçoar os clientes validadores da Solana com a criação do Agave — um fork do cliente validador da Solana Labs. As ambições da Anza vão além do desenvolvimento de seu cliente validador e abrangem melhorias em todo o ecossistema. Isso inclui o desenvolvimento de Token Extensions e de uma cadeia de ferramentas Rust / Clang personalizada. Ao promover uma abordagem colaborativa e aberta ao desenvolvimento, a Anza se dedica a acelerar e aprimorar o ecossistema da Solana.

O que é o Agave?

Como mencionado brevemente na seção anterior, Agave é um fork do cliente validador da Solana Labs liderado pela Anza. Nesse contexto, o termo “fork” significa que a equipe de desenvolvimento da Anza utiliza o código existente no repositório da Solana Labs e inicia um novo caminho de desenvolvimento separado da base de código original. Isso permite que a Anza implemente suas próprias melhorias, funcionalidades e otimizações no cliente da Solana Labs.

O processo de migração

A migração do cliente para a organização da Anza no GitHub começou em 1º de março. Inicialmente, Agave espelhará o repositório da Solana Labs para dar tempo à comunidade de se adaptar. Durante esse período, a Anza cuidará do encerramento de pull requests (PRs) e da migração de issues relevantes para o repositório do Agave. Agave e as versões 1.17 e 1.18 do cliente da Solana Labs serão idênticos em termos de funcionalidade. A Anza pretende lançar o Agave v2.0 neste verão no Hemisfério Norte, o que inclui arquivar o cliente da Solana Labs e recomendar que 100% da rede migre para o novo cliente Agave.

O processo de migração da Solana Labs para o Agave é acompanhado publicamente no GitHub.

O ambiente de execução do Agave

O ambiente de execução do Agave herda sua arquitetura fundamental da Solana Virtual Machine (SVM) e serve como base para executar as principais funcionalidades definidas pelo ambiente de execução Sealevel. 

O protocolo da Solana define o ambiente de execução como um componente essencial para processar transações e atualizar o estado no banco de dados de contas. Essa especificação foi adotada e aperfeiçoada pelos clientes Agave e Firedancer. A essência da SVM está em sua capacidade de executar todos os programas da Solana e modificar os estados das contas em paralelo.

O conceito de banco é fundamental para processar transações e entender as mudanças que chegam com a versão 1.18. Um banco é tanto uma lógica quanto uma representação do estado do livro-razão em um momento específico. Ele atua como um controlador sofisticado que gerencia o banco de dados de contas, supervisiona o rastreamento das contas dos clientes, gerencia a execução de programas e mantém a integridade e a progressão do livro-razão da Solana. Um banco encapsula o estado resultante das transações incluídas em determinado bloco, servindo como um instantâneo do livro-razão naquele momento.

Cada banco conta com caches e referências necessários para a execução de transações, permitindo que seja inicializado a partir de um instantâneo anterior ou do bloco gênese. Durante o Banking Stage, no qual o validador processa transações, os bancos são usados para montar blocos e, posteriormente, verificar sua integridade. Esse ciclo de vida inclui carregar contas, processar transações, congelar o banco para finalizar o estado e, por fim, torná-lo enraizado, garantindo sua permanência.

Em termos gerais, o mecanismo de processamento de transações do ambiente de execução do Agave é responsável por carregar, compilar e executar programas. Ele usa compilação Just-In-Time (JIT), armazenando programas compilados em cache para otimizar a eficiência da execução e reduzir recompilações desnecessárias. Os programas são compilados para o formato eBPF antes da implantação. Em seguida, o ambiente de execução usa o kit de ferramentas rBPF para criar uma máquina virtual eBPF, que realiza a compilação JIT de eBPF para instruções de código de máquina x86_64, aproveitando ao máximo o hardware disponível. Isso garante que os programas sejam executados com eficiência.

A atualização 1.18 introduz um agendador central de transações, profundamente relacionado às eficiências operacionais trazidas pelo ambiente de execução do Agave. Ao melhorar a forma como as transações são compiladas, executadas e gerenciadas por meio de bancos, a atualização 1.18 possibilita um processo de agendamento mais simples e eficiente. Isso, por sua vez, reduz o tempo de processamento das transações e aumenta a capacidade de processamento. O novo ambiente de execução do Agave e seu cliente servem como base para essas melhorias. Por isso, é fundamental termos uma compreensão geral antes de analisarmos os detalhes do novo agendador. 

Se quiser saber mais sobre o ambiente de execução do Agave, recomendo a leitura do artigo de Joe Caulfield sobre o tema. Ele apresenta muitos detalhes e inclui trechos úteis de código ao longo do texto.

Um agendador de transações mais eficiente

A implementação atual

No pipeline de processamento de transações, os pacotes de transações entram primeiro no sistema pela entrada de pacotes. Depois, esses pacotes passam pela verificação de assinaturas durante a etapa SigVerify. Essa etapa garante que cada transação seja válida e autorizada pelo remetente.

Após a verificação das assinaturas, as transações são enviadas ao Banking Stage. O Banking Stage tem seis threads: duas dedicadas ao processamento de transações de voto provenientes da Transaction Processing Unit (TPU) ou do Gossip e quatro voltadas para transações que não são de voto. Cada thread é independente das demais e recebe pacotes de um canal compartilhado. Ou seja, o SigVerify envia pacotes em lotes, e cada thread extrai transações desse canal compartilhado e as armazena em um buffer local. 

O buffer local recebe as transações, determina sua prioridade e as ordena de acordo. Essa fila é dinâmica e se atualiza constantemente para refletir as mudanças em tempo real no status das transações e nas demandas da rede. À medida que as transações são adicionadas à fila, sua ordem é reavaliada para garantir que as transações de maior prioridade estejam prontas para serem processadas primeiro.

Esse processo ocorre continuamente, e o que acontece com esses pacotes de transações depende da posição do validador no cronograma de líderes. Se o validador não estiver programado para ser o líder em breve, ele encaminhará os pacotes ao próximo líder e os descartará. À medida que o validador se aproxima de seu slot de liderança programado (a cerca de ~20 slots), ele continuará encaminhando os pacotes, mas deixará de descartá-los. Isso garante que esses pacotes possam ser incluídos em um de seus próprios blocos caso os outros líderes não os processem. Quando um validador está a 2 slots de se tornar líder, ele começa a reter os pacotes — aceitando-os sem fazer nada para que possam ser processados quando o validador se tornar líder.

Durante a produção de blocos, cada thread retira as 128 primeiras transações de sua fila local, tenta obter bloqueios e, em seguida, verifica, carrega, executa, registra e confirma as transações. Se a obtenção do bloqueio falhar, a transação será tentada novamente mais tarde. Vamos detalhar cada etapa:

  • Bloqueio: esta etapa verifica para quais transações a thread consegue obter bloqueios. Cada uma dessas transações lerá e gravará em determinado número de contas, portanto o validador precisa garantir que não haja conflitos
  • Verificações: esta etapa verifica se a transação é antiga demais ou se já foi processada. Observe que os bancos têm um cache de status que acompanha as transações dos últimos 150 a 300 slots
  • Carregamento: esta etapa carrega as contas necessárias para executar determinada transação. Ela também verifica se o pagador da taxa realmente tem recursos para pagá-la e se o programa invocado é válido. Basicamente, esta etapa carrega as contas e realiza algumas configurações iniciais
  • Execução: esta etapa executa cada transação
  • Registro: os resultados das transações executadas são enviados ao serviço de Proof of History para serem submetidos a hash. É nesse momento que a assinatura da transação é enviada
  • Confirmação: se a etapa de registro for bem-sucedida, as transações serão confirmadas. Esta etapa também propaga as alterações de volta ao sistema de contas, para que transações futuras neste slot ou nos seguintes tenham a visão atualizada de cada conta‍
  • Desbloqueio: os bloqueios de cada conta aplicados na primeira etapa são removidos

O Banking Stage usa uma abordagem de múltiplos iteradores para criar esses lotes de transações. Um múltiplo iterador é um padrão de programação que permite percorrer simultaneamente um conjunto de dados em várias sequências. Imagine vários leitores percorrendo um único livro, cada um começando em um capítulo diferente e se coordenando para não ler a mesma página ao mesmo tempo caso a compreensão do conteúdo por um possa interferir na do outro. No Banking Stage, esses “leitores” são iteradores, e o “livro” é o conjunto de transações que aguardam processamento. O objetivo do múltiplo iterador é filtrar as transações com eficiência, agrupando-as em lotes que possam ser processados sem conflitos de bloqueio.

Inicialmente, as transações são serializadas em um vetor com base na prioridade. Isso fornece ao múltiplo iterador uma sequência estruturada para separar essas transações em lotes sem conflitos. O múltiplo iterador começa no início do vetor serializado, posicionando iteradores em pontos nos quais as transações não entrem em conflito entre si. Dessa forma, ele cria lotes de 128 transações sem conflitos de leitura-gravação ou gravação-gravação. Se uma transação entrar em conflito com o lote em formação, ela será ignorada e permanecerá sem marcação, o que permite incluí-la em um lote posterior no qual o conflito já não exista. Esse processo iterativo se ajusta dinamicamente à medida que as transações continuam sendo processadas. 

Após a formação bem-sucedida de um lote, as transações são executadas e, se forem bem-sucedidas, registradas no serviço de Proof of History e transmitidas para a rede.

Os problemas da implementação atual

A implementação atual apresenta várias áreas nas quais o desempenho pode ser prejudicado, criando possíveis gargalos no processamento de transações e inconsistências na priorização. Esses desafios decorrem principalmente da arquitetura do Banking Stage e da natureza do processamento de transações no sistema.

Um problema fundamental é que as quatro threads independentes que processam transações que não são de voto têm sua própria visão da prioridade das transações dentro de cada thread. Essa divergência pode causar variações ou inconsistências na ordenação das transações. Essas discrepâncias ficam mais evidentes quando todas as transações de alta prioridade entram em conflito. Como os pacotes são basicamente extraídos de maneira aleatória por cada thread do canal compartilhado do SigVerify, cada thread terá um conjunto aleatório de todas as transações. Durante eventos competitivos, como a cunhagem de uma coleção popular de NFT, é provável que muitas transações de alta prioridade estejam presentes em várias threads do Banking Stage. Isso é problemático porque pode causar conflitos de bloqueio entre threads. Ao trabalhar com diferentes conjuntos de prioridades, as threads podem competir para processar essas transações de alta prioridade, desperdiçando tempo de processamento involuntariamente devido a tentativas malsucedidas de bloqueio.

Pense no Banking Stage como uma orquestra em que cada thread representa uma seção diferente — cordas, metais, madeiras e percussão. Em condições ideais, um maestro coordenaria essas seções para garantir uma apresentação harmoniosa. No entanto, o sistema atual se parece com uma orquestra tentando executar uma peça complexa sem maestro. Cada seção toca sua própria melodia e entra em conflito com as outras com frequência. As transações de alta prioridade são as partes solistas que todas as seções tentam tocar ao mesmo tempo, causando confusão. Essa falta de coordenação evidencia a necessidade de um “maestro” centralizado para garantir eficiência e harmonia no processamento de transações da Solana, assim como um maestro conduz uma orquestra.

O novo agendador de transações

A atualização 1.18 introduz uma thread central de agendamento, substituindo o modelo anterior com quatro threads bancárias independentes, cada uma responsável por sua própria priorização e processamento de transações. Nessa estrutura revisada, o agendador central é o único destinatário das transações vindas da etapa SigVerify. Ele cria uma fila de prioridade e utiliza um grafo de dependências para gerenciar a priorização e o processamento das transações.

Esse grafo de dependências é conhecido como prio-graph. Ele é um grafo acíclico direcionado que passa por avaliação preguiçosa à medida que novas transações são adicionadas. As transações são inseridas no grafo para criar cadeias de execução e depois são retiradas por ordem de tempo e prioridade. Quando há transações conflitantes, a primeira inserida sempre terá prioridade maior. No exemplo acima, temos as transações de A a H. Observe que as transações A e E têm a maior prioridade em suas respectivas cadeias e não entram em conflito. O agendador avança da esquerda para a direita, processando as transações em lotes:

As transações A e E são processadas como o primeiro lote; depois, B e F; em seguida, C, D e G; e H como o lote final. Como você pode ver, as transações de maior prioridade ficam no topo do grafo (ou seja, na extremidade esquerda). Conforme o agendador examina as transações em ordem decrescente, ele identifica conflitos. Se uma transação entrar em conflito com outra de prioridade maior, uma aresta será criada no grafo para representar essa dependência (por exemplo, C e D entram em conflito com B).

O novo modelo de agendador resolve vários problemas importantes inerentes à abordagem de múltiplos iteradores:

  • Consistência no tratamento de prioridades: o novo sistema garante que todas as transações sejam processadas em uma ordem de prioridade consistente ao centralizar o recebimento e o agendamento das transações. Isso elimina as variações anteriormente causadas por várias threads com diferentes visões das prioridades das transações
  • Redução dos atrasos no processamento: o prio-graph garante que os lotes preparados para execução tenham grande probabilidade de sucesso sem conflitos de bloqueio, reduzindo o tempo de processamento e quaisquer atrasos causados pela disputa por bloqueios. Observe o uso da expressão “grande probabilidade de sucesso” — não é estritamente verdade que o prio-graph produza lotes que não possam falhar na obtenção de bloqueios, pois eles podem entrar em conflito com threads de voto, embora esse seja um caso extremo muito raro
  • Escalabilidade e flexibilidade: o novo design do agendador permite aumentar o número de threads sem as preocupações anteriores com o aumento de conflitos de bloqueio. Isso se deve à visão centralizada dos bloqueios e à distribuição mais controlada das transações entre os workers 

Espera-se que a introdução do agendador central na versão 1.18 melhore significativamente o processamento de transações, reduzindo a complexidade e a sobrecarga associadas ao sistema anterior. Isso provavelmente reduzirá o tempo de processamento das transações, aumentará a capacidade de processamento e tornará a rede mais estável. Devido aos atrasos no lançamento da versão 1.18, o agendador foi aprimorado desde sua criação. Por exemplo, a verificação de pré-compilação das transações foi transferida para as threads de trabalho a fim de melhorar a eficiência. Além disso, os limites de CU agora são mais razoáveis, com proporções entre estimativa e consumo real muito menores do que no agendador antigo. O novo agendador agora pode usar CUs para limitar as filas de trabalho agendadas, evitando que um volume excessivo de trabalho seja enfileirado devido a conflitos de contas.

Observe que o agendador central não é ativado por padrão e precisa ser habilitado com a nova flag --block-production-method central-scheduler ao iniciar um validador. Atualmente, ele é opcional, mas se tornará o agendador padrão em versões futuras. Observe também que o agendador antigo pode ser habilitado com a flag --block-production-method thread-local-multi-iterator (ela é habilitada por padrão, mas não faça isso em versões futuras — o agendador central é muito mais eficiente e resolve os problemas apresentados pelo agendador antigo).

Cálculo de prioridade mais eficaz 

A versão 1.18 também aperfeiçoa a forma como a prioridade das transações é determinada, tornando o processo mais justo e eficiente em relação ao uso de recursos e à recuperação de custos. Anteriormente, a priorização de transações se baseava principalmente na prioridade do orçamento computacional, o que às vezes levava a uma precificação abaixo do ideal das unidades computacionais. Isso ocorria porque a priorização não considerava adequadamente as taxas básicas cobradas, criando situações em que os recursos podiam receber preços abaixo do adequado e afetar a eficiência operacional da rede.

A nova abordagem ajusta o cálculo de prioridade das transações para considerar as taxas da transação e os custos associados usando a fórmula Prioridade = Taxas / (Custo + 1). Nela, as taxas representam as taxas associadas a determinada transação, enquanto o custo representa o consumo de computação e recursos determinado pelo modelo de custos da Solana. A adição de “1” ao denominador é uma medida de segurança para evitar a divisão por zero. 

Podemos detalhar ainda mais a fórmula para tornar Taxas e Custo mais explícitos:

O custo de uma transação agora é calculado de forma abrangente, considerando todos os custos computacionais e operacionais associados. Isso garante que os cálculos de prioridade reflitam o verdadeiro consumo de recursos de uma transação. Isso significa que desenvolvedores e usuários receberão prioridade maior se solicitarem menos unidades computacionais. Também significa que transferências simples, sem taxas de prioridade, terão alguma prioridade na fila.

Implantação aprimorada de programas

A versão 1.18 também melhora significativamente as implantações de programas em termos de confiabilidade da implantação e eficiência de execução. 

A nova atualização resolve um problema no qual programas implantados no último slot de uma época não aplicavam corretamente as mudanças no ambiente de execução planejadas para a época seguinte. Assim, um programa implantado durante esse período de transição usava incorretamente o ambiente de execução antigo. A versão 1.18 ajusta o processo de implantação para garantir que o ambiente de execução de qualquer programa implantado no fim de uma época esteja alinhado ao ambiente da próxima época.

A versão 1.18 também resolve a impossibilidade de definir um preço ou limite de unidades computacionais nas transações de implantação ao adicionar a flag --with-compute-unit-price aos comandos de implantação de programas da CLI. Essa flag pode ser usada com os comandos solana program deploy e solana program write-buffer. O limite de unidades computacionais é definido simulando cada tipo de transação de implantação e configurando-o de acordo com o número de unidades computacionais consumidas.  

Outra melhoria importante envolve a forma como os blockhashes de implantações de programas grandes são tratados. Antes da versão 1.18, as transações enviadas com sign_all_messages_and_send eram limitadas a 100 TPS. Para programas maiores, o número de transações de implantação chega aos milhares. Isso significa que as transações podiam sofrer atrasos e correr o risco de usar blockhashes expirados, pois muitas delas ficavam atrasadas por mais de 10 segundos. A versão 1.18 adia a assinatura de transações de implantação com um blockhash recente até depois do atraso causado pela limitação. Agora, os blockhashes são atualizados a cada 5 segundos. Assim, implantações com mais de 500 transações se beneficiarão do uso de um blockhash mais recente.

Além disso, a versão 1.18 introduz melhorias na forma como a rede processa implantações de programas e verifica transações. Anteriormente, alguns programas eram marcados incorretamente como FailedVerification devido a erros na identificação dos status das contas. Isso podia rotular incorretamente programas que não haviam falhado em nenhuma verificação. Agora, esses programas são identificados corretamente como Closed quando não devem estar ativos. Essa mudança garante que apenas programas problemáticos sejam sinalizados para uma nova verificação e ajuda a evitar verificações repetidas desnecessárias.

O processo de atualização dos estados dos programas também foi aperfeiçoado. Agora, os programas podem passar de um estado Closed para um estado ativo no mesmo slot em que são implantados. Isso significa que os programas entram em operação de forma mais rápida e confiável, algo essencial durante períodos de alta demanda. No entanto, é importante observar que essa melhoria ainda está sujeita ao período de espera de um slot para cancelamento, reimplantação ou implantação e ao atraso de visibilidade de um slot. Como resultado, embora esses ajustes ajudem a gerenciar a carga da rede com mais eficiência e evitem certos tipos de congestionamento, eles não alteram significativamente o fluxo de trabalho dos desenvolvedores de dApps.

“A correção de congestionamento” — Como lidar melhor com o congestionamento

A versão 1.18.11 da testnet, anunciada como “A correção de congestionamento”, propôs mudanças para resolver o congestionamento recente da Solana. Observe que essa versão não é exclusiva da 1.18 e foi retroportada para a 1.17.31. De qualquer forma, é fundamental falarmos sobre ela.

A grande mudança é que o QUIC agora trata pares com stake extremamente baixo como pares sem stake no Stake-Weighted Quality of Service (SWQoS). Isso foi feito para resolver o fato de que nós com stake muito pequeno podiam explorar o sistema para obter uma largura de banda desproporcional. Além disso, as métricas atuais não conseguiam indicar as proporções de pacotes transmitidos e limitados provenientes de nós com stake em comparação com os nós sem stake. Por isso, essas métricas foram adicionadas para oferecer maior visibilidade. A forma como os blocos de pacotes eram tratados também foi otimizada, substituindo instâncias de vec por smallvec para economizar uma alocação por pacote. Isso é possível porque os streams têm o tamanho de um pacote, portanto espera-se que sejam poucos. 

Anteriormente, no Banking Stage, todos os pacotes eram encaminhados ao próximo nó. No entanto, a versão 1.18 muda esse comportamento para que apenas pacotes de nós com stake sejam encaminhados. Com essa atualização, as conexões com stake se tornam mais importantes do que nunca, pois têm maior peso no cálculo da prioridade e no encaminhamento das transações.

Documentação aprimorada

A atualização 1.18 também melhora significativamente o suporte a traduções da documentação oficial da Solana, garantindo maior acessibilidade para um público global. As atualizações incluem melhorias na CLI e na configuração do Crowdin — o que simplifica a sincronização de documentos entre idiomas — e a introdução de um novo comando serve para aprimorar os testes locais via Docusaurus. A documentação também melhora a forma como o conteúdo estático é processado, vinculando arquivos PDF diretamente a blobs do GitHub para evitar problemas com caminhos relativos em builds traduzidos.

Para desenvolvedores, o processo de contribuição com traduções foi esclarecido em um README atualizado, que explica como lidar com problemas comuns, como variáveis de ambiente necessárias e erros típicos de build. Isso é complementado por melhorias no fluxo de integração contínua, que agora inclui traduções apenas nos builds do canal estável. Isso garante que somente documentação revisada e estável chegue aos usuários finais. Essas mudanças buscam simplificar as contribuições, aprimorar a qualidade da documentação oficial e dar a todos os usuários acesso a informações confiáveis e precisas.

Conclusão

Impulsionada pela Anza, a atualização 1.18 melhora substancialmente o processamento de transações, os cálculos de prioridade, as implantações de programas, a documentação oficial e o desempenho geral da rede. Com a introdução de um agendador central e as diversas correções destinadas a resolver o congestionamento recente, a Solana está mais preparada para lidar com picos de carga e garantir um comportamento eficiente e confiável da rede. A Solana é a melhor oportunidade para uma blockchain escalável, e esta atualização reafirma seu potencial.

Se você leu até aqui, agradecemos, anon! Insira seu endereço de e-mail abaixo para nunca perder uma atualização sobre as novidades da Solana. Quer se aprofundar? Explore os artigos mais recentes no blog da Helius e continue hoje mesmo sua jornada pela Solana.

Recursos adicionais

Assine a Helius

Acompanhe as novidades mais recentes do desenvolvimento Solana e receba atualizações quando publicarmos

Imagem ampliada