lnd/watchtower/wtclient/interface_test.go
Erick Cestari 2ae1db83b3
multi: drop tor v2 onion production, keep wire codec faithful
Tor stopped serving v2 onion services in October 2021; lnd should not
produce v2 addresses anymore, but it must still verify signatures on
and re-broadcast peer NodeAnnouncement messages that carry v2 entries.

Stop accepting v2 as configuration input (lncfg), strip the legacy
`--tor.v2` flag from the sample config, and remove the
`tor.OnionHostToFakeIP` helper. Operator entry points (`--externalip`,
`--listen`, `lncli connect`, `lncli wtclient towers add`) fail fast on
a v2 `.onion` string, so upgrading nodes must remove any v2 entry from
`lnd.conf` before lnd will start.

Filter persisted v2 state before use without rewriting on-disk records:
the self-announcement builder strips any v2 entry inherited from the
stored self-node; the watchtower client drops v2 entries from each
persisted tower's address list (skipping the tower entirely if no
non-v2 address remains); the autopilot connector, graph bootstrapper,
and static-channel backup restore paths skip v2 entries before
attempting outbound dials. Restrict the Tor controller's ADD_ONION
path to v3 keys, including the encrypted on-disk legacy-key fallback.

For inbound announcements, keep the wire codec wire-faithful:
`lnwire.WriteOnionAddr`, `graph/db.encodeOnionAddr`, and the matching
decoders round-trip v2 bytes so `DataToSign` reproduces the bytes the
remote peer signed, signature validation succeeds, and the announcement
is persisted to the graph DB and re-broadcast across restarts byte-for-
byte. RPC surfaces continue to expose the full address set so external
tools can independently reproduce and verify the signed bytes.

Add a netann regression test that signs a [v3, v2, ipv4] announcement,
round-trips it through Encode/Decode, verifies the signature, and
confirms the resulting models.Node preserves the v2 entry. Add a
graph bootstrapper test asserting v2 entries are skipped while v3 and
plain TCP entries on the same node still surface as bootstrap
candidates.
2026-05-22 09:42:37 -03:00

57 lines
1.6 KiB
Go

package wtclient
import (
"net"
"testing"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/lightningnetwork/lnd/tor"
"github.com/lightningnetwork/lnd/watchtower/wtdb"
"github.com/stretchr/testify/require"
)
// TestNewTowerFromDBTowerFiltersV2Onion asserts that NewTowerFromDBTower drops
// any persisted Tor v2 .onion entries before constructing the address
// iterator, that mixed lists still surface the remaining v3/tcp addresses, and
// that a tower whose addresses are exclusively v2 surfaces
// ErrTowerOnlyV2Onion so the caller can skip it without touching the DB.
func TestNewTowerFromDBTowerFiltersV2Onion(t *testing.T) {
t.Parallel()
priv, err := btcec.NewPrivateKey()
require.NoError(t, err)
v2 := &tor.OnionAddr{
OnionService: "3g2upl4pq6kufc4m.onion",
Port: 9911,
}
v3 := &tor.OnionAddr{
OnionService: "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnz" +
"jpbi7utijcltosqemad.onion",
Port: 9911,
}
tcp := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 9911}
t.Run("mixed addresses keep v3/tcp", func(t *testing.T) {
t.Parallel()
tower, err := NewTowerFromDBTower(&wtdb.Tower{
ID: 7,
IdentityKey: priv.PubKey(),
Addresses: []net.Addr{v2, v3, tcp, v2},
})
require.NoError(t, err)
require.Equal(t, []net.Addr{v3, tcp}, tower.Addresses.GetAll())
})
t.Run("only v2 addresses returns sentinel", func(t *testing.T) {
t.Parallel()
_, err := NewTowerFromDBTower(&wtdb.Tower{
ID: 7,
IdentityKey: priv.PubKey(),
Addresses: []net.Addr{v2, v2},
})
require.ErrorIs(t, err, ErrTowerOnlyV2Onion)
})
}