/ 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 }