diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index 30025ad1..d746f4eb 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -226,7 +226,7 @@ type ChainControl struct { // full-node, another backed by a running bitcoind full-node, and the other // backed by a running neutrino light client instance. When running with a // neutrino light client instance, `neutrinoCS` must be non-nil. -func NewChainControl(cfg *Config) (*ChainControl, error) { +func NewChainControl(cfg *Config) (*ChainControl, func(), error) { // Set the RPC config from the "home" chain. Multi-chain isn't yet // active, so we'll restrict usage to a particular chain for now. @@ -264,7 +264,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { DefaultLitecoinStaticFeePerKW, 0, ) default: - return nil, fmt.Errorf("default routing policy for chain %v is "+ + return nil, nil, fmt.Errorf("default routing policy for chain %v is "+ "unknown", cfg.PrimaryChain()) } @@ -294,7 +294,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { heightHintCacheConfig, cfg.LocalChanDB, ) if err != nil { - return nil, fmt.Errorf("unable to initialize height hint "+ + return nil, nil, fmt.Errorf("unable to initialize height hint "+ "cache: %v", err) } @@ -311,14 +311,14 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { ) cc.ChainView, err = chainview.NewCfFilteredChainView(cfg.NeutrinoCS) if err != nil { - return nil, err + return nil, nil, err } // Map the deprecated neutrino feeurl flag to the general fee // url. if cfg.NeutrinoMode.FeeURL != "" { if cfg.FeeURL != "" { - return nil, errors.New("feeurl and " + + return nil, nil, errors.New("feeurl and " + "neutrino.feeurl are mutually exclusive") } @@ -358,7 +358,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { // this back to the btcwallet/bitcoind port. rpcPort, err := strconv.Atoi(cfg.ActiveNetParams.RPCPort) if err != nil { - return nil, err + return nil, nil, err } rpcPort -= 2 bitcoindHost = fmt.Sprintf("%v:%d", @@ -390,11 +390,11 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { 5*time.Second, ) if err != nil { - return nil, err + return nil, nil, err } if err := bitcoindConn.Start(); err != nil { - return nil, fmt.Errorf("unable to connect to bitcoind: "+ + return nil, nil, fmt.Errorf("unable to connect to bitcoind: "+ "%v", err) } @@ -429,7 +429,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { fallBackFeeRate.FeePerKWeight(), ) if err != nil { - return nil, err + return nil, nil, err } } else if cfg.Litecoin.Active && !cfg.Litecoin.RegTest { log.Infof("Initializing litecoind backed fee estimator in "+ @@ -445,7 +445,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { fallBackFeeRate.FeePerKWeight(), ) if err != nil { - return nil, err + return nil, nil, err } } @@ -454,14 +454,14 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { // connection. chainConn, err := rpcclient.New(rpcConfig, nil) if err != nil { - return nil, err + return nil, nil, err } // The api we will use for our health check depends on the // bitcoind version. cmd, err := getBitcoindHealthCheckCmd(chainConn) if err != nil { - return nil, err + return nil, nil, err } cc.HealthCheck = func() error { @@ -487,19 +487,19 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { if btcdMode.RawRPCCert != "" { rpcCert, err = hex.DecodeString(btcdMode.RawRPCCert) if err != nil { - return nil, err + return nil, nil, err } } else { certFile, err := os.Open(btcdMode.RPCCert) if err != nil { - return nil, err + return nil, nil, err } rpcCert, err = ioutil.ReadAll(certFile) if err != nil { - return nil, err + return nil, nil, err } if err := certFile.Close(); err != nil { - return nil, err + return nil, nil, err } } @@ -531,7 +531,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { rpcConfig, cfg.ActiveNetParams.Params, hintCache, hintCache, ) if err != nil { - return nil, err + return nil, nil, err } // Finally, we'll create an instance of the default chain view to be @@ -539,7 +539,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { cc.ChainView, err = chainview.NewBtcdFilteredChainView(*rpcConfig) if err != nil { log.Errorf("unable to create chain view: %v", err) - return nil, err + return nil, nil, err } // Create a special websockets rpc client for btcd which will be used @@ -547,7 +547,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { chainRPC, err := chain.NewRPCClient(cfg.ActiveNetParams.Params, btcdHost, btcdUser, btcdPass, rpcCert, false, 20) if err != nil { - return nil, err + return nil, nil, err } walletConfig.ChainSource = chainRPC @@ -574,11 +574,11 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { *rpcConfig, fallBackFeeRate.FeePerKWeight(), ) if err != nil { - return nil, err + return nil, nil, err } } default: - return nil, fmt.Errorf("unknown node type: %s", + return nil, nil, fmt.Errorf("unknown node type: %s", homeChainConfig.Node) } @@ -589,7 +589,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { case cfg.FeeURL == "" && cfg.Bitcoin.MainNet && homeChainConfig.Node == "neutrino": - return nil, fmt.Errorf("--feeurl parameter required when " + + return nil, nil, fmt.Errorf("--feeurl parameter required when " + "running neutrino on mainnet") // Override default fee estimator if an external service is specified. @@ -609,15 +609,29 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { ) } + ccCleanup := func() { + if cc.Wallet != nil { + if err := cc.Wallet.Shutdown(); err != nil { + log.Errorf("Failed to shutdown wallet: %v", err) + } + } + + if cc.FeeEstimator != nil { + if err := cc.FeeEstimator.Stop(); err != nil { + log.Errorf("Failed to stop feeEstimator: %v", err) + } + } + } + // Start fee estimator. if err := cc.FeeEstimator.Start(); err != nil { - return nil, err + return nil, nil, err } wc, err := btcwallet.New(*walletConfig) if err != nil { fmt.Printf("unable to create wallet controller: %v\n", err) - return nil, err + return nil, ccCleanup, err } cc.MsgSigner = wc @@ -652,18 +666,17 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { lnWallet, err := lnwallet.NewLightningWallet(walletCfg) if err != nil { fmt.Printf("unable to create wallet: %v\n", err) - return nil, err + return nil, ccCleanup, err } if err := lnWallet.Startup(); err != nil { fmt.Printf("unable to start wallet: %v\n", err) - return nil, err + return nil, ccCleanup, err } log.Info("LightningWallet opened") - cc.Wallet = lnWallet - return cc, nil + return cc, ccCleanup, nil } // getBitcoindHealthCheckCmd queries bitcoind for its version to decide which diff --git a/lnd.go b/lnd.go index d3edde16..0fb866e0 100644 --- a/lnd.go +++ b/lnd.go @@ -545,7 +545,10 @@ func Main(cfg *Config, lisCfg ListenerCfg, interceptor signal.Interceptor) error FeeURL: cfg.FeeURL, } - activeChainControl, err := chainreg.NewChainControl(chainControlCfg) + activeChainControl, cleanup, err := chainreg.NewChainControl(chainControlCfg) + if cleanup != nil { + defer cleanup() + } if err != nil { err := fmt.Errorf("unable to create chain control: %v", err) ltndLog.Error(err)