Roteamento Onion
Como esconder o caminho de um pagamento
⚡ Lightning · Técnico
No encaminhamento, vimos que o Bob ajuda a Alice a pagar a Carol. Mas isso levanta um problema de privacidade: o Bob deveria saber que a Alice é a origem e a Carol é o destino? De jeito nenhum. O roteamento onion garante que cada nó saiba só de quem recebeu e para quem repassar — nada mais.
A ideia da cebola
A origem monta um pacote em camadas criptografadas, uma para cada salto — como uma cebola. Cada nó consegue descascar exatamente uma camada (a sua), e o que encontra dentro é:
- as instruções para ele: quanto encaminhar (
amt_to_forward), com qual prazo (outgoing_cltv_value) e para qual canal (short_channel_iddo próximo salto); - a cebola interna (as camadas restantes), que ele repassa ao próximo nó sem conseguir ler.
Ou seja: o Bob descasca a camada dele, descobre "encaminhe X para a Carol", e passa adiante uma cebola menor — sem nunca saber quem montou tudo nem quantos saltos ainda faltam.
Tamanho fixo: ninguém sabe sua posição
Se a cebola encolhesse a cada camada descascada, um nó poderia adivinhar sua posição na rota pelo tamanho do pacote. Para evitar isso, o pacote onion tem tamanho fixo (o payload de roteamento tem 1300 bytes). Conforme as camadas são removidas, um preenchimento (filler) pseudoaleatório é adicionado no fim, mantendo o tamanho constante. Assim, todo nó vê um pacote do mesmo tamanho — seja ele o primeiro ou o último salto.
Como as camadas são cifradas
A Lightning usa um esquema baseado no Sphinx (BOLT 4). A sacada é gerar um segredo compartilhado entre a origem e cada nó da rota, sem que os nós conversem antes:
- A origem cria uma chave efêmera e faz um ECDH (Diffie-Hellman em curva elíptica) com a chave pública de cada nó. Isso dá um segredo compartilhado por salto.
- Desse segredo derivam-se chaves específicas: uma para cifrar a camada (rho), uma para o HMAC de integridade (mu), e outras para o preenchimento.
- A chave efêmera é "cegada" (blinded) a cada salto, então cada nó faz o ECDH com um ponto efêmero diferente — mas a origem já pré-calculou todos.
A origem monta a cebola de dentro para fora (do destino para o primeiro salto), e cada camada leva um HMAC para o nó verificar que a sua parte não foi adulterada.
Descascando uma camada
Quando um nó recebe a cebola (junto com o ponto efêmero atual), ele: refaz o ECDH para obter o segredo compartilhado, deriva as chaves, verifica o HMAC, decifra a sua camada para ler as instruções, "cega" o ponto efêmero para o próximo salto e encaminha a cebola interna. Os payloads hoje são TLV (type-length-value), o que permite incluir campos novos sem quebrar nós antigos.
Monte uma rota e veja as camadas que a origem constrói (com os valores e CLTV de cada salto calculados de trás para frente):
Construtor de Rota (Onion)
E quando algo falha?
Os erros também voltam cifrados em camadas. O nó onde o pagamento falhou monta uma mensagem de erro e a cifra com o segredo compartilhado dele; cada nó no caminho de volta adiciona a sua camada. Quando o erro chega à origem, só ela consegue descascar tudo e descobrir qual nó falhou e por quê — sem revelar isso aos intermediários. É o que permite à carteira tentar outra rota de forma inteligente.
Caminhos cegados (route blinding)
Uma adição mais recente são os caminhos cegados (blinded paths), usados pelos offers (BOLT 12). Eles deixam o destinatário esconder a parte final da rota — o pagador monta a cebola até um ponto de entrada, e dali em diante o caminho é cego, melhorando a privacidade de quem recebe (e não só de quem paga).
Até aqui assumimos que a origem já conhece a rota. Mas como ela descobre os nós e canais que existem? É o gossip e o grafo de canais — a próxima página.