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 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 é:

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.

O pacote onion como uma cebola de camadas criptografadas, uma por salto: a externa para o primeiro nó, e o núcleo para o destino. Tamanho fixo de 1300 bytes.

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 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.

Derivação do segredo compartilhado: a chave efêmera da origem combinada por ECDH com a chave pública de cada nó gera um segredo, do qual saem as chaves de cifragem (rho) e de HMAC (mu).

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.

Um nó descascando uma camada: entra a cebola + ponto efêmero, o nó deriva o segredo, verifica o HMAC, lê suas instruções (valor, cltv, próximo salto) e encaminha a cebola interna.

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):

Ícone Ferramenta Construtor de Rota (Onion)
Ícone Ferramenta

Construtor de Rota (Onion)

Defina o destino e os nós intermediários. A ferramenta calcula (do destino para a origem) o valor e o CLTV de cada camada — exatamente o que cada nó vê ao descascar a cebola.

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.