lnd+chainregistry: initialize neutrino light client before wallet setup

In this commit, we slightly refactor the startup of lnd when running
with a Neutrino light client backend. We'll now begin syncing our
backend as soon as lnd starts and passes all configuration checks. Since
this is all done before lnd's wallet setup, the light client will be
syncing in the background while the user notes/inputs their wallet seed.
This is done in order to provide a better UX from the point of the user,
such that most of the chain will already be synced by the time they get
to deposit funds into the wallet.
This commit is contained in:
Wilmer Paulino
2019-02-11 18:35:45 -08:00
committed by Olaoluwa Osuntokun
parent d0757221b4
commit 1fe6599fd8
2 changed files with 93 additions and 78 deletions

79
lnd.go
View File

@ -35,8 +35,10 @@ import (
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcwallet/wallet"
"github.com/btcsuite/btcwallet/walletdb"
proxy "github.com/grpc-ecosystem/grpc-gateway/runtime"
flags "github.com/jessevdk/go-flags"
"github.com/lightninglabs/neutrino"
"github.com/lightningnetwork/lnd/autopilot"
"github.com/lightningnetwork/lnd/build"
@ -196,6 +198,81 @@ func lndMain() error {
}
proxyOpts := []grpc.DialOption{grpc.WithTransportCredentials(cCreds)}
// Before starting the wallet, we'll create and start our Neutrino light
// client instance, if enabled, in order to allow it to sync while the
// rest of the daemon continues startup.
mainChain := cfg.Bitcoin
if registeredChains.PrimaryChain() == litecoinChain {
mainChain = cfg.Litecoin
}
var neutrinoCS *neutrino.ChainService
if mainChain.Node == "neutrino" {
// First we'll open the database file for neutrino, creating
// the database if needed. We append the normalized network name
// here to match the behavior of btcwallet.
dbPath := filepath.Join(
mainChain.ChainDir,
normalizeNetwork(activeNetParams.Name),
)
// Ensure that the neutrino db path exists.
if err := os.MkdirAll(dbPath, 0700); err != nil {
return err
}
dbName := filepath.Join(dbPath, "neutrino.db")
db, err := walletdb.Create("bdb", dbName)
if err != nil {
return fmt.Errorf("unable to create neutrino "+
"database: %v", err)
}
defer db.Close()
// With the database open, we can now create an instance of the
// neutrino light client. We pass in relevant configuration
// parameters required.
config := neutrino.Config{
DataDir: dbPath,
Database: db,
ChainParams: *activeNetParams.Params,
AddPeers: cfg.NeutrinoMode.AddPeers,
ConnectPeers: cfg.NeutrinoMode.ConnectPeers,
Dialer: func(addr net.Addr) (net.Conn, error) {
return cfg.net.Dial(addr.Network(), addr.String())
},
NameResolver: func(host string) ([]net.IP, error) {
addrs, err := cfg.net.LookupHost(host)
if err != nil {
return nil, err
}
ips := make([]net.IP, 0, len(addrs))
for _, strIP := range addrs {
ip := net.ParseIP(strIP)
if ip == nil {
continue
}
ips = append(ips, ip)
}
return ips, nil
},
}
neutrino.MaxPeers = 8
neutrino.BanDuration = 5 * time.Second
neutrinoCS, err = neutrino.NewChainService(config)
if err != nil {
return fmt.Errorf("unable to create neutrino light "+
"client: %v", err)
}
neutrinoCS.Start()
defer neutrinoCS.Stop()
}
var (
privateWalletPw = lnwallet.DefaultPrivatePassphrase
publicWalletPw = lnwallet.DefaultPublicPassphrase
@ -269,7 +346,7 @@ func lndMain() error {
// Lightning Network Daemon.
activeChainControl, chainCleanUp, err := newChainControlFromConfig(
cfg, chanDB, privateWalletPw, publicWalletPw, birthday,
recoveryWindow, unlockedWallet,
recoveryWindow, unlockedWallet, neutrinoCS,
)
if err != nil {
fmt.Printf("unable to create chain control: %v\n", err)