Valor total de mercado:$00
API
PT
Escuro

PesquisarSSI/Mag7/Meme/ETF/Moeda/Índice/Gráficos/Pesquisa
00:00 / 00:00
Visualizar
    Mercados
    Índexes
    Feed de notícias
    TokenBar®
    Análise
    Macro
    Favoritos
Partilhar

Notas sobre 'DoS devido ao crescimento excessivo dos conjuntos inv-to-send' de maio de 2023

#Bitcoin
0xB10C's Blog: German Bitcoin freelance developer on 0xB10C's Blog
2KPalavras
23/06/2025

Em outubro de 2024, o projeto Bitcoin Core divulgou uma Negação de Serviço devido ao crescimento excessivo dos conjuntos inv-to-send, da qual sou autor, para as versões do Bitcoin Core anteriores à v25.0. Tenho algumas notas e capturas de tela da minha investigação da época que quero manter aqui. No início de maio de 2023, minha infraestrutura de monitoramento notou esse bug afetando os nós da mainnet, o que me permitiu identificar de onde vinha o problema. O crédito pelo trabalho em uma correção vai para Anthony Towns.


Observação


Em 2 de maio de 2023, notei que em um dos meus nós de monitoramento, as conexões de entrada haviam caído de cerca de 1901 para apenas 35 em cerca de dois dias. Normalmente, um nó mantém seus slots de entrada preenchidos até que seja reiniciado ou perca a conectividade de rede.




Uma captura de tela do meu painel Grafana para monitorar o número de conexões de entrada e saída do meu nó Bitcoin Core. As barras amarelas mostram o número de conexões de entrada. Estas desaparecem no final do gráfico.

Ao verificar com outros colaboradores, notei que o nó tinha 100% de utilização da CPU. Isso afetou o nó a um ponto em que ele não conseguia manter a comunicação com seus pares, o que resultou em tempo limite e queda das conexões de entrada. Usando perf top no processo do nó, pude ver que muito tempo de CPU estava sendo gasto em CTxMemPool::CompareDepthAndScore() na thread b-msghand. Gravei o seguinte flamegraph, que mostra que make_heap(), que chama CompareDepthAndScore(), usou mais de 45% do tempo de CPU do processo.




Um flame graph mostrando onde o tempo de CPU do processo Bitcoin Core está sendo gasto. Abra em uma nova aba para interagir com este flame graph.

Ao mesmo tempo, havia um problema de uso de 100% da CPU aberto e não relacionado com as compilações do modo debug do Bitcoin Core. Isso confundiu alguns colaboradores e usuários que não estavam executando compilações do modo debug, mas notaram o alto uso da CPU em seus nós. Embora o problema do modo debug provavelmente tenha afetado apenas alguns desenvolvedores, o outro problema de alto uso da CPU afetou toda a rede. Isso incluiu, por exemplo, pools de mineração como AntPool e outros, que relataram problemas com suas operações de mineração devido à falha de seus nós em processar os blocos recebidos em tempo hábil.


Efeito


A observação dos tempos de ping em toda a rede revela o efeito desta Negação de Serviço. Como o processamento de mensagens do Bitcoin Core é de thread único, apenas uma mensagem pode ser criada ou processada por vez, o que significa que todos os outros pares têm que esperar. Tempos de espera mais longos impactam o tempo de resposta para um ping. O monitoramento KIT DSN Bitcoin tem dados sobre pings ICMP e do protocolo Bitcoin. A comparação destes permite-nos determinar quando o software do nó tem problemas para acompanhar o processamento de mensagens. Os dados mostram que o ping ICMP para o host permaneceu inalterado, no entanto, o ping mediano para o software do nó Bitcoin quase dobrou de cerca de 25ms para mais de 50ms entre o final de abril e o início de maio. O ping mediano do Bitcoin atingiu 200ms em 8 de maio, enquanto o ping ICMP permaneceu inalterado.




Ping mediano do protocolo Bitcoin e ping ICMP. Baseado em dados do DSN KIT (https://www.dsn.kastel.kit.edu/bitcoin/)

O efeito também pode ser visto observando os dados de atraso de propagação de blocos coletados pelo monitoramento KIT DSN Bitcoin. Por volta de 8 de maio de 2023, um pico no atraso de propagação do bloco é visível. O tempo que 50% dos nós alcançáveis levaram para anunciar o bloco aos seus nós de monitoramento aumentou de menos de um segundo para mais de cinco segundos. Da mesma forma, a medição de 90% saltou de cerca de dois segundos para mais de 20 segundos.




Atraso de propagação do bloco: tempo médio até que 50% e 90% da rede anunciassem um bloco. Baseado em dados do DSN KIT (https://www.dsn.kastel.kit.edu/bitcoin/)

A má propagação de blocos também causa mais blocos obsoletos, pois os pools de mineração mineram em seus blocos desatualizados por mais tempo, enquanto um novo bloco que eles ainda não viram já existe na rede. Com base nos dados do meu conjunto de dados stale-blocks, dez blocos obsoletos foram observados durante a semana entre 3 de maio (começando com o bloco obsoleto 788016) e 10 de maio (e terminando com o bloco 789147). Essa é uma taxa de cerca de 8,84 blocos obsoletos por 1000 blocos. Em comparação, entre os blocos 800000 e 900000 (cerca de dois anos), 73 blocos obsoletos foram observados. Esta taxa 10 vezes maior de blocos obsoletos foi provavelmente causada pela propagação de blocos sendo significativamente afetada.


Causa


Por que a função CTxMemPool::CompareDepthAndScore() desacelerou o nó a um ponto em que teve problemas para processar mensagens P2P? No Bitcoin Core, a thread b-msghand processa mensagens P2P. Por exemplo, passar blocos recém-recebidos para validação, responder a pings, anunciar transações para outros pares e muito mais.


A função CTxMemPool::CompareDepthAndScore() é usada ao decidir quais transações anunciar para um par em seguida. No protocolo Bitcoin P2P, as transações são anunciadas através de mensagens inv (inventory). Um anúncio de transação Bitcoin Core para um par geralmente contém até 35 entradas wtxid. Para controlar quais transações anunciar para um par em seguida, existe um conjunto m_tx_inventory_to_send por par. Ele contém as transações que o nó pensa que o par ainda não viu. Ao construir uma mensagem de inventário para um par, o conjunto é classificado por dependências de transação e feerate para priorizar transações de alto feerate e para evitar vazar a ordem em que o nó aprendeu sobre as transações. Para isso, a função de comparação CTxMemPool::CompareDepthAndScore() é usada.


No início de maio de 2023, uma enorme quantidade de transações relacionadas aos tokens BRC-20 foram transmitidas. Isso significava que os conjuntos m_tx_inventory_to_send cresciam mais rápido do que o normal e maiores do que o normal. Como resultado, a classificação dos conjuntos demorou mais. Na noite de 7 de maio (UTC), a cunhagem do token VMPX BRC-20 começou, o que resultou em mais de 300 mil transações sendo transmitidas em 6 horas, além das outras cunhagens de token BRC-20 em andamento. Isso causou os picos nos tempos medianos de ping e propagação de blocos observados em 8 de maio.


O efeito é amplificado pelos chamados nós espiões que apenas ouvem mensagens inv e nunca anunciam transações por conta própria. Quando um par anuncia uma transação para um nó,
o nó pode removê-la de seu conjunto m_tx_inventory_to_send, pois é conhecida pelo par e não precisa mais ser anunciada. Isso significava que os conjuntos para nós espiões eram ainda maiores e demoravam ainda mais para serem classificados, pois eram drenados mais lentamente. Nós espiões, por exemplo, LinkingLion e outros, são comuns e frequentemente têm várias conexões abertas para um nó em paralelo. Às vezes, conto mais nós espiões presumidos do que conexões de nós não espiões aos meus nós.


A enorme quantidade de transações sendo transmitidas, combinada com a amplificação por nós espiões e a classificação não otimizada dos grandes conjuntos m_tx_inventory_to_send por CTxMemPool::CompareDepthAndScore(), fez com que os nós gastassem muito tempo criando novas
mensagens de inventário para retransmissão de transações. Como o tratamento de mensagens é de thread único, a comunicação com outros pares foi significativamente desacelerada. Isso chegou a um ponto em que os blocos não foram processados em tempo hábil e algumas conexões expiraram.


Correção


A correção é dupla. Primeiro, todas as transações a serem anunciadas que já foram mineradas ou por algum outro motivo não estavam mais no mempool, foram removidas antes que o conjunto m_tx_inventory_to_send fosse classificado. Anteriormente, essas transações eram removidas apenas após a classificação do conjunto. Isso evita gastar tempo na classificação de entradas de transação que nunca serão anunciadas de qualquer forma e reduz o tamanho do conjunto a ser classificado. Em segundo lugar, quando os conjuntos m_tx_inventory_to_send são grandes, o número de entradas a serem drenadas do conjunto é aumentado dinamicamente com base no tamanho do conjunto. Isso significa que, quando muitas transações são transmitidas, um nó anunciará mais transações para seus pares até que os conjuntos sejam menores novamente. A correção foi retroportada a tempo para o lançamento da v25.0 no final de maio de 2023.


Reflexão


Embora um conjunto de colaboradores regulares soubesse que isso estava acontecendo, este problema não foi comunicado abertamente ao público. O problema de uso de 100% da CPU com o modo debug sendo discutido ao mesmo tempo causou confusão, mesmo entre os colaboradores regulares do Bitcoin Core. Na época, tive a sensação de que isso poderia e talvez devesse ser corrigido silenciosamente e não precisa de muita publicidade por enquanto. Em retrospecto, talvez ser mais público e transparente com o problema também pudesse ter funcionado. O alto número de transmissões BRC-20 durou apenas cerca de uma semana (mas isso não era conhecido de antemão) e reiniciar o nó teria ajudado por um tempo. Para mitigar o problema para, por exemplo, pools de mineração que não podem atualizar para uma versão com a correção imediatamente (devido à execução com patches personalizados), uma lista de banimento de nós espiões foi preparada, mas não sei se alguma vez foi usada.


Embora não houvesse um canal de comunicação dedicado para este evento, um canal IRC não listado com colaboradores P2P foi usado e os colaboradores interessados foram convidados ou informados sobre os eventos por meio de mensagens diretas. Tanto quanto sei, não havia um canal de resposta a incidentes e não sei se um seria útil dada a natureza ad hoc e descentralizada do desenvolvimento do Bitcoin. Nenhum colaborador é responsável pela resposta a incidentes, mas todos podem ajudar.


Pessoalmente, estou feliz que meu monitoramento tenha se mostrado útil para isso. Embora eu não tivesse alertas para conexões descartadas configuradas na época e só tenha notado olhando para o painel, foi útil tê-lo. Para identificar o problema, foi útil ter alguns nós para brincar e executar, por exemplo, perf top. O monitoramento futuro deve incluir tempos de ping e alertas sobre conexões descartadas.






  1. Eu havia aumentado a contagem de conexões das 125 conexões padrão para 200. ↩︎




Tudo o que você precisa saber em 10s
TermosPolítica de PrivacidadePapel BrancoVerificação oficialCookieBlogue
sha512-gmb+mMXJiXiv+eWvJ2SAkPYdcx2jn05V/UFSemmQN07Xzi5pn0QhnS09TkRj2IZm/UnUmYV4tRTVwvHiHwY2BQ==
sha512-kYWj302xPe4RCV/dCeCy7bQu1jhBWhkeFeDJid4V8+5qSzhayXq80dsq8c+0s7YFQKiUUIWvHNzduvFJAPANWA==