Gossip e o Grafo de Canais
Como os nós descobrem canais públicos, políticas de roteamento e caminhos possíveis
Lightning · Técnico
No roteamento onion, a origem precisa conhecer uma rota antes de montar o pacote criptografado. Mas a Lightning não tem um servidor central dizendo quais canais existem. Cada nó aprende a rede por gossip: mensagens assinadas que anunciam canais públicos, metadados de nós e políticas de roteamento.
O resultado local desse processo é o grafo de canais. Nesse grafo, os vértices são node ids, as arestas são canais públicos e cada direção da aresta tem uma política própria: fee base, fee proporcional, CLTV delta, valor mínimo, valor máximo e flag de disponibilidade. A busca de caminho usa esse grafo para escolher uma rota, mas o gossip não garante que a rota tenha liquidez real.
A especificação principal é a BOLT 7. Ela conecta Lightning diretamente ao Bitcoin on-chain, porque um canal público só deve ser aceito se apontar para uma funding transaction existente.
Conteúdo
Modelo mental
Gossip não é o pagamento. Gossip é o mapa público aproximado que permite calcular uma rota. O pagamento real ainda usa HTLCs, commitments e onion routing.
- Dois peers abrem um canal on-chain com uma funding transaction.
- Se quiserem tornar o canal público, eles trocam assinaturas de anúncio.
- Depois que a funding output tem profundidade suficiente, um
channel_announcementpode ser propagado. - Cada lado publica seu próprio
channel_update, porque a política de encaminhamento é direcional. - Os node ids envolvidos podem publicar
node_announcementcom alias, cor, endereços e features. - Outros nós validam, armazenam e repassam essas mensagens para montar seu próprio grafo.
Descrição longa do diagrama
O diagrama mostra vários nós Lightning conectados. Uma mensagem channel_announcement destaca a existência de um canal público. Mensagens channel_update aparecem em cada direção do canal, indicando taxas e CLTV. Uma mensagem node_announcement aparece ligada a um nó, indicando alias e endereço. Setas simples mostram as mensagens sendo repassadas pela rede.
Mensagens BOLT 7
A BOLT 7 não define apenas três mensagens públicas. Ela também define mensagens de consulta e filtros para sincronizar o grafo sem depender de receber tudo por inundação.
| Tipo | Mensagem | Escopo | Função |
|---|---|---|---|
| 259 | announcement_signatures | entre os dois peers do canal | Troca assinaturas antes de publicar um canal público. |
| 256 | channel_announcement | gossip público | Prova que um canal público existe e liga dois node ids a uma funding output on-chain. |
| 258 | channel_update | gossip público | Anuncia a política de roteamento de uma direção do canal. |
| 257 | node_announcement | gossip público | Anuncia metadados do nó: alias, cor, endereços e features. |
| 261 | query_short_channel_ids | sincronização | Pede anúncios e updates para uma lista de SCIDs. |
| 263 | query_channel_range | sincronização | Pede os SCIDs conhecidos em uma faixa de blocos. |
| 265 | gossip_timestamp_filter | sincronização | Filtra updates por timestamp para receber apenas informação recente. |
Essas mensagens viajam dentro do protocolo wire. Portanto, elas seguem a moldura geral da BOLT 1: type de 2 bytes e payload específico da mensagem.
Antes do anúncio público
O canal público não aparece magicamente no gossip. Primeiro, os dois peers precisam trocar announcement_signatures. Essa mensagem é enviada entre os participantes do canal, não como gossip global. Ela permite que cada lado obtenha as assinaturas necessárias para construir um channel_announcement completo.
Essa etapa importa porque um anúncio público precisa provar duas coisas ao mesmo tempo:
- os dois node ids Lightning aceitam associar seus nós ao canal;
- as duas chaves Bitcoin da funding output aceitam associar aquela saída on-chain ao canal anunciado.
Sem essa dupla prova, qualquer pessoa poderia inventar canais falsos entre node ids conhecidos ou apontar para saídas Bitcoin que não controla.
channel_announcement
O channel_announcement é o certificado público de existência do canal. Ele diz: "existe um canal público nesta blockchain, localizado por este short channel id, entre estes dois node ids, com estas chaves Bitcoin na funding output".
| Campo | Tamanho | Função |
|---|---|---|
| node_signature_1/2 | 64 bytes cada | Assinaturas dos dois node ids sobre o anúncio. |
| bitcoin_signature_1/2 | 64 bytes cada | Assinaturas das duas chaves Bitcoin que controlam a funding output. |
| features | variável | Feature bits do canal, codificados como vetor de features. |
| chain_hash | 32 bytes | Identifica a blockchain onde a funding transaction existe, como Bitcoin mainnet ou testnet. |
| short_channel_id | 8 bytes | Localização compacta da funding output: bloco, índice da transação e índice da saída. |
| node_id_1/2 | 33 bytes cada | Chaves públicas comprimidas dos dois nós Lightning. |
| bitcoin_key_1/2 | 33 bytes cada | Chaves públicas Bitcoin usadas na saída de financiamento 2-de-2. |
A ordem dos dois lados não é arbitrária. O protocolo exige que node_id_1 seja a menor das duas chaves públicas comprimidas em ordem lexicográfica, e node_id_2 a maior. Como toda implementação chega ao mesmo critério só de olhar as chaves, os dois peers concordam sem negociar qual lado é "1" e qual é "2". Esse rótulo estável é o que dá sentido à direção anunciada em cada channel_update.
O ponto anti-spam está aqui: para anunciar um canal público, o anunciante precisa apontar para bitcoin realmente travado em uma saída de transação. Verificar essa saída exige conceitos de altura de bloco, txid, vout, UTXO e P2WSH ou outro formato de script usado pela funding output.
ao receber channel_announcement:
1. conferir se chain_hash é da rede esperada
2. decodificar short_channel_id em bloco, txindex e outputindex
3. localizar a transação no bloco indicado
4. conferir se a saída indicada existe e ainda corresponde a funding output válida
5. verificar as bitcoin_signature_1/2 contra as bitcoin_key_1/2
6. verificar as node_signature_1/2 contra os node_id_1/2
7. aceitar o canal no grafo somente se as provas baterem A validação exata depende do estado da cadeia visto pelo nó. Uma reorganização, uma funding transaction ainda rasa ou um fechamento de canal podem mudar se aquele canal deve permanecer no grafo local.
Short Channel ID (SCID)
O Short Channel ID é um identificador compacto de 8 bytes. Ele não é um hash aleatório. Ele codifica a localização da funding output dentro da blockchain:
SCID = blockheight x txindex x outputindex
SCID numérico = (blockheight << 40) | (txindex << 16) | outputindex | Parte | Tamanho | Exemplo | Significado |
|---|---|---|---|
| blockheight | 24 bits | 700000 | Altura do bloco que confirmou a funding transaction. |
| txindex | 24 bits | 1337 | Posição da funding transaction dentro daquele bloco. |
| outputindex | 16 bits | 0 | Índice da funding output dentro da transação. |
Na forma humana, o mesmo valor costuma aparecer como 700000x1337x0. O x é apenas separador. Por baixo, os três campos são empacotados em um inteiro de 64 bits.
Descrição longa do diagrama
O diagrama mostra uma pilha simples de blocos. Um bloco específico está marcado pela altura. Dentro dele há uma lista de transações, com uma transação marcada pelo índice. Dentro dessa transação há saídas numeradas, e a saída zero está destacada como funding output. Ao lado, o valor 700000x1337x0 é decomposto em bloco, transação e saída.
channel_update
O channel_announcement diz que o canal existe. O channel_update diz se uma direção daquele canal pode ser usada para roteamento e quanto custa usar essa direção.
Isso é direcional. Um canal entre Alice e Bob pode ter uma política para Alice -> Bob e outra para Bob -> Alice. Por isso, um canal público normalmente tem dois updates ativos, um por sentido.
| Campo | Tamanho | Função |
|---|---|---|
| signature | 64 bytes | Assinatura do node id responsável por esta direção. |
| chain_hash | 32 bytes | Blockchain da funding output. |
| short_channel_id | 8 bytes | Canal ao qual esta política pertence. |
| timestamp | 4 bytes | Versão temporal do update; updates antigos são ignorados. |
| message_flags | 1 byte | Bit 0 = must_be_one (sempre 1); bit 1 = dont_forward. |
| channel_flags | 1 byte | Bit 0 = direção do update; bit 1 = direção desabilitada. |
| cltv_expiry_delta | 2 bytes | Diferença mínima de CLTV exigida entre HTLC de entrada e de saída. |
| htlc_minimum_msat | 8 bytes | Menor HTLC que o nó aceita encaminhar por essa direção. |
| fee_base_msat | 4 bytes | Taxa fixa cobrada por encaminhamento nessa direção. |
| fee_proportional_millionths | 4 bytes | Taxa proporcional em partes por milhão do valor encaminhado. |
| htlc_maximum_msat | 8 bytes | Maior HTLC aceito nessa direção. |
Direção e flags
Dois bytes carregam quase toda a semântica de controle do update. O channel_flags diz de qual sentido é a política e se ela está ativa; o message_flags descreve o formato da própria mensagem.
| Campo · bit | Nome | Significado |
|---|---|---|
| message_flags · bit 0 | must_be_one | Sempre 1. Historicamente sinalizava a presença de htlc_maximum_msat, hoje um campo obrigatório. |
| message_flags · bit 1 | dont_forward | Update enviado apenas ao peer do canal; não deve ser propagado no gossip global. |
| channel_flags · bit 0 | direction | 0 se o originador do update é node_id_1; 1 se é node_id_2. |
| channel_flags · bit 1 | disable | Marca a direção como temporária ou permanentemente indisponível. |
O bit direction se apoia na ordenação do channel_announcement: valor 0 significa que o update foi assinado por node_id_1, valor 1 que foi por node_id_2. É por isso que um canal saudável costuma ter dois updates, um de cada lado. O bit disable deixa um nó anunciar que sua direção está fora do ar sem fechar o canal, e a busca de caminho deve pular essa direção.
A fórmula de fee anunciada para um hop é:
fee_msat = fee_base_msat + floor(amount_to_forward_msat * fee_proportional_millionths / 1_000_000) O cltv_expiry_delta entra no cálculo de timeout da rota. Cada hop exige que o HTLC de entrada tenha mais blocos de folga que o HTLC de saída. Isso dá tempo para reagir a falhas e fechamentos unilaterais. Veja a relação com locktime e com a operação de HTLCs em canais.
canal: 700000x1337x0
direção: node_id_1 -> node_id_2
fee_base_msat = 1000
fee_proportional_millionths = 250
cltv_expiry_delta = 40
htlc_minimum_msat = 1000
htlc_maximum_msat = 500000000
valor a encaminhar = 200000 msat
fee = 1000 + floor(200000 * 250 / 1000000)
fee = 1050 msat Não confunda política de roteamento com liquidez. O gossip pode dizer que uma direção cobra 1050 msat para encaminhar, mas não revela se há saldo remoto suficiente para encaminhar aquele pagamento agora.
node_announcement
O node_announcement descreve um nó público. Ele ajuda carteiras, exploradores e peers a exibirem e encontrarem aquele nó, mas não cria canal sozinho. Um nó sem canal público relevante não é útil para o grafo de roteamento público.
| Campo | Função |
|---|---|
| signature | Assinatura do node id sobre o anúncio. |
| features | Features do nó, como suporte a campos opcionais e extensões. |
| timestamp | Versão temporal do anúncio. |
| node_id | Chave pública comprimida que identifica o nó Lightning. |
| rgb_color | Cor pública exibida por exploradores e UIs. |
| alias | Nome curto público, não confiável e não único. |
| addresses | Endereços de rede onde outros peers podem tentar conexão. |
O campo addresses é uma lista de descritores, cada um começando por um byte de tipo que diz como interpretar os bytes seguintes. Assim um nó anuncia por onde aceita conexões:
| Tipo | Rede | Tamanho | Formato |
|---|---|---|---|
| 1 | IPv4 | 6 bytes | 4 bytes de endereço e 2 bytes de porta. |
| 2 | IPv6 | 18 bytes | 16 bytes de endereço e 2 bytes de porta. |
| 4 | Tor v3 | 37 bytes | 35 bytes do serviço onion e 2 bytes de porta. |
| 5 | DNS | variável | 1 byte de tamanho, o hostname e 2 bytes de porta. |
O tipo 3 existia para Tor v2 e está obsoleto. Os descritores devem vir em ordem crescente de tipo, e um nó que não reconhece um tipo apenas ignora aquele endereço.
Alias e cor não são identidade forte. A identidade forte é o node id, uma chave pública comprimida. Dois nós podem escolher aliases parecidos, e um alias pode mudar ao longo do tempo.
Sincronização de gossip
Um nó recém-conectado não precisa esperar passivamente o mundo inteiro reenviar todos os anúncios. A BOLT 7 define mensagens de consulta para sincronizar o grafo por faixas de blocos, listas de SCIDs e janelas de timestamp.
| Mensagem | Uso |
|---|---|
| query_channel_range | Pergunta quais SCIDs existem em uma faixa de alturas de bloco. |
| reply_channel_range | Responde com uma lista compacta de SCIDs e pode indicar se a resposta está completa. |
| query_short_channel_ids | Pede os anúncios e updates correspondentes a SCIDs específicos. |
| reply_short_channel_ids_end | Marca o fim da resposta para uma consulta por SCID. |
| gossip_timestamp_filter | Pede apenas mensagens com timestamp dentro de uma janela. |
Como as consultas são codificadas
As listas de SCIDs em query_short_channel_ids e reply_channel_range começam por um byte de codificação. O valor 0 significa um array bruto, oito bytes por SCID. O valor 1 significa compressão zlib, mas a especificação proíbe usá-lo, porque um payload comprimido pequeno poderia forçar o receptor a alocar muita memória.
Para não pedir tudo às cegas, o query_short_channel_ids pode anexar um query_flags, um bitfield por SCID que escolhe exatamente o que se quer daquele canal:
- bit 0: o
channel_announcement; - bits 1 e 2: o
channel_updatede cada lado; - bits 3 e 4: o
node_announcementde cada nó.
O query_channel_range pode ir além e pedir, por TLV, os timestamps e os checksums de cada canal. O checksum é um CRC32C calculado sobre o channel_update ignorando signature e timestamp. Com isso, o reply_channel_range devolve, junto dos SCIDs, informação suficiente para o nó decidir se já tem a versão mais recente de cada canal, evitando rebaixar e rebuscar tudo.
Na prática, a rede precisa equilibrar atualidade e custo. Flooding agressivo demais desperdiçaria banda. Flooding lento demais deixaria carteiras calculando rotas com políticas antigas. Por isso, implementações fazem deduplicação, ignoram updates antigos, aplicam limites de frequência e podam canais fechados ou obsoletos.
Propagação escalonada e limites de spam
O gossip não é retransmitido no instante em que chega. A recomendação é acumular as mensagens e liberá-las em lote a cada 60 segundos, independentemente de quando chegaram. Essa propagação escalonada (staggered broadcast) dilui rajadas, facilita a deduplicação e limita o quanto um nó consegue fazer a rede trabalhar.
- um nó não repassa gossip que não gerou até o peer enviar
gossip_timestamp_filter, então quem só quer o dump inicial não recebe fluxo contínuo à toa; - cada novo update precisa de
timestampestritamente maior que o anterior para aquele par SCID e node id, e updates redundantes devem ser evitados; - ao trocar de política, o nó deve continuar aceitando a política anterior por cerca de 10 minutos, dando folga para o novo update se espalhar;
- dois updates com o mesmo
timestampmas campos diferentes indicam abuso, e o node id responsável pode ir para uma blacklist.
Poda de canais e nós zumbis
O grafo também precisa esquecer o que morreu. Um canal cuja funding output foi gasta é considerado fechado depois de 72 confirmações e removido da visão local; o atraso dá tempo para anúncios de splice se propagarem antes do descarte. Além disso, um canal cujo channel_update mais recente, em qualquer direção, seja mais velho que duas semanas (1209600 segundos) vira um canal zumbi e pode ser podado. E um nó que perdeu todos os canais associados pode ter seu node_announcement removido também.
Montando o grafo de canais
Cada nó constrói seu próprio grafo local. Não existe "o grafo oficial" da Lightning. Existem visões locais que convergem razoavelmente, mas podem divergir por latência, filtros, conexões, canais privados, políticas recentes e informações que ainda não chegaram.
| Mensagem | Elemento no grafo | Dados usados |
|---|---|---|
| channel_announcement | aresta | SCID, dois node ids, chaves Bitcoin e prova on-chain do canal. |
| channel_update | aresta direcional | fees, CLTV delta, limites de HTLC, flag disabled e timestamp. |
| node_announcement | vértice | alias, cor, endereços e features do nó. |
para montar o grafo:
1. guardar channel_announcement válido como canal público
2. anexar channel_update de cada direção ao canal
3. ignorar update com timestamp mais antigo que o conhecido
4. marcar direção como indisponível quando o bit disabled estiver ativo
5. guardar node_announcement somente para node id ligado a canal conhecido
6. podar canais fechados ou inconsistentes com a cadeia
7. entregar o grafo resultante para a busca de caminho
Descrição longa do diagrama
O diagrama mostra um grafo com vários nós conectados por canais. Os nós aparecem como círculos e os canais como linhas. Algumas linhas possuem setas em sentidos diferentes, indicando que cada direção pode ter política própria. Uma caixa lateral lista dados vindos de channel_announcement, channel_update e node_announcement.
Canais públicos vs. privados
Nem todo canal entra no gossip. Um canal privado, ou não anunciado, existe entre dois peers, mas não aparece no grafo público. Ele ainda pode receber ou enviar pagamentos, desde que o pagador receba informação suficiente por outro caminho.
Em invoices BOLT 11, isso aparece como routing hints no campo r. O recebedor inclui uma pequena rota final com node id, SCID, fee base, fee proporcional e CLTV delta para que o pagador consiga chegar até um canal que não descobriria pelo gossip público.
Essa diferença é importante para privacidade: canal privado reduz exposição no grafo público, mas não torna o pagamento invisível para os peers envolvidos. Também aumenta a dependência de hints corretos e atualizados na invoice.
Ferramenta: Short Channel ID
A ferramenta abaixo converte entre a forma humana blocoxtxxsaida, decimal e hexadecimal do SCID. Ela é didática e roda somente no navegador. Não cole dados sensíveis de carteira; SCID de canal público pode ser público, mas exemplos educativos devem usar valores fictícios.
Short Channel ID
Privacidade, segurança e limites
Gossip é público por design. Isso ajuda roteamento e auditoria, mas expõe metadados:
- node id, alias e endereços de rede podem ligar infraestrutura a uma identidade operacional;
- canais públicos revelam funding outputs, capacidade inicial e relação entre dois node ids;
- updates revelam política de fees, CLTV e disponibilidade declarada;
- o grafo não revela liquidez local/remota, então pagamentos ainda podem falhar;
- canais privados não aparecem no grafo, mas podem ser inferidos por routing hints, probing ou comportamento de pagamentos.
Do ponto de vista de segurança, a regra mais importante é não aceitar gossip sem validação. Assinaturas, chain hash, SCID, funding output e timestamps existem para impedir spam barato, impersonação e atualizações antigas sobrescrevendo informação mais nova.
Armadilhas comuns
- Tratar SCID como txid. O SCID aponta para posição no bloco, não é hash da transação.
- Assumir que canal público tem liquidez. Gossip anuncia existência e política, não saldo disponível.
- Ignorar direção. Fees e CLTV delta pertencem a uma direção do canal, não ao canal inteiro.
- Aceitar update antigo. O timestamp evita que informação velha substitua política mais recente.
- Confiar em alias. Alias é metadado visual; node id é a identidade criptográfica.
- Publicar canal sem pensar em privacidade. Um canal público fica ligado a uma funding output on-chain e a dois node ids.
Mapa de dependências conceituais
Antes de ler esta página
- Canais de Pagamento a fundo
- Operação de Canais e Encaminhamento
- Protocolo Wire
- Altura de bloco
- Saídas de transação
Depois desta página
- Busca de Caminho
- Pedidos de Pagamento BOLT 11
- Segurança e Privacidade a fundo
- Ferramenta Short Channel ID
Referências técnicas usadas
- BOLT 7: P2P Node and Channel Discovery
- BOLT 1: Base Protocol
- BOLT 2: Peer Protocol for Channel Management
- BOLT 11: Invoice Protocol for Lightning Payments
Com o grafo em mãos, o próximo problema é escolher uma rota que provavelmente funcione, pese fees, respeite CLTV e lide com falhas. Esse é o assunto da busca de caminho.