Mensagens Wire e TLV
Inspecione tipos Lightning e a estrutura canônica de streams TLV
Depois que a camada de transporte decripta um frame, o receptor obtém uma mensagem Lightning: um type de 2 bytes em big-endian, seguido pelo payload definido para aquele tipo e, quando previsto, uma extensão TLV.
Esta ferramenta executa duas tarefas limitadas: identifica o número do tipo usando um catálogo didático parcial e desmonta a estrutura genérica de um stream TLV. Ela não valida o schema completo, não confirma suporte por uma implementação e não executa mensagens.
Conteúdo
Ferramenta
Use somente bytes públicos, fictícios ou de teste. Os exemplos mostram mensagens completas e incompletas de propósito, tipos custom desconhecidos, TLV canônico e erros estruturais.
Mensagens Wire e TLV
Fonte primária
A BOLT 1 define o envelope da mensagem, os grupos numéricos, a regra par/ímpar, o formato TLV, o inteiro BigSize e vetores oficiais de teste. O formato interno de cada payload pode vir da própria BOLT 1 ou de especificações como BOLT 2, BOLT 4 e BOLT 7.
Transporte, wire e schema
- A BOLT 8 autentica peers, cifra o tráfego e delimita frames.
- A BOLT 1 lê os 2 primeiros bytes plaintext como
type. - O BOLT responsável pelo tipo define os campos e as regras do payload.
- Features negociadas e o estado da conexão ou do canal determinam se a mensagem pode ser aceita naquele momento.
Identificar 0012 como ping não basta para validar a mensagem. Ainda é preciso ler num_pong_bytes, byteslen, conferir o tamanho de ignored e aplicar os limites definidos pela BOLT 1.
Anatomia da mensagem
Descrição longa do diagrama
Uma barra horizontal representa os bytes plaintext de uma mensagem. Os dois primeiros bytes formam o campo type em big-endian. A região seguinte é o payload de tamanho variável, interpretado conforme o tipo. No fim pode existir uma extensão composta por registros TLV. O diagrama deixa a camada de transporte fora da barra porque a decriptação e o framing já aconteceram.
| Faixa | Grupo | Uso |
|---|---|---|
| 0–31 | Setup e controle | Conexão, init, features, warning, error, ping e pong. |
| 32–127 | Canal | Abertura, financiamento e fechamento de canais. |
| 128–255 | Commitment | HTLCs, assinaturas, revogações, fees e ressincronização. |
| 256–511 | Roteamento | Gossip, anúncios, updates e consultas do grafo. |
| 32768–65535 | Custom | Mensagens experimentais ou específicas de aplicações. |
A faixa 512–32767 não pertence a um dos cinco grupos base listados pela BOLT 1. A ferramenta informa isso como classificação numérica; não tenta adivinhar se um número foi reservado, proposto em outro documento ou usado por uma implementação.
A mensagem inteira, incluindo os 2 bytes de type, precisa caber no limite de 65.535 bytes do transporte. Mensagens de canal com channel_id compartilham uma única conexão entre os mesmos peers; o identificador direciona cada mensagem ao canal correspondente.
Conhecido, desconhecido e custom
“Conhecido” é uma propriedade do receptor e do contexto, não apenas de uma tabela. Um número pode estar atribuído em um BOLT atual, mas ser desconhecido por uma implementação antiga. Também pode exigir feature negotiation. Por isso a ferramenta usa a expressão catálogo parcial: encontrar um nome não prova que seu nó suporte ou aceite a mensagem.
| Paridade | Recepção | Envio |
|---|---|---|
| Ímpar | O receptor deve ignorar a mensagem desconhecida. | Pode ser usado quando receptores sem suporte devem ignorar os dados. |
| Par | O receptor deve fechar a conexão e pode falhar os canais. | Não deve ser enviado sem atribuição conhecida ou negociação prévia. |
Na faixa custom, 0x8000 é par e 0x8001 é ímpar. Isso classifica o comportamento de um receptor que não conhece o tipo; não declara que qualquer um deles esteja atribuído ou suportado.
BigSize
Os campos type e length de um registro TLV são inteiros uint64 codificados como BigSize. O formato lembra o CompactSize do Bitcoin, mas os inteiros multibyte do BigSize usam big-endian.
| Intervalo | Bytes | Exemplo mínimo |
|---|---|---|
| 0–252 | 1 | fc = 252 |
| 253–65.535 | 3 | fd00fd = 253 |
| 65.536–4.294.967.295 | 5 | fe00010000 = 65.536 |
| 4.294.967.296–264-1 | 9 | ff0000000100000000 = 4.294.967.296 |
A codificação deve ser mínima. fd00fc também produziria numericamente 252, mas é inválido porque fc usa menos bytes. Essa unicidade é importante para parsers e para estruturas assinadas.
Stream TLV
Um registro concatena três partes:
[ type: BigSize ][ length: BigSize ][ value: length bytes ]
O parser genérico pode verificar BigSize mínimo, ordem, duplicação e truncamento. Ele não pode, sem receber o schema daquele stream, saber se o type está definido, se o value tem o formato correto ou se um peer negociou suporte.
O namespace também importa. Types abaixo de 216 são reservados para a especificação Lightning; types a partir de 216 ficam disponíveis para registros custom. Em ambos os espaços, se um type for realmente desconhecido, par faz o parse falhar e ímpar permite descartar exatamente os bytes indicados por length.
Exemplos trabalhados
init mínimo
0010 0000 0000
^^^^ ^^^^ ^^^^
type gflen flen
type = 0x0010 = 16 = init
globalfeatures = 0 bytes
features = 0 bytes Este exemplo é completo e tem 6 bytes. Já 0010 contém somente o type: a ferramenta consegue nomeá-lo, mas alerta implicitamente pela contagem de payload que ainda não houve validação do schema.
Dois registros TLV
c9 01 2a cb 01 04
^^ ^^ ^^ ^^ ^^ ^^
T L V T L V
registro 1: type 201, length 1, value 2a
registro 2: type 203, length 1, value 04 Os types são ímpares, estão em ordem crescente e os values têm o tamanho declarado. O stream é estruturalmente canônico. Sem um schema específico, porém, não se pode afirmar o significado de 2a ou 04.
Falhas que a ferramenta detecta
c90101c90102: repete o type 201.fd00fc0100: type 252 usa BigSize não mínimo.c9022a: length declara 2 bytes, mas resta somente 1 byte de value.
Limites e armadilhas
- Confundir reconhecimento com suporte. O catálogo parcial só associa alguns números a nomes.
- Validar apenas o type. Payload, features, assinaturas e estado do canal continuam pendentes.
- Ler inteiros em little-endian. A BOLT 1 usa big-endian salvo indicação contrária.
- Tratar TLV par como automaticamente válido. Se for desconhecido no schema, o stream deve falhar.
- Ignorar ordem ou duplicação. Types devem ser estritamente crescentes.
- Aceitar BigSize não mínimo. Representações alternativas do mesmo inteiro não são canônicas.
- Confundir TLV genérico com extensão de mensagem. TLV também aparece em payload onion, BOLT 12 e vários namespaces específicos.