/ config_builder.go
config_builder.go
   1  package lnd
   2  
   3  import (
   4  	"bytes"
   5  	"context"
   6  	"database/sql"
   7  	"errors"
   8  	"fmt"
   9  	"net"
  10  	"os"
  11  	"path/filepath"
  12  	"sort"
  13  	"strconv"
  14  	"strings"
  15  	"sync/atomic"
  16  	"time"
  17  
  18  	"github.com/btcsuite/btcd/chaincfg"
  19  	"github.com/btcsuite/btcd/chaincfg/chainhash"
  20  	"github.com/btcsuite/btcd/wire"
  21  	"github.com/btcsuite/btclog/v2"
  22  	"github.com/btcsuite/btcwallet/chain"
  23  	"github.com/btcsuite/btcwallet/waddrmgr"
  24  	"github.com/btcsuite/btcwallet/wallet"
  25  	"github.com/btcsuite/btcwallet/walletdb"
  26  	proxy "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
  27  	"github.com/lightninglabs/neutrino"
  28  	"github.com/lightninglabs/neutrino/blockntfns"
  29  	"github.com/lightninglabs/neutrino/headerfs"
  30  	"github.com/lightninglabs/neutrino/pushtx"
  31  	"github.com/lightningnetwork/lnd/blockcache"
  32  	"github.com/lightningnetwork/lnd/chainntnfs"
  33  	"github.com/lightningnetwork/lnd/chainreg"
  34  	"github.com/lightningnetwork/lnd/channeldb"
  35  	"github.com/lightningnetwork/lnd/clock"
  36  	"github.com/lightningnetwork/lnd/fn/v2"
  37  	"github.com/lightningnetwork/lnd/funding"
  38  	graphdb "github.com/lightningnetwork/lnd/graph/db"
  39  	graphdbmig1 "github.com/lightningnetwork/lnd/graph/db/migration1"
  40  	graphmig1sqlc "github.com/lightningnetwork/lnd/graph/db/migration1/sqlc"
  41  	"github.com/lightningnetwork/lnd/htlcswitch"
  42  	"github.com/lightningnetwork/lnd/invoices"
  43  	"github.com/lightningnetwork/lnd/keychain"
  44  	"github.com/lightningnetwork/lnd/kvdb"
  45  	"github.com/lightningnetwork/lnd/lncfg"
  46  	"github.com/lightningnetwork/lnd/lnrpc"
  47  	"github.com/lightningnetwork/lnd/lnwallet"
  48  	"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
  49  	"github.com/lightningnetwork/lnd/lnwallet/chancloser"
  50  	"github.com/lightningnetwork/lnd/lnwallet/rpcwallet"
  51  	"github.com/lightningnetwork/lnd/macaroons"
  52  	"github.com/lightningnetwork/lnd/msgmux"
  53  	paymentsdb "github.com/lightningnetwork/lnd/payments/db"
  54  	paymentsmig1 "github.com/lightningnetwork/lnd/payments/db/migration1"
  55  	paymentsmig1sqlc "github.com/lightningnetwork/lnd/payments/db/migration1/sqlc"
  56  	"github.com/lightningnetwork/lnd/rpcperms"
  57  	"github.com/lightningnetwork/lnd/signal"
  58  	"github.com/lightningnetwork/lnd/sqldb"
  59  	"github.com/lightningnetwork/lnd/sqldb/sqlc"
  60  	"github.com/lightningnetwork/lnd/sweep"
  61  	"github.com/lightningnetwork/lnd/walletunlocker"
  62  	"github.com/lightningnetwork/lnd/watchtower"
  63  	"github.com/lightningnetwork/lnd/watchtower/wtclient"
  64  	"github.com/lightningnetwork/lnd/watchtower/wtdb"
  65  	"google.golang.org/grpc"
  66  	"gopkg.in/macaroon-bakery.v2/bakery"
  67  )
  68  
  69  const (
  70  	// invoiceMigrationBatchSize is the number of invoices that will be
  71  	// migrated in a single batch.
  72  	invoiceMigrationBatchSize = 1000
  73  
  74  	// invoiceMigration is the version of the migration that will be used to
  75  	// migrate invoices from the kvdb to the sql database.
  76  	invoiceMigration = 7
  77  
  78  	// graphMigration is the version number for the graph migration
  79  	// that migrates the KV graph to the native SQL schema.
  80  	graphMigration = 10
  81  
  82  	// paymentMigration is the version number for the payments migration
  83  	// that migrates KV payments to the native SQL schema.
  84  	paymentMigration = 14
  85  )
  86  
  87  // GrpcRegistrar is an interface that must be satisfied by an external subserver
  88  // that wants to be able to register its own gRPC server onto lnd's main
  89  // grpc.Server instance.
  90  type GrpcRegistrar interface {
  91  	// RegisterGrpcSubserver is called for each net.Listener on which lnd
  92  	// creates a grpc.Server instance. External subservers implementing this
  93  	// method can then register their own gRPC server structs to the main
  94  	// server instance.
  95  	RegisterGrpcSubserver(*grpc.Server) error
  96  }
  97  
  98  // RestRegistrar is an interface that must be satisfied by an external subserver
  99  // that wants to be able to register its own REST mux onto lnd's main
 100  // proxy.ServeMux instance.
 101  type RestRegistrar interface {
 102  	// RegisterRestSubserver is called after lnd creates the main
 103  	// proxy.ServeMux instance. External subservers implementing this method
 104  	// can then register their own REST proxy stubs to the main server
 105  	// instance.
 106  	RegisterRestSubserver(context.Context, *proxy.ServeMux, string,
 107  		[]grpc.DialOption) error
 108  }
 109  
 110  // ExternalValidator is an interface that must be satisfied by an external
 111  // macaroon validator.
 112  type ExternalValidator interface {
 113  	macaroons.MacaroonValidator
 114  
 115  	// Permissions returns the permissions that the external validator is
 116  	// validating. It is a map between the full HTTP URI of each RPC and its
 117  	// required macaroon permissions. If multiple action/entity tuples are
 118  	// specified per URI, they are all required. See rpcserver.go for a list
 119  	// of valid action and entity values.
 120  	Permissions() map[string][]bakery.Op
 121  }
 122  
 123  // DatabaseBuilder is an interface that must be satisfied by the implementation
 124  // that provides lnd's main database backend instances.
 125  type DatabaseBuilder interface {
 126  	// BuildDatabase extracts the current databases that we'll use for
 127  	// normal operation in the daemon. A function closure that closes all
 128  	// opened databases is also returned.
 129  	BuildDatabase(ctx context.Context) (*DatabaseInstances, func(), error)
 130  }
 131  
 132  // WalletConfigBuilder is an interface that must be satisfied by a custom wallet
 133  // implementation.
 134  type WalletConfigBuilder interface {
 135  	// BuildWalletConfig is responsible for creating or unlocking and then
 136  	// fully initializing a wallet.
 137  	BuildWalletConfig(context.Context, *DatabaseInstances, *AuxComponents,
 138  		*rpcperms.InterceptorChain,
 139  		[]*ListenerWithSignal) (*chainreg.PartialChainControl,
 140  		*btcwallet.Config, func(), error)
 141  }
 142  
 143  // ChainControlBuilder is an interface that must be satisfied by a custom wallet
 144  // implementation.
 145  type ChainControlBuilder interface {
 146  	// BuildChainControl is responsible for creating a fully populated chain
 147  	// control instance from a wallet.
 148  	BuildChainControl(*chainreg.PartialChainControl,
 149  		*btcwallet.Config) (*chainreg.ChainControl, func(), error)
 150  }
 151  
 152  // ImplementationCfg is a struct that holds all configuration items for
 153  // components that can be implemented outside lnd itself.
 154  type ImplementationCfg struct {
 155  	// GrpcRegistrar is a type that can register additional gRPC subservers
 156  	// before the main gRPC server is started.
 157  	GrpcRegistrar
 158  
 159  	// RestRegistrar is a type that can register additional REST subservers
 160  	// before the main REST proxy is started.
 161  	RestRegistrar
 162  
 163  	// ExternalValidator is a type that can provide external macaroon
 164  	// validation.
 165  	ExternalValidator
 166  
 167  	// DatabaseBuilder is a type that can provide lnd's main database
 168  	// backend instances.
 169  	DatabaseBuilder
 170  
 171  	// WalletConfigBuilder is a type that can provide a wallet configuration
 172  	// with a fully loaded and unlocked wallet.
 173  	WalletConfigBuilder
 174  
 175  	// ChainControlBuilder is a type that can provide a custom wallet
 176  	// implementation.
 177  	ChainControlBuilder
 178  
 179  	// AuxComponents is a set of auxiliary components that can be used by
 180  	// lnd for certain custom channel types.
 181  	AuxComponents
 182  }
 183  
 184  // AuxComponents is a set of auxiliary components that can be used by lnd for
 185  // certain custom channel types.
 186  type AuxComponents struct {
 187  	// AuxLeafStore is an optional data source that can be used by custom
 188  	// channels to fetch+store various data.
 189  	AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
 190  
 191  	// TrafficShaper is an optional traffic shaper that can be used to
 192  	// control the outgoing channel of a payment.
 193  	TrafficShaper fn.Option[htlcswitch.AuxTrafficShaper]
 194  
 195  	// MsgRouter is an optional message router that if set will be used in
 196  	// place of a new blank default message router.
 197  	MsgRouter fn.Option[msgmux.Router]
 198  
 199  	// AuxFundingController is an optional controller that can be used to
 200  	// modify the way we handle certain custom channel types. It's also
 201  	// able to automatically handle new custom protocol messages related to
 202  	// the funding process.
 203  	AuxFundingController fn.Option[funding.AuxFundingController]
 204  
 205  	// AuxSigner is an optional signer that can be used to sign auxiliary
 206  	// leaves for certain custom channel types.
 207  	AuxSigner fn.Option[lnwallet.AuxSigner]
 208  
 209  	// AuxDataParser is an optional data parser that can be used to parse
 210  	// auxiliary data for certain custom channel types.
 211  	AuxDataParser fn.Option[AuxDataParser]
 212  
 213  	// AuxChanCloser is an optional channel closer that can be used to
 214  	// modify the way a coop-close transaction is constructed.
 215  	AuxChanCloser fn.Option[chancloser.AuxChanCloser]
 216  
 217  	// AuxSweeper is an optional interface that can be used to modify the
 218  	// way sweep transaction are generated.
 219  	AuxSweeper fn.Option[sweep.AuxSweeper]
 220  
 221  	// AuxContractResolver is an optional interface that can be used to
 222  	// modify the way contracts are resolved.
 223  	AuxContractResolver fn.Option[lnwallet.AuxContractResolver]
 224  
 225  	// AuxChannelNegotiator is an optional interface that allows aux channel
 226  	// implementations to inject and process custom records over channel
 227  	// related wire messages.
 228  	AuxChannelNegotiator fn.Option[lnwallet.AuxChannelNegotiator]
 229  }
 230  
 231  // DefaultWalletImpl is the default implementation of our normal, btcwallet
 232  // backed configuration.
 233  type DefaultWalletImpl struct {
 234  	cfg         *Config
 235  	logger      btclog.Logger
 236  	interceptor signal.Interceptor
 237  
 238  	watchOnly        bool
 239  	migrateWatchOnly bool
 240  	pwService        *walletunlocker.UnlockerService
 241  }
 242  
 243  // NewDefaultWalletImpl creates a new default wallet implementation.
 244  func NewDefaultWalletImpl(cfg *Config, logger btclog.Logger,
 245  	interceptor signal.Interceptor, watchOnly bool) *DefaultWalletImpl {
 246  
 247  	return &DefaultWalletImpl{
 248  		cfg:         cfg,
 249  		logger:      logger,
 250  		interceptor: interceptor,
 251  		watchOnly:   watchOnly,
 252  		pwService:   createWalletUnlockerService(cfg),
 253  	}
 254  }
 255  
 256  // RegisterRestSubserver is called after lnd creates the main proxy.ServeMux
 257  // instance. External subservers implementing this method can then register
 258  // their own REST proxy stubs to the main server instance.
 259  //
 260  // NOTE: This is part of the GrpcRegistrar interface.
 261  func (d *DefaultWalletImpl) RegisterRestSubserver(ctx context.Context,
 262  	mux *proxy.ServeMux, restProxyDest string,
 263  	restDialOpts []grpc.DialOption) error {
 264  
 265  	return lnrpc.RegisterWalletUnlockerHandlerFromEndpoint(
 266  		ctx, mux, restProxyDest, restDialOpts,
 267  	)
 268  }
 269  
 270  // RegisterGrpcSubserver is called for each net.Listener on which lnd creates a
 271  // grpc.Server instance. External subservers implementing this method can then
 272  // register their own gRPC server structs to the main server instance.
 273  //
 274  // NOTE: This is part of the GrpcRegistrar interface.
 275  func (d *DefaultWalletImpl) RegisterGrpcSubserver(s *grpc.Server) error {
 276  	lnrpc.RegisterWalletUnlockerServer(s, d.pwService)
 277  
 278  	return nil
 279  }
 280  
 281  // ValidateMacaroon extracts the macaroon from the context's gRPC metadata,
 282  // checks its signature, makes sure all specified permissions for the called
 283  // method are contained within and finally ensures all caveat conditions are
 284  // met. A non-nil error is returned if any of the checks fail.
 285  //
 286  // NOTE: This is part of the ExternalValidator interface.
 287  func (d *DefaultWalletImpl) ValidateMacaroon(ctx context.Context,
 288  	requiredPermissions []bakery.Op, fullMethod string) error {
 289  
 290  	// Because the default implementation does not return any permissions,
 291  	// we shouldn't be registered as an external validator at all and this
 292  	// should never be invoked.
 293  	return fmt.Errorf("default implementation does not support external " +
 294  		"macaroon validation")
 295  }
 296  
 297  // Permissions returns the permissions that the external validator is
 298  // validating. It is a map between the full HTTP URI of each RPC and its
 299  // required macaroon permissions. If multiple action/entity tuples are specified
 300  // per URI, they are all required. See rpcserver.go for a list of valid action
 301  // and entity values.
 302  //
 303  // NOTE: This is part of the ExternalValidator interface.
 304  func (d *DefaultWalletImpl) Permissions() map[string][]bakery.Op {
 305  	return nil
 306  }
 307  
 308  // BuildWalletConfig is responsible for creating or unlocking and then
 309  // fully initializing a wallet.
 310  //
 311  // NOTE: This is part of the WalletConfigBuilder interface.
 312  func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
 313  	dbs *DatabaseInstances, aux *AuxComponents,
 314  	interceptorChain *rpcperms.InterceptorChain,
 315  	grpcListeners []*ListenerWithSignal) (*chainreg.PartialChainControl,
 316  	*btcwallet.Config, func(), error) {
 317  
 318  	// Keep track of our various cleanup functions. We use a defer function
 319  	// as well to not repeat ourselves with every return statement.
 320  	var (
 321  		cleanUpTasks []func()
 322  		earlyExit    = true
 323  		cleanUp      = func() {
 324  			for _, fn := range cleanUpTasks {
 325  				if fn == nil {
 326  					continue
 327  				}
 328  
 329  				fn()
 330  			}
 331  		}
 332  	)
 333  	defer func() {
 334  		if earlyExit {
 335  			cleanUp()
 336  		}
 337  	}()
 338  
 339  	// Initialize a new block cache.
 340  	blockCache := blockcache.NewBlockCache(d.cfg.BlockCacheSize)
 341  
 342  	// Before starting the wallet, we'll create and start our Neutrino
 343  	// light client instance, if enabled, in order to allow it to sync
 344  	// while the rest of the daemon continues startup.
 345  	mainChain := d.cfg.Bitcoin
 346  	var neutrinoCS *neutrino.ChainService
 347  	if mainChain.Node == "neutrino" {
 348  		neutrinoBackend, neutrinoCleanUp, err := initNeutrinoBackend(
 349  			ctx, d.cfg, mainChain.ChainDir, blockCache,
 350  		)
 351  		if err != nil {
 352  			err := fmt.Errorf("unable to initialize neutrino "+
 353  				"backend: %v", err)
 354  			d.logger.Error(err)
 355  			return nil, nil, nil, err
 356  		}
 357  		cleanUpTasks = append(cleanUpTasks, neutrinoCleanUp)
 358  		neutrinoCS = neutrinoBackend
 359  	}
 360  
 361  	var (
 362  		walletInitParams = walletunlocker.WalletUnlockParams{
 363  			// In case we do auto-unlock, we need to be able to send
 364  			// into the channel without blocking so we buffer it.
 365  			MacResponseChan: make(chan []byte, 1),
 366  		}
 367  		privateWalletPw = lnwallet.DefaultPrivatePassphrase
 368  		publicWalletPw  = lnwallet.DefaultPublicPassphrase
 369  	)
 370  
 371  	// If the user didn't request a seed, then we'll manually assume a
 372  	// wallet birthday of now, as otherwise the seed would've specified
 373  	// this information.
 374  	walletInitParams.Birthday = time.Now()
 375  
 376  	d.pwService.SetLoaderOpts([]btcwallet.LoaderOption{dbs.WalletDB})
 377  	d.pwService.SetMacaroonDB(dbs.MacaroonDB)
 378  	walletExists, err := d.pwService.WalletExists()
 379  	if err != nil {
 380  		return nil, nil, nil, err
 381  	}
 382  
 383  	if !walletExists {
 384  		interceptorChain.SetWalletNotCreated()
 385  	} else {
 386  		interceptorChain.SetWalletLocked()
 387  	}
 388  
 389  	// If we've started in auto unlock mode, then a wallet should already
 390  	// exist because we don't want to enable the RPC unlocker in that case
 391  	// for security reasons (an attacker could inject their seed since the
 392  	// RPC is unauthenticated). Only if the user explicitly wants to allow
 393  	// wallet creation we don't error out here.
 394  	if d.cfg.WalletUnlockPasswordFile != "" && !walletExists &&
 395  		!d.cfg.WalletUnlockAllowCreate {
 396  
 397  		return nil, nil, nil, fmt.Errorf("wallet unlock password file " +
 398  			"was specified but wallet does not exist; initialize " +
 399  			"the wallet before using auto unlocking")
 400  	}
 401  
 402  	// What wallet mode are we running in? We've already made sure the no
 403  	// seed backup and auto unlock aren't both set during config parsing.
 404  	switch {
 405  	// No seed backup means we're also using the default password.
 406  	case d.cfg.NoSeedBackup:
 407  		// We continue normally, the default password has already been
 408  		// set above.
 409  
 410  	// A password for unlocking is provided in a file.
 411  	case d.cfg.WalletUnlockPasswordFile != "" && walletExists:
 412  		d.logger.Infof("Attempting automatic wallet unlock with " +
 413  			"password provided in file")
 414  		pwBytes, err := os.ReadFile(d.cfg.WalletUnlockPasswordFile)
 415  		if err != nil {
 416  			return nil, nil, nil, fmt.Errorf("error reading "+
 417  				"password from file %s: %v",
 418  				d.cfg.WalletUnlockPasswordFile, err)
 419  		}
 420  
 421  		// Remove any newlines at the end of the file. The lndinit tool
 422  		// won't ever write a newline but maybe the file was provisioned
 423  		// by another process or user.
 424  		pwBytes = bytes.TrimRight(pwBytes, "\r\n")
 425  
 426  		// We have the password now, we can ask the unlocker service to
 427  		// do the unlock for us.
 428  		unlockedWallet, unloadWalletFn, err := d.pwService.LoadAndUnlock(
 429  			pwBytes, 0,
 430  		)
 431  		if err != nil {
 432  			return nil, nil, nil, fmt.Errorf("error unlocking "+
 433  				"wallet with password from file: %v", err)
 434  		}
 435  
 436  		cleanUpTasks = append(cleanUpTasks, func() {
 437  			if err := unloadWalletFn(); err != nil {
 438  				d.logger.Errorf("Could not unload wallet: %v",
 439  					err)
 440  			}
 441  		})
 442  
 443  		privateWalletPw = pwBytes
 444  		publicWalletPw = pwBytes
 445  		walletInitParams.Wallet = unlockedWallet
 446  		walletInitParams.UnloadWallet = unloadWalletFn
 447  
 448  	// If none of the automatic startup options are selected, we fall back
 449  	// to the default behavior of waiting for the wallet creation/unlocking
 450  	// over RPC.
 451  	default:
 452  		if err := d.interceptor.Notifier.NotifyReady(false); err != nil {
 453  			return nil, nil, nil, err
 454  		}
 455  
 456  		params, err := waitForWalletPassword(
 457  			d.cfg, d.pwService, []btcwallet.LoaderOption{dbs.WalletDB},
 458  			d.interceptor.ShutdownChannel(),
 459  		)
 460  		if err != nil {
 461  			err := fmt.Errorf("unable to set up wallet password "+
 462  				"listeners: %v", err)
 463  			d.logger.Error(err)
 464  			return nil, nil, nil, err
 465  		}
 466  
 467  		walletInitParams = *params
 468  		privateWalletPw = walletInitParams.Password
 469  		publicWalletPw = walletInitParams.Password
 470  		cleanUpTasks = append(cleanUpTasks, func() {
 471  			if err := walletInitParams.UnloadWallet(); err != nil {
 472  				d.logger.Errorf("Could not unload wallet: %v",
 473  					err)
 474  			}
 475  		})
 476  
 477  		if walletInitParams.RecoveryWindow > 0 {
 478  			d.logger.Infof("Wallet recovery mode enabled with "+
 479  				"address lookahead of %d addresses",
 480  				walletInitParams.RecoveryWindow)
 481  		}
 482  	}
 483  
 484  	var macaroonService *macaroons.Service
 485  	if !d.cfg.NoMacaroons {
 486  		// Create the macaroon authentication/authorization service.
 487  		rootKeyStore, err := macaroons.NewRootKeyStorage(dbs.MacaroonDB)
 488  		if err != nil {
 489  			return nil, nil, nil, err
 490  		}
 491  		macaroonService, err = macaroons.NewService(
 492  			rootKeyStore, "lnd", walletInitParams.StatelessInit,
 493  			macaroons.IPLockChecker, macaroons.IPRangeLockChecker,
 494  			macaroons.CustomChecker(interceptorChain),
 495  		)
 496  		if err != nil {
 497  			err := fmt.Errorf("unable to set up macaroon "+
 498  				"authentication: %v", err)
 499  			d.logger.Error(err)
 500  			return nil, nil, nil, err
 501  		}
 502  		cleanUpTasks = append(cleanUpTasks, func() {
 503  			if err := macaroonService.Close(); err != nil {
 504  				d.logger.Errorf("Could not close macaroon "+
 505  					"service: %v", err)
 506  			}
 507  		})
 508  
 509  		// Try to unlock the macaroon store with the private password.
 510  		// Ignore ErrAlreadyUnlocked since it could be unlocked by the
 511  		// wallet unlocker.
 512  		err = macaroonService.CreateUnlock(&privateWalletPw)
 513  		if err != nil && err != macaroons.ErrAlreadyUnlocked {
 514  			err := fmt.Errorf("unable to unlock macaroons: %w", err)
 515  			d.logger.Error(err)
 516  			return nil, nil, nil, err
 517  		}
 518  
 519  		// If we have a macaroon root key from the init wallet params,
 520  		// set the root key before baking any macaroons.
 521  		if len(walletInitParams.MacRootKey) > 0 {
 522  			err := macaroonService.SetRootKey(
 523  				walletInitParams.MacRootKey,
 524  			)
 525  			if err != nil {
 526  				return nil, nil, nil, err
 527  			}
 528  		}
 529  
 530  		// Send an admin macaroon to all our listeners that requested
 531  		// one by setting a non-nil macaroon channel.
 532  		adminMacBytes, err := bakeMacaroon(
 533  			ctx, macaroonService, adminPermissions(),
 534  		)
 535  		if err != nil {
 536  			return nil, nil, nil, err
 537  		}
 538  		for _, lis := range grpcListeners {
 539  			if lis.MacChan != nil {
 540  				lis.MacChan <- adminMacBytes
 541  			}
 542  		}
 543  
 544  		// In case we actually needed to unlock the wallet, we now need
 545  		// to create an instance of the admin macaroon and send it to
 546  		// the unlocker so it can forward it to the user. In no seed
 547  		// backup mode, there's nobody listening on the channel and we'd
 548  		// block here forever.
 549  		if !d.cfg.NoSeedBackup {
 550  			// The channel is buffered by one element so writing
 551  			// should not block here.
 552  			walletInitParams.MacResponseChan <- adminMacBytes
 553  		}
 554  
 555  		// If the user requested a stateless initialization, no macaroon
 556  		// files should be created.
 557  		if !walletInitParams.StatelessInit {
 558  			// Create default macaroon files for lncli to use if
 559  			// they don't exist.
 560  			err = genDefaultMacaroons(
 561  				ctx, macaroonService, d.cfg.AdminMacPath,
 562  				d.cfg.ReadMacPath, d.cfg.InvoiceMacPath,
 563  			)
 564  			if err != nil {
 565  				err := fmt.Errorf("unable to create macaroons "+
 566  					"%v", err)
 567  				d.logger.Error(err)
 568  				return nil, nil, nil, err
 569  			}
 570  		}
 571  
 572  		// As a security service to the user, if they requested
 573  		// stateless initialization and there are macaroon files on disk
 574  		// we log a warning.
 575  		if walletInitParams.StatelessInit {
 576  			msg := "Found %s macaroon on disk (%s) even though " +
 577  				"--stateless_init was requested. Unencrypted " +
 578  				"state is accessible by the host system. You " +
 579  				"should change the password and use " +
 580  				"--new_mac_root_key with --stateless_init to " +
 581  				"clean up and invalidate old macaroons."
 582  
 583  			if lnrpc.FileExists(d.cfg.AdminMacPath) {
 584  				d.logger.Warnf(msg, "admin", d.cfg.AdminMacPath)
 585  			}
 586  			if lnrpc.FileExists(d.cfg.ReadMacPath) {
 587  				d.logger.Warnf(msg, "readonly", d.cfg.ReadMacPath)
 588  			}
 589  			if lnrpc.FileExists(d.cfg.InvoiceMacPath) {
 590  				d.logger.Warnf(msg, "invoice", d.cfg.InvoiceMacPath)
 591  			}
 592  		}
 593  
 594  		// We add the macaroon service to our RPC interceptor. This
 595  		// will start checking macaroons against permissions on every
 596  		// RPC invocation.
 597  		interceptorChain.AddMacaroonService(macaroonService)
 598  	}
 599  
 600  	// Now that the wallet password has been provided, transition the RPC
 601  	// state into Unlocked.
 602  	interceptorChain.SetWalletUnlocked()
 603  
 604  	// Since calls to the WalletUnlocker service wait for a response on the
 605  	// macaroon channel, we close it here to make sure they return in case
 606  	// we did not return the admin macaroon above. This will be the case if
 607  	// --no-macaroons is used.
 608  	close(walletInitParams.MacResponseChan)
 609  
 610  	// We'll also close all the macaroon channels since lnd is done sending
 611  	// macaroon data over it.
 612  	for _, lis := range grpcListeners {
 613  		if lis.MacChan != nil {
 614  			close(lis.MacChan)
 615  		}
 616  	}
 617  
 618  	// With the information parsed from the configuration, create valid
 619  	// instances of the pertinent interfaces required to operate the
 620  	// Lightning Network Daemon.
 621  	//
 622  	// When we create the chain control, we need storage for the height
 623  	// hints and also the wallet itself, for these two we want them to be
 624  	// replicated, so we'll pass in the remote channel DB instance.
 625  	chainControlCfg := &chainreg.Config{
 626  		Bitcoin:                     d.cfg.Bitcoin,
 627  		HeightHintCacheQueryDisable: d.cfg.HeightHintCacheQueryDisable,
 628  		NeutrinoMode:                d.cfg.NeutrinoMode,
 629  		BitcoindMode:                d.cfg.BitcoindMode,
 630  		BtcdMode:                    d.cfg.BtcdMode,
 631  		HeightHintDB:                dbs.HeightHintDB,
 632  		ChanStateDB:                 dbs.ChanStateDB.ChannelStateDB(),
 633  		NeutrinoCS:                  neutrinoCS,
 634  		AuxLeafStore:                aux.AuxLeafStore,
 635  		AuxSigner:                   aux.AuxSigner,
 636  		ActiveNetParams:             d.cfg.ActiveNetParams,
 637  		FeeURL:                      d.cfg.FeeURL,
 638  		Fee: &lncfg.Fee{
 639  			URL:              d.cfg.Fee.URL,
 640  			MinUpdateTimeout: d.cfg.Fee.MinUpdateTimeout,
 641  			MaxUpdateTimeout: d.cfg.Fee.MaxUpdateTimeout,
 642  		},
 643  		Dialer: func(addr string) (net.Conn, error) {
 644  			return d.cfg.net.Dial(
 645  				"tcp", addr, d.cfg.ConnectionTimeout,
 646  			)
 647  		},
 648  		BlockCache:         blockCache,
 649  		WalletUnlockParams: &walletInitParams,
 650  	}
 651  
 652  	// Let's go ahead and create the partial chain control now that is only
 653  	// dependent on our configuration and doesn't require any wallet
 654  	// specific information.
 655  	partialChainControl, pccCleanup, err := chainreg.NewPartialChainControl(
 656  		chainControlCfg,
 657  	)
 658  	cleanUpTasks = append(cleanUpTasks, pccCleanup)
 659  	if err != nil {
 660  		err := fmt.Errorf("unable to create partial chain control: %w",
 661  			err)
 662  		d.logger.Error(err)
 663  		return nil, nil, nil, err
 664  	}
 665  
 666  	walletConfig := &btcwallet.Config{
 667  		PrivatePass:      privateWalletPw,
 668  		PublicPass:       publicWalletPw,
 669  		Birthday:         walletInitParams.Birthday,
 670  		RecoveryWindow:   walletInitParams.RecoveryWindow,
 671  		NetParams:        d.cfg.ActiveNetParams.Params,
 672  		CoinType:         d.cfg.ActiveNetParams.CoinType,
 673  		Wallet:           walletInitParams.Wallet,
 674  		LoaderOptions:    []btcwallet.LoaderOption{dbs.WalletDB},
 675  		ChainSource:      partialChainControl.ChainSource,
 676  		WatchOnly:        d.watchOnly,
 677  		MigrateWatchOnly: d.migrateWatchOnly,
 678  	}
 679  
 680  	// Parse coin selection strategy.
 681  	switch d.cfg.CoinSelectionStrategy {
 682  	case "largest":
 683  		walletConfig.CoinSelectionStrategy = wallet.CoinSelectionLargest
 684  
 685  	case "random":
 686  		walletConfig.CoinSelectionStrategy = wallet.CoinSelectionRandom
 687  
 688  	default:
 689  		return nil, nil, nil, fmt.Errorf("unknown coin selection "+
 690  			"strategy %v", d.cfg.CoinSelectionStrategy)
 691  	}
 692  
 693  	earlyExit = false
 694  	return partialChainControl, walletConfig, cleanUp, nil
 695  }
 696  
 697  // proxyBlockEpoch proxies a block epoch subsections to the underlying neutrino
 698  // rebroadcaster client.
 699  func proxyBlockEpoch(
 700  	notifier chainntnfs.ChainNotifier) func() (*blockntfns.Subscription,
 701  	error) {
 702  
 703  	return func() (*blockntfns.Subscription, error) {
 704  		blockEpoch, err := notifier.RegisterBlockEpochNtfn(
 705  			nil,
 706  		)
 707  		if err != nil {
 708  			return nil, err
 709  		}
 710  
 711  		sub := blockntfns.Subscription{
 712  			Notifications: make(chan blockntfns.BlockNtfn, 6),
 713  			Cancel:        blockEpoch.Cancel,
 714  		}
 715  		go func() {
 716  			for blk := range blockEpoch.Epochs {
 717  				ntfn := blockntfns.NewBlockConnected(
 718  					*blk.BlockHeader,
 719  					uint32(blk.Height),
 720  				)
 721  
 722  				sub.Notifications <- ntfn
 723  			}
 724  		}()
 725  
 726  		return &sub, nil
 727  	}
 728  }
 729  
 730  // walletReBroadcaster is a simple wrapper around the pushtx.Broadcaster
 731  // interface to adhere to the expanded lnwallet.Rebroadcaster interface.
 732  type walletReBroadcaster struct {
 733  	started atomic.Bool
 734  
 735  	*pushtx.Broadcaster
 736  }
 737  
 738  // newWalletReBroadcaster creates a new instance of the walletReBroadcaster.
 739  func newWalletReBroadcaster(
 740  	broadcaster *pushtx.Broadcaster) *walletReBroadcaster {
 741  
 742  	return &walletReBroadcaster{
 743  		Broadcaster: broadcaster,
 744  	}
 745  }
 746  
 747  // Start launches all goroutines the rebroadcaster needs to operate.
 748  func (w *walletReBroadcaster) Start() error {
 749  	defer w.started.Store(true)
 750  
 751  	return w.Broadcaster.Start()
 752  }
 753  
 754  // Started returns true if the broadcaster is already active.
 755  func (w *walletReBroadcaster) Started() bool {
 756  	return w.started.Load()
 757  }
 758  
 759  // BuildChainControl is responsible for creating a fully populated chain
 760  // control instance from a wallet.
 761  //
 762  // NOTE: This is part of the ChainControlBuilder interface.
 763  func (d *DefaultWalletImpl) BuildChainControl(
 764  	partialChainControl *chainreg.PartialChainControl,
 765  	walletConfig *btcwallet.Config) (*chainreg.ChainControl, func(), error) {
 766  
 767  	walletController, err := btcwallet.New(
 768  		*walletConfig, partialChainControl.Cfg.BlockCache,
 769  	)
 770  	if err != nil {
 771  		err := fmt.Errorf("unable to create wallet controller: %w", err)
 772  		d.logger.Error(err)
 773  		return nil, nil, err
 774  	}
 775  
 776  	keyRing := keychain.NewBtcWalletKeyRing(
 777  		walletController.InternalWallet(), walletConfig.CoinType,
 778  	)
 779  
 780  	// Create, and start the lnwallet, which handles the core payment
 781  	// channel logic, and exposes control via proxy state machines.
 782  	lnWalletConfig := lnwallet.Config{
 783  		Database:              partialChainControl.Cfg.ChanStateDB,
 784  		Notifier:              partialChainControl.ChainNotifier,
 785  		WalletController:      walletController,
 786  		Signer:                walletController,
 787  		FeeEstimator:          partialChainControl.FeeEstimator,
 788  		SecretKeyRing:         keyRing,
 789  		ChainIO:               walletController,
 790  		NetParams:             *walletConfig.NetParams,
 791  		CoinSelectionStrategy: walletConfig.CoinSelectionStrategy,
 792  		AuxLeafStore:          partialChainControl.Cfg.AuxLeafStore,
 793  		AuxSigner:             partialChainControl.Cfg.AuxSigner,
 794  	}
 795  
 796  	// The broadcast is already always active for neutrino nodes, so we
 797  	// don't want to create a rebroadcast loop.
 798  	if partialChainControl.Cfg.NeutrinoCS == nil {
 799  		cs := partialChainControl.ChainSource
 800  		broadcastCfg := pushtx.Config{
 801  			Broadcast: func(tx *wire.MsgTx) error {
 802  				_, err := cs.SendRawTransaction(
 803  					tx, true,
 804  				)
 805  
 806  				return err
 807  			},
 808  			SubscribeBlocks: proxyBlockEpoch(
 809  				partialChainControl.ChainNotifier,
 810  			),
 811  			RebroadcastInterval: pushtx.DefaultRebroadcastInterval,
 812  			// In case the backend is different from neutrino we
 813  			// make sure that broadcast backend errors are mapped
 814  			// to the neutrino broadcastErr.
 815  			MapCustomBroadcastError: func(err error) error {
 816  				rpcErr := cs.MapRPCErr(err)
 817  				return broadcastErrorMapper(rpcErr)
 818  			},
 819  		}
 820  
 821  		lnWalletConfig.Rebroadcaster = newWalletReBroadcaster(
 822  			pushtx.NewBroadcaster(&broadcastCfg),
 823  		)
 824  	}
 825  
 826  	// We've created the wallet configuration now, so we can finish
 827  	// initializing the main chain control.
 828  	activeChainControl, cleanUp, err := chainreg.NewChainControl(
 829  		lnWalletConfig, walletController, partialChainControl,
 830  	)
 831  	if err != nil {
 832  		err := fmt.Errorf("unable to create chain control: %w", err)
 833  		d.logger.Error(err)
 834  		return nil, nil, err
 835  	}
 836  
 837  	return activeChainControl, cleanUp, nil
 838  }
 839  
 840  // RPCSignerWalletImpl is a wallet implementation that uses a remote signer over
 841  // an RPC interface.
 842  type RPCSignerWalletImpl struct {
 843  	// DefaultWalletImpl is the embedded instance of the default
 844  	// implementation that the remote signer uses as its watch-only wallet
 845  	// for keeping track of addresses and UTXOs.
 846  	*DefaultWalletImpl
 847  }
 848  
 849  // NewRPCSignerWalletImpl creates a new instance of the remote signing wallet
 850  // implementation.
 851  func NewRPCSignerWalletImpl(cfg *Config, logger btclog.Logger,
 852  	interceptor signal.Interceptor,
 853  	migrateWatchOnly bool) *RPCSignerWalletImpl {
 854  
 855  	return &RPCSignerWalletImpl{
 856  		DefaultWalletImpl: &DefaultWalletImpl{
 857  			cfg:              cfg,
 858  			logger:           logger,
 859  			interceptor:      interceptor,
 860  			watchOnly:        true,
 861  			migrateWatchOnly: migrateWatchOnly,
 862  			pwService:        createWalletUnlockerService(cfg),
 863  		},
 864  	}
 865  }
 866  
 867  // BuildChainControl is responsible for creating or unlocking and then fully
 868  // initializing a wallet and returning it as part of a fully populated chain
 869  // control instance.
 870  //
 871  // NOTE: This is part of the ChainControlBuilder interface.
 872  func (d *RPCSignerWalletImpl) BuildChainControl(
 873  	partialChainControl *chainreg.PartialChainControl,
 874  	walletConfig *btcwallet.Config) (*chainreg.ChainControl, func(), error) {
 875  
 876  	walletController, err := btcwallet.New(
 877  		*walletConfig, partialChainControl.Cfg.BlockCache,
 878  	)
 879  	if err != nil {
 880  		err := fmt.Errorf("unable to create wallet controller: %w", err)
 881  		d.logger.Error(err)
 882  		return nil, nil, err
 883  	}
 884  
 885  	baseKeyRing := keychain.NewBtcWalletKeyRing(
 886  		walletController.InternalWallet(), walletConfig.CoinType,
 887  	)
 888  
 889  	rpcKeyRing, err := rpcwallet.NewRPCKeyRing(
 890  		baseKeyRing, walletController,
 891  		d.DefaultWalletImpl.cfg.RemoteSigner, walletConfig.NetParams,
 892  	)
 893  	if err != nil {
 894  		err := fmt.Errorf("unable to create RPC remote signing wallet "+
 895  			"%v", err)
 896  		d.logger.Error(err)
 897  		return nil, nil, err
 898  	}
 899  
 900  	// Create, and start the lnwallet, which handles the core payment
 901  	// channel logic, and exposes control via proxy state machines.
 902  	lnWalletConfig := lnwallet.Config{
 903  		Database:              partialChainControl.Cfg.ChanStateDB,
 904  		Notifier:              partialChainControl.ChainNotifier,
 905  		WalletController:      rpcKeyRing,
 906  		Signer:                rpcKeyRing,
 907  		FeeEstimator:          partialChainControl.FeeEstimator,
 908  		SecretKeyRing:         rpcKeyRing,
 909  		ChainIO:               walletController,
 910  		NetParams:             *walletConfig.NetParams,
 911  		CoinSelectionStrategy: walletConfig.CoinSelectionStrategy,
 912  	}
 913  
 914  	// We've created the wallet configuration now, so we can finish
 915  	// initializing the main chain control.
 916  	activeChainControl, cleanUp, err := chainreg.NewChainControl(
 917  		lnWalletConfig, rpcKeyRing, partialChainControl,
 918  	)
 919  	if err != nil {
 920  		err := fmt.Errorf("unable to create chain control: %w", err)
 921  		d.logger.Error(err)
 922  		return nil, nil, err
 923  	}
 924  
 925  	return activeChainControl, cleanUp, nil
 926  }
 927  
 928  // DatabaseInstances is a struct that holds all instances to the actual
 929  // databases that are used in lnd.
 930  type DatabaseInstances struct {
 931  	// GraphDB is the database that stores the channel graph used for path
 932  	// finding.
 933  	GraphDB *graphdb.ChannelGraph
 934  
 935  	// ChanStateDB is the database that stores all of our node's channel
 936  	// state.
 937  	ChanStateDB *channeldb.DB
 938  
 939  	// HeightHintDB is the database that stores height hints for spends.
 940  	HeightHintDB kvdb.Backend
 941  
 942  	// InvoiceDB is the database that stores information about invoices.
 943  	InvoiceDB invoices.InvoiceDB
 944  
 945  	// PaymentsDB is the database that stores all payment related
 946  	// information.
 947  	PaymentsDB paymentsdb.DB
 948  
 949  	// MacaroonDB is the database that stores macaroon root keys.
 950  	MacaroonDB kvdb.Backend
 951  
 952  	// DecayedLogDB is the database that stores p2p related encryption
 953  	// information.
 954  	DecayedLogDB kvdb.Backend
 955  
 956  	// TowerClientDB is the database that stores the watchtower client's
 957  	// configuration.
 958  	TowerClientDB wtclient.DB
 959  
 960  	// TowerServerDB is the database that stores the watchtower server's
 961  	// configuration.
 962  	TowerServerDB watchtower.DB
 963  
 964  	// WalletDB is the configuration for loading the wallet database using
 965  	// the btcwallet's loader.
 966  	WalletDB btcwallet.LoaderOption
 967  
 968  	// NativeSQLStore holds a reference to the native SQL store that can
 969  	// be used for native SQL queries for tables that already support it.
 970  	// This may be nil if the use-native-sql flag was not set.
 971  	NativeSQLStore sqldb.DB
 972  }
 973  
 974  // DefaultDatabaseBuilder is a type that builds the default database backends
 975  // for lnd, using the given configuration to decide what actual implementation
 976  // to use.
 977  type DefaultDatabaseBuilder struct {
 978  	cfg    *Config
 979  	logger btclog.Logger
 980  }
 981  
 982  // NewDefaultDatabaseBuilder returns a new instance of the default database
 983  // builder.
 984  func NewDefaultDatabaseBuilder(cfg *Config,
 985  	logger btclog.Logger) *DefaultDatabaseBuilder {
 986  
 987  	return &DefaultDatabaseBuilder{
 988  		cfg:    cfg,
 989  		logger: logger,
 990  	}
 991  }
 992  
 993  // BuildDatabase extracts the current databases that we'll use for normal
 994  // operation in the daemon. A function closure that closes all opened databases
 995  // is also returned.
 996  func (d *DefaultDatabaseBuilder) BuildDatabase(
 997  	ctx context.Context) (*DatabaseInstances, func(), error) {
 998  
 999  	d.logger.Infof("Opening the main database, this might take a few " +
1000  		"minutes...")
1001  
1002  	cfg := d.cfg
1003  	if cfg.DB.Backend == lncfg.BoltBackend {
1004  		d.logger.Infof("Opening bbolt database, sync_freelist=%v, "+
1005  			"auto_compact=%v", !cfg.DB.Bolt.NoFreelistSync,
1006  			cfg.DB.Bolt.AutoCompact)
1007  	}
1008  
1009  	startOpenTime := time.Now()
1010  
1011  	databaseBackends, err := cfg.DB.GetBackends(
1012  		ctx, cfg.graphDatabaseDir(), cfg.networkDir, filepath.Join(
1013  			cfg.Watchtower.TowerDir, BitcoinChainName,
1014  			lncfg.NormalizeNetwork(cfg.ActiveNetParams.Name),
1015  		), cfg.WtClient.Active, cfg.Watchtower.Active, d.logger,
1016  	)
1017  	if err != nil {
1018  		return nil, nil, fmt.Errorf("unable to obtain database "+
1019  			"backends: %v", err)
1020  	}
1021  
1022  	// With the full remote mode we made sure both the graph and channel
1023  	// state DB point to the same local or remote DB and the same namespace
1024  	// within that DB.
1025  	dbs := &DatabaseInstances{
1026  		HeightHintDB:   databaseBackends.HeightHintDB,
1027  		MacaroonDB:     databaseBackends.MacaroonDB,
1028  		DecayedLogDB:   databaseBackends.DecayedLogDB,
1029  		WalletDB:       databaseBackends.WalletDB,
1030  		NativeSQLStore: databaseBackends.NativeSQLStore,
1031  	}
1032  	cleanUp := func() {
1033  		// We can just close the returned close functions directly. Even
1034  		// if we decorate the channel DB with an additional struct, its
1035  		// close function still just points to the kvdb backend.
1036  		for name, closeFunc := range databaseBackends.CloseFuncs {
1037  			if err := closeFunc(); err != nil {
1038  				d.logger.Errorf("Error closing %s "+
1039  					"database: %v", name, err)
1040  			}
1041  		}
1042  	}
1043  	if databaseBackends.Remote {
1044  		d.logger.Infof("Using remote %v database! Creating "+
1045  			"graph and channel state DB instances", cfg.DB.Backend)
1046  	} else {
1047  		d.logger.Infof("Creating local graph and channel state DB " +
1048  			"instances")
1049  	}
1050  
1051  	graphDBOptions := []graphdb.StoreOptionModifier{
1052  		graphdb.WithRejectCacheSize(cfg.Caches.RejectCacheSize),
1053  		graphdb.WithChannelCacheSize(cfg.Caches.ChannelCacheSize),
1054  		graphdb.WithBatchCommitInterval(cfg.DB.BatchCommitInterval),
1055  	}
1056  
1057  	chanGraphOpts := []graphdb.ChanGraphOption{
1058  		graphdb.WithUseGraphCache(!cfg.DB.NoGraphCache),
1059  	}
1060  
1061  	// We want to pre-allocate the channel graph cache according to what we
1062  	// expect for mainnet to speed up memory allocation.
1063  	if cfg.ActiveNetParams.Name == chaincfg.MainNetParams.Name {
1064  		chanGraphOpts = append(
1065  			chanGraphOpts, graphdb.WithPreAllocCacheNumNodes(
1066  				graphdb.DefaultPreAllocCacheNumNodes,
1067  			),
1068  		)
1069  	}
1070  
1071  	dbOptions := []channeldb.OptionModifier{
1072  		channeldb.OptionDryRunMigration(cfg.DryRunMigration),
1073  		channeldb.OptionStoreFinalHtlcResolutions(
1074  			cfg.StoreFinalHtlcResolutions,
1075  		),
1076  		channeldb.OptionPruneRevocationLog(cfg.DB.PruneRevocation),
1077  		channeldb.OptionNoRevLogAmtData(cfg.DB.NoRevLogAmtData),
1078  		channeldb.OptionGcDecayedLog(cfg.DB.NoGcDecayedLog),
1079  		channeldb.OptionWithDecayedLogDB(dbs.DecayedLogDB),
1080  	}
1081  
1082  	// Otherwise, we'll open two instances, one for the state we only need
1083  	// locally, and the other for things we want to ensure are replicated.
1084  	dbs.ChanStateDB, err = channeldb.CreateWithBackend(
1085  		databaseBackends.ChanStateDB, dbOptions...,
1086  	)
1087  	switch {
1088  	// Give the DB a chance to dry run the migration. Since we know that
1089  	// both the channel state and graph DBs are still always behind the same
1090  	// backend, we know this would be applied to both of those DBs.
1091  	case err == channeldb.ErrDryRunMigrationOK:
1092  		d.logger.Infof("Channel DB dry run migration successful")
1093  		return nil, nil, err
1094  
1095  	case err != nil:
1096  		cleanUp()
1097  
1098  		err = fmt.Errorf("unable to open graph DB: %w", err)
1099  		d.logger.Error(err)
1100  		return nil, nil, err
1101  	}
1102  
1103  	// The graph store implementation we will use depends on whether
1104  	// native SQL is enabled or not.
1105  	var graphStore graphdb.Store
1106  
1107  	// Instantiate a native SQL store if the flag is set.
1108  	if d.cfg.DB.UseNativeSQL {
1109  		migrations := sqldb.GetMigrations()
1110  
1111  		queryCfg := &d.cfg.DB.Sqlite.QueryConfig
1112  		if d.cfg.DB.Backend == lncfg.PostgresBackend {
1113  			queryCfg = &d.cfg.DB.Postgres.QueryConfig
1114  		}
1115  
1116  		// If the user has not explicitly disabled the SQL invoice
1117  		// migration, attach the custom migration function to invoice
1118  		// migration (version 7). Even if this custom migration is
1119  		// disabled, the regular native SQL store migrations will still
1120  		// run. If the database version is already above this custom
1121  		// migration's version (7), it will be skipped permanently,
1122  		// regardless of the flag.
1123  		if !d.cfg.DB.SkipNativeSQLMigration {
1124  			invoiceMig := func(tx *sqlc.Queries) error {
1125  				err := invoices.MigrateInvoicesToSQL(
1126  					ctx, dbs.ChanStateDB.Backend,
1127  					dbs.ChanStateDB, tx,
1128  					invoiceMigrationBatchSize,
1129  				)
1130  				if err != nil {
1131  					return fmt.Errorf("failed to migrate "+
1132  						"invoices to SQL: %w", err)
1133  				}
1134  
1135  				// Set the invoice bucket tombstone to indicate
1136  				// that the migration has been completed.
1137  				d.logger.Debugf("Setting invoice bucket " +
1138  					"tombstone")
1139  
1140  				//nolint:ll
1141  				return dbs.ChanStateDB.SetInvoiceBucketTombstone()
1142  			}
1143  
1144  			graphMig := func(tx *sqlc.Queries) error {
1145  				cfg := &graphdbmig1.SQLStoreConfig{
1146  					//nolint:ll
1147  					ChainHash: *d.cfg.ActiveNetParams.GenesisHash,
1148  					QueryCfg:  queryCfg,
1149  				}
1150  				err := graphdbmig1.MigrateGraphToSQL(
1151  					ctx, cfg, dbs.ChanStateDB.Backend,
1152  					graphmig1sqlc.New(tx.GetTx()),
1153  				)
1154  				if err != nil {
1155  					return fmt.Errorf("failed to migrate "+
1156  						"graph to SQL: %w", err)
1157  				}
1158  
1159  				return nil
1160  			}
1161  
1162  			paymentMig := func(tx *sqlc.Queries) error {
1163  				err := paymentsmig1.MigratePaymentsKVToSQL(
1164  					ctx,
1165  					dbs.ChanStateDB.Backend,
1166  					paymentsmig1sqlc.New(tx.GetTx()),
1167  					&paymentsmig1.SQLStoreConfig{
1168  						QueryCfg: queryCfg,
1169  					},
1170  				)
1171  				if err != nil {
1172  					return fmt.Errorf("failed to migrate "+
1173  						"payments to SQL: %w", err)
1174  				}
1175  
1176  				// Set the payments bucket tombstone to
1177  				// indicate that the migration has been
1178  				// completed.
1179  				d.logger.Debugf("Setting payments bucket " +
1180  					"tombstone")
1181  
1182  				return paymentsdb.SetPaymentsBucketTombstone(
1183  					dbs.ChanStateDB.Backend,
1184  				)
1185  			}
1186  
1187  			// Make sure we attach the custom migration function to
1188  			// the correct migration version.
1189  			for i := 0; i < len(migrations); i++ {
1190  				version := migrations[i].Version
1191  				switch version {
1192  				case invoiceMigration:
1193  					migrations[i].MigrationFn = invoiceMig
1194  
1195  					continue
1196  
1197  				case graphMigration:
1198  					migrations[i].MigrationFn = graphMig
1199  
1200  					continue
1201  
1202  				case paymentMigration:
1203  					migrations[i].MigrationFn = paymentMig
1204  
1205  					continue
1206  
1207  				default:
1208  				}
1209  
1210  				migFn, ok := d.getSQLMigration(
1211  					ctx, version, dbs.ChanStateDB.Backend,
1212  				)
1213  				if !ok {
1214  					continue
1215  				}
1216  
1217  				migrations[i].MigrationFn = migFn
1218  			}
1219  		}
1220  
1221  		// We need to apply all migrations to the native SQL store
1222  		// before we can use it.
1223  		err = dbs.NativeSQLStore.ApplyAllMigrations(ctx, migrations)
1224  		if err != nil {
1225  			cleanUp()
1226  			err = fmt.Errorf("faild to run migrations for the "+
1227  				"native SQL store: %w", err)
1228  			d.logger.Error(err)
1229  
1230  			return nil, nil, err
1231  		}
1232  
1233  		// With the DB ready and migrations applied, we can now create
1234  		// the base DB and transaction executor for the native SQL
1235  		// invoice store.
1236  		baseDB := dbs.NativeSQLStore.GetBaseDB()
1237  		invoiceExecutor := sqldb.NewTransactionExecutor(
1238  			baseDB, func(tx *sql.Tx) invoices.SQLInvoiceQueries {
1239  				return baseDB.WithTx(tx)
1240  			},
1241  		)
1242  
1243  		sqlInvoiceDB := invoices.NewSQLStore(
1244  			invoiceExecutor, clock.NewDefaultClock(),
1245  		)
1246  
1247  		dbs.InvoiceDB = sqlInvoiceDB
1248  
1249  		graphExecutor := sqldb.NewTransactionExecutor(
1250  			baseDB, func(tx *sql.Tx) graphdb.SQLQueries {
1251  				return baseDB.WithTx(tx)
1252  			},
1253  		)
1254  
1255  		graphStore, err = graphdb.NewSQLStore(
1256  			&graphdb.SQLStoreConfig{
1257  				ChainHash: *d.cfg.ActiveNetParams.GenesisHash,
1258  				QueryCfg:  queryCfg,
1259  			},
1260  			graphExecutor, graphDBOptions...,
1261  		)
1262  		if err != nil {
1263  			err = fmt.Errorf("unable to get graph store: %w", err)
1264  			d.logger.Error(err)
1265  
1266  			return nil, nil, err
1267  		}
1268  
1269  		// Create the payments DB.
1270  		//
1271  		// NOTE:  In the regular build, this will construct a kvdb
1272  		// backed payments backend. With the test_native_sql tag, it
1273  		// will build a SQL payments backend.
1274  		sqlPaymentsDB, err := d.getPaymentsStore(
1275  			baseDB, dbs.ChanStateDB.Backend,
1276  		)
1277  		if err != nil {
1278  			err = fmt.Errorf("unable to get payments store: %w",
1279  				err)
1280  
1281  			return nil, nil, err
1282  		}
1283  
1284  		dbs.PaymentsDB = sqlPaymentsDB
1285  	} else {
1286  		// Check if the invoice bucket tombstone is set. If it is, we
1287  		// need to return and ask the user switch back to using the
1288  		// native SQL store.
1289  		ripInvoices, err := dbs.ChanStateDB.GetInvoiceBucketTombstone()
1290  		if err != nil {
1291  			err = fmt.Errorf("unable to check invoice bucket "+
1292  				"tombstone: %w", err)
1293  			d.logger.Error(err)
1294  
1295  			return nil, nil, err
1296  		}
1297  		if ripInvoices {
1298  			err = fmt.Errorf("invoices bucket tombstoned, please " +
1299  				"switch back to native SQL")
1300  			d.logger.Error(err)
1301  
1302  			return nil, nil, err
1303  		}
1304  
1305  		// Check if the payments bucket tombstone is set. If it is, we
1306  		// need to return and ask the user switch back to using the
1307  		// native SQL store.
1308  		ripPayments, err := paymentsdb.GetPaymentsBucketTombstone(
1309  			dbs.ChanStateDB.Backend,
1310  		)
1311  		if err != nil {
1312  			err = fmt.Errorf("unable to check payments bucket "+
1313  				"tombstone: %w", err)
1314  			d.logger.Error(err)
1315  
1316  			return nil, nil, err
1317  		}
1318  		if ripPayments {
1319  			err = fmt.Errorf("payments bucket tombstoned, please " +
1320  				"switch back to native SQL")
1321  			d.logger.Error(err)
1322  
1323  			return nil, nil, err
1324  		}
1325  
1326  		dbs.InvoiceDB = dbs.ChanStateDB
1327  
1328  		graphStore, err = graphdb.NewKVStore(
1329  			databaseBackends.GraphDB, graphDBOptions...,
1330  		)
1331  		if err != nil {
1332  			return nil, nil, err
1333  		}
1334  
1335  		// Create the payments DB.
1336  		kvPaymentsDB, err := paymentsdb.NewKVStore(
1337  			dbs.ChanStateDB,
1338  		)
1339  		if err != nil {
1340  			cleanUp()
1341  
1342  			err = fmt.Errorf("unable to open payments DB: %w", err)
1343  			d.logger.Error(err)
1344  
1345  			return nil, nil, err
1346  		}
1347  
1348  		dbs.PaymentsDB = kvPaymentsDB
1349  	}
1350  
1351  	dbs.GraphDB, err = graphdb.NewChannelGraph(graphStore, chanGraphOpts...)
1352  	if err != nil {
1353  		cleanUp()
1354  
1355  		err = fmt.Errorf("unable to open channel graph DB: %w", err)
1356  		d.logger.Error(err)
1357  
1358  		return nil, nil, err
1359  	}
1360  
1361  	// Wrap the watchtower client DB and make sure we clean up.
1362  	if cfg.WtClient.Active {
1363  		dbs.TowerClientDB, err = wtdb.OpenClientDB(
1364  			databaseBackends.TowerClientDB,
1365  		)
1366  		if err != nil {
1367  			cleanUp()
1368  
1369  			err = fmt.Errorf("unable to open %s database: %w",
1370  				lncfg.NSTowerClientDB, err)
1371  			d.logger.Error(err)
1372  			return nil, nil, err
1373  		}
1374  	}
1375  
1376  	// Wrap the watchtower server DB and make sure we clean up.
1377  	if cfg.Watchtower.Active {
1378  		dbs.TowerServerDB, err = wtdb.OpenTowerDB(
1379  			databaseBackends.TowerServerDB,
1380  		)
1381  		if err != nil {
1382  			cleanUp()
1383  
1384  			err = fmt.Errorf("unable to open %s database: %w",
1385  				lncfg.NSTowerServerDB, err)
1386  			d.logger.Error(err)
1387  			return nil, nil, err
1388  		}
1389  	}
1390  
1391  	openTime := time.Since(startOpenTime)
1392  	d.logger.Infof("Database(s) now open (time_to_open=%v)!", openTime)
1393  
1394  	return dbs, cleanUp, nil
1395  }
1396  
1397  // waitForWalletPassword blocks until a password is provided by the user to
1398  // this RPC server.
1399  func waitForWalletPassword(cfg *Config,
1400  	pwService *walletunlocker.UnlockerService,
1401  	loaderOpts []btcwallet.LoaderOption, shutdownChan <-chan struct{}) (
1402  	*walletunlocker.WalletUnlockParams, error) {
1403  
1404  	// Wait for user to provide the password.
1405  	ltndLog.Infof("Waiting for wallet encryption password. Use `lncli " +
1406  		"create` to create a wallet, `lncli unlock` to unlock an " +
1407  		"existing wallet, or `lncli changepassword` to change the " +
1408  		"password of an existing wallet and unlock it.")
1409  
1410  	// We currently don't distinguish between getting a password to be used
1411  	// for creation or unlocking, as a new wallet db will be created if
1412  	// none exists when creating the chain control.
1413  	select {
1414  	// The wallet is being created for the first time, we'll check to see
1415  	// if the user provided any entropy for seed creation. If so, then
1416  	// we'll create the wallet early to load the seed.
1417  	case initMsg := <-pwService.InitMsgs:
1418  		password := initMsg.Passphrase
1419  		cipherSeed := initMsg.WalletSeed
1420  		extendedKey := initMsg.WalletExtendedKey
1421  		watchOnlyAccounts := initMsg.WatchOnlyAccounts
1422  		recoveryWindow := initMsg.RecoveryWindow
1423  
1424  		// Before we proceed, we'll check the internal version of the
1425  		// seed. If it's greater than the current key derivation
1426  		// version, then we'll return an error as we don't understand
1427  		// this.
1428  		if cipherSeed != nil &&
1429  			!keychain.IsKnownVersion(cipherSeed.InternalVersion) {
1430  
1431  			return nil, fmt.Errorf("invalid internal "+
1432  				"seed version %v, current max version is %v",
1433  				cipherSeed.InternalVersion,
1434  				keychain.CurrentKeyDerivationVersion)
1435  		}
1436  
1437  		loader, err := btcwallet.NewWalletLoader(
1438  			cfg.ActiveNetParams.Params, recoveryWindow,
1439  			loaderOpts...,
1440  		)
1441  		if err != nil {
1442  			return nil, err
1443  		}
1444  
1445  		// With the seed, we can now use the wallet loader to create
1446  		// the wallet, then pass it back to avoid unlocking it again.
1447  		var (
1448  			birthday  time.Time
1449  			newWallet *wallet.Wallet
1450  		)
1451  		switch {
1452  		// A normal cipher seed was given, use the birthday encoded in
1453  		// it and create the wallet from that.
1454  		case cipherSeed != nil:
1455  			birthday = cipherSeed.BirthdayTime()
1456  			newWallet, err = loader.CreateNewWallet(
1457  				password, password, cipherSeed.Entropy[:],
1458  				birthday,
1459  			)
1460  
1461  		// No seed was given, we're importing a wallet from its extended
1462  		// private key.
1463  		case extendedKey != nil:
1464  			birthday = initMsg.ExtendedKeyBirthday
1465  			newWallet, err = loader.CreateNewWalletExtendedKey(
1466  				password, password, extendedKey, birthday,
1467  			)
1468  
1469  		// Neither seed nor extended private key was given, so maybe the
1470  		// third option was chosen, the watch-only initialization. In
1471  		// this case we need to import each of the xpubs individually.
1472  		case watchOnlyAccounts != nil:
1473  			if !cfg.RemoteSigner.Enable {
1474  				return nil, fmt.Errorf("cannot initialize " +
1475  					"watch only wallet with remote " +
1476  					"signer config disabled")
1477  			}
1478  
1479  			birthday = initMsg.WatchOnlyBirthday
1480  			newWallet, err = loader.CreateNewWatchingOnlyWallet(
1481  				password, birthday,
1482  			)
1483  			if err != nil {
1484  				break
1485  			}
1486  
1487  			err = importWatchOnlyAccounts(newWallet, initMsg)
1488  
1489  		default:
1490  			// The unlocker service made sure either the cipher seed
1491  			// or the extended key is set so, we shouldn't get here.
1492  			// The default case is just here for readability and
1493  			// completeness.
1494  			err = fmt.Errorf("cannot create wallet, neither seed " +
1495  				"nor extended key was given")
1496  		}
1497  		if err != nil {
1498  			// Don't leave the file open in case the new wallet
1499  			// could not be created for whatever reason.
1500  			if err := loader.UnloadWallet(); err != nil {
1501  				ltndLog.Errorf("Could not unload new "+
1502  					"wallet: %v", err)
1503  			}
1504  			return nil, err
1505  		}
1506  
1507  		// For new wallets, the ResetWalletTransactions flag is a no-op.
1508  		if cfg.ResetWalletTransactions {
1509  			ltndLog.Warnf("Ignoring reset-wallet-transactions " +
1510  				"flag for new wallet as it has no effect")
1511  		}
1512  
1513  		return &walletunlocker.WalletUnlockParams{
1514  			Password:        password,
1515  			Birthday:        birthday,
1516  			RecoveryWindow:  recoveryWindow,
1517  			Wallet:          newWallet,
1518  			ChansToRestore:  initMsg.ChanBackups,
1519  			UnloadWallet:    loader.UnloadWallet,
1520  			StatelessInit:   initMsg.StatelessInit,
1521  			MacResponseChan: pwService.MacResponseChan,
1522  			MacRootKey:      initMsg.MacRootKey,
1523  		}, nil
1524  
1525  	// The wallet has already been created in the past, and is simply being
1526  	// unlocked. So we'll just return these passphrases.
1527  	case unlockMsg := <-pwService.UnlockMsgs:
1528  		// Resetting the transactions is something the user likely only
1529  		// wants to do once so we add a prominent warning to the log to
1530  		// remind the user to turn off the setting again after
1531  		// successful completion.
1532  		if cfg.ResetWalletTransactions {
1533  			ltndLog.Warnf("Dropped all transaction history from " +
1534  				"on-chain wallet. Remember to disable " +
1535  				"reset-wallet-transactions flag for next " +
1536  				"start of lnd")
1537  		}
1538  
1539  		return &walletunlocker.WalletUnlockParams{
1540  			Password:        unlockMsg.Passphrase,
1541  			RecoveryWindow:  unlockMsg.RecoveryWindow,
1542  			Wallet:          unlockMsg.Wallet,
1543  			ChansToRestore:  unlockMsg.ChanBackups,
1544  			UnloadWallet:    unlockMsg.UnloadWallet,
1545  			StatelessInit:   unlockMsg.StatelessInit,
1546  			MacResponseChan: pwService.MacResponseChan,
1547  		}, nil
1548  
1549  	// If we got a shutdown signal we just return with an error immediately
1550  	case <-shutdownChan:
1551  		return nil, fmt.Errorf("shutting down")
1552  	}
1553  }
1554  
1555  // importWatchOnlyAccounts imports all individual account xpubs into our wallet
1556  // which we created as watch-only.
1557  func importWatchOnlyAccounts(wallet *wallet.Wallet,
1558  	initMsg *walletunlocker.WalletInitMsg) error {
1559  
1560  	scopes := make([]waddrmgr.ScopedIndex, 0, len(initMsg.WatchOnlyAccounts))
1561  	for scope := range initMsg.WatchOnlyAccounts {
1562  		scopes = append(scopes, scope)
1563  	}
1564  
1565  	// We need to import the accounts in the correct order, otherwise the
1566  	// indices will be incorrect.
1567  	sort.Slice(scopes, func(i, j int) bool {
1568  		return scopes[i].Scope.Purpose < scopes[j].Scope.Purpose ||
1569  			scopes[i].Index < scopes[j].Index
1570  	})
1571  
1572  	for _, scope := range scopes {
1573  		addrSchema := waddrmgr.ScopeAddrMap[waddrmgr.KeyScopeBIP0084]
1574  
1575  		// We want witness pubkey hash by default, except for BIP49
1576  		// where we want mixed and BIP86 where we want taproot address
1577  		// formats.
1578  		switch scope.Scope.Purpose {
1579  		case waddrmgr.KeyScopeBIP0049Plus.Purpose,
1580  			waddrmgr.KeyScopeBIP0086.Purpose:
1581  
1582  			addrSchema = waddrmgr.ScopeAddrMap[scope.Scope]
1583  		}
1584  
1585  		// We want a human-readable account name. But for the default
1586  		// on-chain wallet we actually need to call it "default" to make
1587  		// sure everything works correctly.
1588  		name := fmt.Sprintf("%s/%d'", scope.Scope.String(), scope.Index)
1589  		if scope.Index == 0 {
1590  			name = "default"
1591  		}
1592  
1593  		_, err := wallet.ImportAccountWithScope(
1594  			name, initMsg.WatchOnlyAccounts[scope],
1595  			initMsg.WatchOnlyMasterFingerprint, scope.Scope,
1596  			addrSchema,
1597  		)
1598  		if err != nil {
1599  			return fmt.Errorf("could not import account %v: %w",
1600  				name, err)
1601  		}
1602  	}
1603  
1604  	return nil
1605  }
1606  
1607  // handleNeutrinoPostgresDBMigration handles the migration of the neutrino db
1608  // to postgres. Initially we kept the neutrino db in the bolt db when running
1609  // with kvdb postgres backend. Now now move it to postgres as well. However we
1610  // need to make a distinction whether the user migrated the neutrino db to
1611  // postgres via lndinit or not. Currently if the db is not migrated we start
1612  // with a fresh db in postgres.
1613  //
1614  // TODO(ziggie): Also migrate the db to postgres in case it is still not
1615  // migrated ?
1616  func handleNeutrinoPostgresDBMigration(dbName, dbPath string,
1617  	cfg *Config) error {
1618  
1619  	if !lnrpc.FileExists(dbName) {
1620  		return nil
1621  	}
1622  
1623  	// Open bolt db to check if it is tombstoned. If it is we assume that
1624  	// the neutrino db was successfully migrated to postgres. We open it
1625  	// in read-only mode to avoid long db open times.
1626  	boltDB, err := kvdb.Open(
1627  		kvdb.BoltBackendName, dbName, true,
1628  		cfg.DB.Bolt.DBTimeout, true,
1629  	)
1630  	if err != nil {
1631  		return fmt.Errorf("failed to open bolt db: %w", err)
1632  	}
1633  	defer boltDB.Close()
1634  
1635  	isTombstoned := false
1636  	err = boltDB.View(func(tx kvdb.RTx) error {
1637  		_, err = channeldb.CheckMarkerPresent(
1638  			tx, channeldb.TombstoneKey,
1639  		)
1640  
1641  		return err
1642  	}, func() {})
1643  	if err == nil {
1644  		isTombstoned = true
1645  	}
1646  
1647  	if isTombstoned {
1648  		ltndLog.Infof("Neutrino Bolt DB is tombstoned, assuming " +
1649  			"database was successfully migrated to postgres")
1650  
1651  		return nil
1652  	}
1653  
1654  	// If the db is not tombstoned, we remove the files and start fresh with
1655  	// postgres. This is the case when a user was running lnd with the
1656  	// postgres backend from the beginning without migrating from bolt.
1657  	ltndLog.Infof("Neutrino Bolt DB found but NOT tombstoned, removing " +
1658  		"it and starting fresh with postgres")
1659  
1660  	filesToRemove := []string{
1661  		filepath.Join(dbPath, "block_headers.bin"),
1662  		filepath.Join(dbPath, "reg_filter_headers.bin"),
1663  		dbName,
1664  	}
1665  
1666  	for _, file := range filesToRemove {
1667  		if err := os.Remove(file); err != nil {
1668  			ltndLog.Warnf("Could not remove %s: %v", file, err)
1669  		}
1670  	}
1671  
1672  	return nil
1673  }
1674  
1675  // initNeutrinoBackend inits a new instance of the neutrino light client
1676  // backend given a target chain directory to store the chain state.
1677  func initNeutrinoBackend(ctx context.Context, cfg *Config, chainDir string,
1678  	blockCache *blockcache.BlockCache) (*neutrino.ChainService,
1679  	func(), error) {
1680  
1681  	// Both channel validation flags are false by default but their meaning
1682  	// is the inverse of each other. Therefore both cannot be true. For
1683  	// every other case, the neutrino.validatechannels overwrites the
1684  	// routing.assumechanvalid value.
1685  	if cfg.NeutrinoMode.ValidateChannels && cfg.Routing.AssumeChannelValid {
1686  		return nil, nil, fmt.Errorf("can't set both " +
1687  			"neutrino.validatechannels and routing." +
1688  			"assumechanvalid to true at the same time")
1689  	}
1690  	cfg.Routing.AssumeChannelValid = !cfg.NeutrinoMode.ValidateChannels
1691  
1692  	// First we'll open the database file for neutrino, creating the
1693  	// database if needed. We append the normalized network name here to
1694  	// match the behavior of btcwallet.
1695  	dbPath := filepath.Join(
1696  		chainDir, lncfg.NormalizeNetwork(cfg.ActiveNetParams.Name),
1697  	)
1698  
1699  	// Ensure that the neutrino db path exists.
1700  	if err := os.MkdirAll(dbPath, 0700); err != nil {
1701  		return nil, nil, err
1702  	}
1703  
1704  	var (
1705  		db  walletdb.DB
1706  		err error
1707  	)
1708  	switch {
1709  	case cfg.DB.Backend == kvdb.SqliteBackendName:
1710  		sqliteConfig := lncfg.GetSqliteConfigKVDB(cfg.DB.Sqlite)
1711  		db, err = kvdb.Open(
1712  			kvdb.SqliteBackendName, ctx, sqliteConfig, dbPath,
1713  			lncfg.SqliteNeutrinoDBName, lncfg.NSNeutrinoDB,
1714  		)
1715  
1716  	case cfg.DB.Backend == kvdb.PostgresBackendName:
1717  		dbName := filepath.Join(dbPath, lncfg.NeutrinoDBName)
1718  
1719  		// This code needs to be in place because we did not start
1720  		// the postgres backend for neutrino at the beginning. Now we
1721  		// are also moving it into the postgres backend so we can phase
1722  		// out the bolt backend.
1723  		err = handleNeutrinoPostgresDBMigration(dbName, dbPath, cfg)
1724  		if err != nil {
1725  			return nil, nil, err
1726  		}
1727  
1728  		postgresConfig := lncfg.GetPostgresConfigKVDB(cfg.DB.Postgres)
1729  		db, err = kvdb.Open(
1730  			kvdb.PostgresBackendName, ctx, postgresConfig,
1731  			lncfg.NSNeutrinoDB,
1732  		)
1733  
1734  	default:
1735  		dbName := filepath.Join(dbPath, lncfg.NeutrinoDBName)
1736  		db, err = walletdb.Create(
1737  			kvdb.BoltBackendName, dbName, !cfg.SyncFreelist,
1738  			cfg.DB.Bolt.DBTimeout, false,
1739  		)
1740  	}
1741  	if err != nil {
1742  		return nil, nil, fmt.Errorf("unable to create "+
1743  			"neutrino database: %v", err)
1744  	}
1745  
1746  	headerStateAssertion, err := parseHeaderStateAssertion(
1747  		cfg.NeutrinoMode.AssertFilterHeader,
1748  	)
1749  	if err != nil {
1750  		db.Close()
1751  		return nil, nil, err
1752  	}
1753  
1754  	// With the database open, we can now create an instance of the
1755  	// neutrino light client. We pass in relevant configuration parameters
1756  	// required.
1757  	config := neutrino.Config{
1758  		DataDir:      dbPath,
1759  		Database:     db,
1760  		ChainParams:  *cfg.ActiveNetParams.Params,
1761  		AddPeers:     cfg.NeutrinoMode.AddPeers,
1762  		ConnectPeers: cfg.NeutrinoMode.ConnectPeers,
1763  		Dialer: func(addr net.Addr) (net.Conn, error) {
1764  			return cfg.net.Dial(
1765  				addr.Network(), addr.String(),
1766  				cfg.ConnectionTimeout,
1767  			)
1768  		},
1769  		NameResolver: func(host string) ([]net.IP, error) {
1770  			addrs, err := cfg.net.LookupHost(host)
1771  			if err != nil {
1772  				return nil, err
1773  			}
1774  
1775  			ips := make([]net.IP, 0, len(addrs))
1776  			for _, strIP := range addrs {
1777  				ip := net.ParseIP(strIP)
1778  				if ip == nil {
1779  					continue
1780  				}
1781  
1782  				ips = append(ips, ip)
1783  			}
1784  
1785  			return ips, nil
1786  		},
1787  		AssertFilterHeader: headerStateAssertion,
1788  		BlockCache:         blockCache.Cache,
1789  		BroadcastTimeout:   cfg.NeutrinoMode.BroadcastTimeout,
1790  		PersistToDisk:      cfg.NeutrinoMode.PersistFilters,
1791  	}
1792  
1793  	if cfg.NeutrinoMode.MaxPeers <= 0 {
1794  		return nil, nil, fmt.Errorf("a non-zero number must be set " +
1795  			"for neutrino max peers")
1796  	}
1797  	neutrino.MaxPeers = cfg.NeutrinoMode.MaxPeers
1798  	neutrino.BanDuration = time.Hour * 48
1799  	neutrino.UserAgentName = cfg.NeutrinoMode.UserAgentName
1800  	neutrino.UserAgentVersion = cfg.NeutrinoMode.UserAgentVersion
1801  
1802  	neutrinoCS, err := neutrino.NewChainService(config)
1803  	if err != nil {
1804  		db.Close()
1805  		return nil, nil, fmt.Errorf("unable to create neutrino light "+
1806  			"client: %v", err)
1807  	}
1808  
1809  	if err := neutrinoCS.Start(); err != nil {
1810  		db.Close()
1811  		return nil, nil, err
1812  	}
1813  
1814  	cleanUp := func() {
1815  		if err := neutrinoCS.Stop(); err != nil {
1816  			ltndLog.Infof("Unable to stop neutrino light client: "+
1817  				"%v", err)
1818  		}
1819  		db.Close()
1820  	}
1821  
1822  	return neutrinoCS, cleanUp, nil
1823  }
1824  
1825  // parseHeaderStateAssertion parses the user-specified neutrino header state
1826  // into a headerfs.FilterHeader.
1827  func parseHeaderStateAssertion(state string) (*headerfs.FilterHeader, error) {
1828  	if len(state) == 0 {
1829  		return nil, nil
1830  	}
1831  
1832  	split := strings.Split(state, ":")
1833  	if len(split) != 2 {
1834  		return nil, fmt.Errorf("header state assertion %v in "+
1835  			"unexpected format, expected format height:hash", state)
1836  	}
1837  
1838  	height, err := strconv.ParseUint(split[0], 10, 32)
1839  	if err != nil {
1840  		return nil, fmt.Errorf("invalid filter header height: %w", err)
1841  	}
1842  
1843  	hash, err := chainhash.NewHashFromStr(split[1])
1844  	if err != nil {
1845  		return nil, fmt.Errorf("invalid filter header hash: %w", err)
1846  	}
1847  
1848  	return &headerfs.FilterHeader{
1849  		Height:     uint32(height),
1850  		FilterHash: *hash,
1851  	}, nil
1852  }
1853  
1854  // broadcastErrorMapper maps errors from bitcoin backends other than neutrino to
1855  // the neutrino BroadcastError which allows the Rebroadcaster which currently
1856  // resides in the neutrino package to use all of its functionalities.
1857  func broadcastErrorMapper(err error) error {
1858  	var returnErr error
1859  
1860  	// We only filter for specific backend errors which are relevant for the
1861  	// Rebroadcaster.
1862  	switch {
1863  	// This makes sure the tx is removed from the rebroadcaster once it is
1864  	// confirmed.
1865  	case errors.Is(err, chain.ErrTxAlreadyKnown),
1866  		errors.Is(err, chain.ErrTxAlreadyConfirmed):
1867  
1868  		returnErr = &pushtx.BroadcastError{
1869  			Code:   pushtx.Confirmed,
1870  			Reason: err.Error(),
1871  		}
1872  
1873  	// Transactions which are still in mempool but might fall out because
1874  	// of low fees are rebroadcasted despite of their backend error.
1875  	case errors.Is(err, chain.ErrTxAlreadyInMempool):
1876  		returnErr = &pushtx.BroadcastError{
1877  			Code:   pushtx.Mempool,
1878  			Reason: err.Error(),
1879  		}
1880  
1881  	// Transactions which are not accepted into mempool because of low fees
1882  	// in the first place are rebroadcasted despite of their backend error.
1883  	// Mempool conditions change over time so it makes sense to retry
1884  	// publishing the transaction. Moreover we log the detailed error so the
1885  	// user can intervene and increase the size of his mempool or increase
1886  	// his min relay fee configuration.
1887  	case errors.Is(err, chain.ErrMempoolMinFeeNotMet),
1888  		errors.Is(err, chain.ErrMinRelayFeeNotMet):
1889  
1890  		ltndLog.Warnf("Error while broadcasting transaction: %v", err)
1891  
1892  		returnErr = &pushtx.BroadcastError{
1893  			Code:   pushtx.Mempool,
1894  			Reason: err.Error(),
1895  		}
1896  	}
1897  
1898  	return returnErr
1899  }