Watchtowers y el split del RDTS: qué son, cómo funcionan, y una torre para compartir
Guía técnica + anuncio de servicio comunitario
El problema que resuelve un watchtower#
En Lightning, cada canal tiene un estado actual y un historial de estados anteriores. Tu contraparte conserva copias firmadas de todos los estados por los que habéis pasado. Si es deshonesta, puede publicar en la cadena un estado antiguo en el que ella tenía más saldo. Eso es un breach.
La defensa existe y es elegante: cuando alguien publica un estado revocado, ha revelado una clave que permite al otro lado barrer todo el saldo del canal como castigo. Es la justice transaction.
Pero requiere estar mirando. El to_self_delay de tu canal —típicamente 144 bloques, un día— es toda la ventana que tienes para reaccionar. Si tu nodo está apagado, sin red, o simplemente no arranca durante esas 24 horas, el ladrón se lleva los fondos y no hay recurso.
Un watchtower es un tercero que vigila por ti mientras tú no estás.
Cómo funciona por dentro#
Quién envía qué#
Tú envías. La torre solo almacena y vigila.
En cada actualización de estado de tus canales, tu LND prepara un blob que contiene la justice transaction ya firmada y lista para difundir. Ese blob va cifrado con una clave derivada del txid del commitment revocado.
Junto al blob, envías un hint de 16 bytes: los primeros bytes de ese mismo txid.
Aquí está lo bonito del diseño: la torre no puede descifrar el blob. Solo tiene el hint. Se dedica a escanear cada bloque nuevo comparando los txids contra su índice de hints. Si encuentra coincidencia, ya tiene el txid completo — y solo entonces puede derivar la clave, descifrar el blob y difundir la justice transaction.
Traducido: la torre no sabe cuántos canales tienes, ni con quién, ni con cuánto saldo. Solo actúa cuando el propio ladrón le entrega la clave publicando el estado robado.
Sesiones y política#
Antes de enviar nada hay que negociar una sesión, un acuerdo con parámetros que quedan fijos durante toda su vida:
| Parámetro | Qué es | Valor típico |
|---|---|---|
max_updates |
estados que caben antes de agotarse | 1024 |
sweep_fee_rate |
fee de la justice tx | 10 sat/vB |
reward_rate |
comisión de la torre | 0 si es altruista |
blob_type |
tipo de commitment | LEGACY / ANCHOR / TAPROOT |
lncli wtclient policy
lncli wtclient policy --anchor
Un detalle que muerde: el sweep_fee_rate queda congelado al negociar. Si acordaste 10 sat/vB con la mempool tranquila y el breach ocurre en plena congestión, tu justice transaction puede no confirmar dentro del to_self_delay. Es un límite del diseño, no un fallo de configuración.
Si te preocupa, súbelo antes de negociar sesiones nuevas:
[wtclient]
wtclient.active=true
wtclient.sweep-fee-rate=25
Requiere reinicio, y solo afecta a sesiones futuras. Las existentes conservan su valor.
Los cuatro clientes#
En los logs verás siempre cuatro líneas:
WTCL: (legacy) Client stats: ...
WTCL: (anchor) Client stats: ...
WTCL: (taproot) Client stats: ...
WTCL: (taproot-final) Client stats: ...
No es redundancia. Son cuatro clientes independientes, uno por tipo de commitment, porque el formato del blob difiere. Cada uno mantiene sus propias sesiones. Si todos tus canales son anchor, solo ese acumulará backups y los otros tres estarán a cero.
La rotación: lo que casi nadie cuenta#
Esto es lo más importante y lo peor documentado:
Registrar N torres no te da N copias. Te da una activa y N−1 suplentes.
Cada cliente mantiene una sola sesión activa a la vez. No reparte tus backups en paralelo entre todas las torres registradas. Elige una candidata, negocia, y sube todo ahí.
Rota cuando la sesión se agota (max_updates), cuando la torre falla al conectar, o cuando la desactivas a mano.
Y aquí está el agujero: no rota cuando la torre está viva pero rechaza a nivel de protocolo. Si una torre responde con CodePermanentFailure, el cliente se queda insistiendo sobre una sesión muerta indefinidamente. Los backups se encolan (accepted sube) pero nunca se suben (acquired=0), y no busca alternativa.
Lo he vivido: seis torres registradas y cero cobertura efectiva durante horas, sin ningún aviso.
Diagnóstico: los comandos que importan#
# Lo único crítico: ¿hay sesión activa?
lncli wtclient stats
| Campo | Lectura |
|---|---|
num_backups |
subidos con éxito |
num_pending_backups |
en cola sin confirmar |
num_failed_backups |
fallos |
num_sessions_acquired |
0 = SIN COBERTURA |
num_sessions_exhausted |
sesiones llenas, se renegocian solas |
# ¿Qué torres son candidatas? (lento si tienes histórico grande)
lncli wtclient towers | jq -r '.towers[] | .pubkey[0:16] + " candidata=" + (.active_session_candidate|tostring)'
# ¿Cuál está subiendo DE VERDAD? — la única fuente fiable
sudo journalctl -u lnd --since "2 hours ago" | grep -i "uploaded backup" | tail -5
# ¿Hay rechazos?
sudo journalctl -u lnd --since "2 hours ago" | grep -ciE "CodePermanentFailure|unable to upload"
# ¿La torre responde por Tor?
timeout 30 torsocks nc -vz <onion> 9911; echo "exit=$?"
La señal de alarma es acquired=0 sostenido, sobre todo si accepted sube. Significa que encolas y no subes. Móntate un cron horario que lo vigile; es el fallo que pasa desapercibido.
Dos notas para quien corra LND sobre PostgreSQL: wtclient towers puede tardar 15–20 segundos porque el subsistema watchtower todavía usa emulación KV y recorre la tabla entera. No lo mates con timeout cortos — está trabajando. Y si remove te da tower has unacked updates, usa deactivate, que no valida eso.
La parte comunitaria: una torre para el split del RDTS#
Si corres Bitcoin Knots con consensusrules=rdts, tu nodo rechaza los bloques que no señalizan. En caso de split persistente, se queda ciego a la otra cadena.
Y ahí está el riesgo: si un socio tuyo publica un estado viejo en la cadena que tu nodo no ve, no te enteras. No es que llegues tarde — es que no llegas.
Una torre cuyo backend sigue la cadena "status quo" cubre exactamente ese punto ciego.
La línea para añadirla#
lncli wtclient add 03159aa7d731426e7b2f59afc76d2b652d9e60c58bc8fd9dc8ece0c8622325df72@k3cijm4tqvdfbiyrm2fzpuzl3fd3fh2p422h5gilrz56kda7rqdh2aid.onion:9911
Requisitos en tu lnd.conf:
[wtclient]
wtclient.active=true
Estado verificado de la torre: sincronizada con la cadena, servidor arrancado, onion alcanzable de punta a punta por Tor, LND v0.21.1 (acepta todos los tipos de canal, incluido taproot-final), y tope de almacenamiento configurado.
Registra cuanto antes. Ninguna torre cubre lo que se revocó antes de que te registraras. La protección empieza el día que negocias sesión, no antes.
⚠️ AÑADIRLA NO SIGNIFICA QUE ESTÉ FUNCIONANDO#
Esto es lo más importante de todo el artículo. Léelo dos veces.
Cuando ejecutas wtclient add, LND responde {} y no dice nada más. Ese {} significa "torre registrada en mi base de datos". No significa que esté recibiendo tus backups.
Por lo que vimos arriba: el cliente mantiene una sola sesión activa a la vez. Si ya tienes otra torre funcionando, esta se queda de suplente y no recibirá ni un solo estado hasta que la primera se agote o falle.
Y hay una segunda trampa: la negociación de sesión es perezosa. No ocurre al añadir la torre, sino cuando hay un cambio de estado en algún canal. Puedes tener la torre registrada, ser la única candidata, y seguir con cero sesiones durante horas si no ha habido movimiento.
Resultado: es perfectamente posible acabar con seis torres registradas, un {} bonito por cada una, y cero cobertura real. Sin ningún aviso.
Verifica que funciona de verdad#
Paso 1 — ¿hay sesión activa?
lncli wtclient stats
Si num_sessions_acquired es 0, no estás protegido. Da igual cuántas torres tengas registradas.
Paso 2 — ¿a qué torre está subiendo?
sudo journalctl -u lnd --since "2 hours ago" | grep -i "attempting to dial tower" | tail -3
Esa onion es la que está trabajando. Si no es la que esperas, tu torre nueva está de suplente.
Paso 3 — ¿sube o solo encola?
sudo journalctl -u lnd --since "1 hour ago" | grep -iE "uploaded backup|Queued backup" | tail -5
Busca uploaded backup, con seqnum que avanza. Si solo ves Queued backup, estás encolando sin subir: la cola crece y no llega nada a la torre.
Si quieres que sea ESTA la que trabaje#
# 1. Ver quién es candidata (tarda ~20s con histórico grande)
lncli wtclient towers | jq -r '.towers[] | .pubkey[0:16] + " candidata=" + (.active_session_candidate|tostring)'
# 2. Desactivar las demás
lncli wtclient deactivate <PUBKEY_DE_LAS_OTRAS>
# 3. Forzar la negociación con un pago mínimo saliente
# (la sesión no se negocia sola sin cambio de estado)
Con el log abierto mientras tanto:
sudo journalctl -fu lnd | grep -iE "Acquired new session|attempting to dial tower|uploaded backup"
Lo que confirma el éxito es esto:
[INF] WTCL: (anchor) Acquired new session with id=...
[INF] WTCL: (anchor) SessionQueue(...) attempting to dial tower at k3cijm4t...onion:9911
[INF] WTCL: (anchor) SessionQueue(...) uploaded backup(...) seqnum=1
seqnum=1 contra la onion correcta. Hasta que no veas eso, no has añadido protección — has añadido una entrada en una base de datos.
Monta el aviso#
El fallo silencioso es el peligro real. Un cron horario que vigile acquired=0 te ahorra descubrirlo tarde:
#!/bin/bash
A=$(lncli wtclient stats 2>/dev/null | jq -r '.num_sessions_acquired')
[ "$A" = "0" ] && echo "$(date -Is) ALERTA: sin sesion de watchtower activa"
Y ahora la letra pequeña, que es la parte importante#
Esto es beta, montado en poco tiempo. Si tienes canales que te preocupan de cara al split, cerrarlos cooperativamente sigue siendo lo que menos puede salir mal. Un watchtower es una red de seguridad, no un plan.
Esta torre vigila la cadena "status quo". A quien no corra Knots con RDTS no le aporta nada — su nodo ya ve esa cadena.
No des por hecho que funciona. Ver la sección anterior. Verifica con lncli wtclient stats que num_sessions_acquired no es cero, y en el log que hay uploaded backup contra esta onion. Si no lo compruebas, puedes pasar semanas creyéndote cubierto sin estarlo.
Redundancia física. Si montas tu propia torre en casa, un corte de luz os tumba a los dos a la vez — justo el escenario en que una torre debe actuar. Combinar una torre propia con una remota cubre ambos casos.
Cierre#
El watchtower es de las piezas mejor diseñadas de Lightning: privacidad real por construcción, coste mínimo, y funciona sin que la torre sepa nada de ti.
Pero la implementación tiene bordes afilados que no están documentados, y el peor es que puedes creerte protegido durante horas sin estarlo. Móntate la monitorización antes de necesitarla.
Servicio ofrecido sin garantías. Si un día se apaga, se avisa.
Publicado desde un nodo MiniBolt. Preguntas y correcciones, bienvenidas.


Comments
No comments yet. Start the conversation.