diff --git a/lnd.go b/lnd.go index 76b08a114a1..dc13e307ab8 100644 --- a/lnd.go +++ b/lnd.go @@ -19,6 +19,7 @@ import ( "sync" "time" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" proxy "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/lightningnetwork/lnd/autopilot" @@ -623,13 +624,18 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg, multiAcceptor = chanacceptor.NewChainedAcceptor() } + var localTowerPubKey *btcec.PublicKey + if tower != nil { + localTowerPubKey = tower.PubKey() + } + // Set up the core server which will listen for incoming peer // connections. server, err := newServer( ctx, cfg, cfg.Listeners, dbs, activeChainControl, &idKeyDesc, activeChainControl.Cfg.WalletUnlockParams.ChansToRestore, multiAcceptor, torController, tlsManager, leaderElector, - implCfg, + implCfg, localTowerPubKey, ) if err != nil { return mkErr("unable to create server", err) diff --git a/server.go b/server.go index 45992c464cb..317d09c417b 100644 --- a/server.go +++ b/server.go @@ -617,7 +617,8 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr, chanPredicate chanacceptor.ChannelAcceptor, torController *tor.Controller, tlsManager *TLSManager, leaderElector cluster.LeaderElector, - implCfg *ImplementationCfg) (*server, error) { + implCfg *ImplementationCfg, + localTowerPubKey *btcec.PublicKey) (*server, error) { var ( err error @@ -1830,6 +1831,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr, MinBackoff: 10 * time.Second, MaxBackoff: 5 * time.Minute, MaxTasksInMemQueue: cfg.WtClient.MaxTasksInMemQueue, + LocalTowerPubKey: localTowerPubKey, }, policy, anchorPolicy, taprootPolicy, taprootFinalPolicy) if err != nil { return nil, err diff --git a/watchtower/wtclient/manager.go b/watchtower/wtclient/manager.go index 7a39c8ff73e..987272a785f 100644 --- a/watchtower/wtclient/manager.go +++ b/watchtower/wtclient/manager.go @@ -154,6 +154,12 @@ type Config struct { // MaxTasksInMemQueue is the maximum number of backup tasks that should // be kept in-memory. Any more tasks will overflow to disk. MaxTasksInMemQueue uint64 + + // LocalTowerPubKey is the public key of the watchtower server running + // in the same process, or nil if no local tower is active. When set, + // AddTower will warn if the client attempts to register the local tower, + // since it shares the same failure domain as this node. + LocalTowerPubKey *btcec.PublicKey } // Manager manages the various tower clients that are active. A client is @@ -359,6 +365,14 @@ func (m *Manager) Stop() error { // included will be considered when dialing it for session negotiations and // backups. func (m *Manager) AddTower(address *lnwire.NetAddress) error { + if m.cfg.LocalTowerPubKey != nil && + address.IdentityKey.IsEqual(m.cfg.LocalTowerPubKey) { + + log.Warnf("Connecting to local watchtower: " + + "if this node goes offline the tower will " + + "also be unavailable") + } + // We'll start by updating our persisted state, followed by the // in-memory state of each client, with the new tower. This might not // actually be a new tower, but it might include a new address at which