mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-07-12 14:12:27 +02:00
chainreg+lnd: split chain control initialization
As a preparation for extracting the wallet related initialization code, we first need to separate the purely configuration related chain control initialization from the wallet related code. We do that by splitting the chain control into a partial and full struct that is initialized in two parts. This also allows us to create the wallet configuration itself outside of the chain control package and we need to thread through fewer parameters through the chain control config.
This commit is contained in:
@ -17,7 +17,6 @@ import (
|
|||||||
"github.com/btcsuite/btcd/rpcclient"
|
"github.com/btcsuite/btcd/rpcclient"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/btcsuite/btcwallet/chain"
|
"github.com/btcsuite/btcwallet/chain"
|
||||||
"github.com/btcsuite/btcwallet/wallet"
|
|
||||||
"github.com/lightninglabs/neutrino"
|
"github.com/lightninglabs/neutrino"
|
||||||
"github.com/lightningnetwork/lnd/blockcache"
|
"github.com/lightningnetwork/lnd/blockcache"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
@ -80,24 +79,6 @@ type Config struct {
|
|||||||
// BlockCache is the main cache for storing block information.
|
// BlockCache is the main cache for storing block information.
|
||||||
BlockCache *blockcache.BlockCache
|
BlockCache *blockcache.BlockCache
|
||||||
|
|
||||||
// PrivateWalletPw is the private wallet password to the underlying
|
|
||||||
// btcwallet instance.
|
|
||||||
PrivateWalletPw []byte
|
|
||||||
|
|
||||||
// PublicWalletPw is the public wallet password to the underlying btcwallet
|
|
||||||
// instance.
|
|
||||||
PublicWalletPw []byte
|
|
||||||
|
|
||||||
// Birthday specifies the time the wallet was initially created.
|
|
||||||
Birthday time.Time
|
|
||||||
|
|
||||||
// RecoveryWindow specifies the address look-ahead for which to scan when
|
|
||||||
// restoring a wallet.
|
|
||||||
RecoveryWindow uint32
|
|
||||||
|
|
||||||
// Wallet is a pointer to the backing wallet instance.
|
|
||||||
Wallet *wallet.Wallet
|
|
||||||
|
|
||||||
// NeutrinoCS is a pointer to a neutrino ChainService. Must be non-nil if
|
// NeutrinoCS is a pointer to a neutrino ChainService. Must be non-nil if
|
||||||
// using neutrino.
|
// using neutrino.
|
||||||
NeutrinoCS *neutrino.ChainService
|
NeutrinoCS *neutrino.ChainService
|
||||||
@ -113,13 +94,6 @@ type Config struct {
|
|||||||
// TCP connections to Bitcoin peers in the event of a pruned block being
|
// TCP connections to Bitcoin peers in the event of a pruned block being
|
||||||
// requested.
|
// requested.
|
||||||
Dialer chain.Dialer
|
Dialer chain.Dialer
|
||||||
|
|
||||||
// LoaderOptions holds functional wallet db loader options.
|
|
||||||
LoaderOptions []btcwallet.LoaderOption
|
|
||||||
|
|
||||||
// CoinSelectionStrategy is the strategy that is used for selecting
|
|
||||||
// coins when funding a transaction.
|
|
||||||
CoinSelectionStrategy wallet.CoinSelectionStrategy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -181,44 +155,30 @@ var DefaultLtcChannelConstraints = channeldb.ChannelConstraints{
|
|||||||
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
|
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChainControl couples the three primary interfaces lnd utilizes for a
|
// PartialChainControl contains all the primary interfaces of the chain control
|
||||||
// particular chain together. A single ChainControl instance will exist for all
|
// that can be purely constructed from the global configuration. No wallet
|
||||||
// the chains lnd is currently active on.
|
// instance is required for constructing this partial state.
|
||||||
type ChainControl struct {
|
type PartialChainControl struct {
|
||||||
// ChainIO represents an abstraction over a source that can query the blockchain.
|
// Cfg is the configuration that was used to create the partial chain
|
||||||
ChainIO lnwallet.BlockChainIO
|
// control.
|
||||||
|
Cfg *Config
|
||||||
|
|
||||||
// HealthCheck is a function which can be used to send a low-cost, fast
|
// HealthCheck is a function which can be used to send a low-cost, fast
|
||||||
// query to the chain backend to ensure we still have access to our
|
// query to the chain backend to ensure we still have access to our
|
||||||
// node.
|
// node.
|
||||||
HealthCheck func() error
|
HealthCheck func() error
|
||||||
|
|
||||||
// FeeEstimator is used to estimate an optimal fee for transactions important to us.
|
// FeeEstimator is used to estimate an optimal fee for transactions
|
||||||
|
// important to us.
|
||||||
FeeEstimator chainfee.Estimator
|
FeeEstimator chainfee.Estimator
|
||||||
|
|
||||||
// Signer is used to provide signatures over things like transactions.
|
// ChainNotifier is used to receive blockchain events that we are
|
||||||
Signer input.Signer
|
// interested in.
|
||||||
|
|
||||||
// KeyRing represents a set of keys that we have the private keys to.
|
|
||||||
KeyRing keychain.SecretKeyRing
|
|
||||||
|
|
||||||
// Wc is an abstraction over some basic wallet commands. This base set of commands
|
|
||||||
// will be provided to the Wallet *LightningWallet raw pointer below.
|
|
||||||
Wc lnwallet.WalletController
|
|
||||||
|
|
||||||
// MsgSigner is used to sign arbitrary messages.
|
|
||||||
MsgSigner lnwallet.MessageSigner
|
|
||||||
|
|
||||||
// ChainNotifier is used to receive blockchain events that we are interested in.
|
|
||||||
ChainNotifier chainntnfs.ChainNotifier
|
ChainNotifier chainntnfs.ChainNotifier
|
||||||
|
|
||||||
// ChainView is used in the router for maintaining an up-to-date graph.
|
// ChainView is used in the router for maintaining an up-to-date graph.
|
||||||
ChainView chainview.FilteredChainView
|
ChainView chainview.FilteredChainView
|
||||||
|
|
||||||
// Wallet is our LightningWallet that also contains the abstract Wc above. This wallet
|
|
||||||
// handles all of the lightning operations.
|
|
||||||
Wallet *lnwallet.LightningWallet
|
|
||||||
|
|
||||||
// ChainSource is the primary chain interface. This is used to operate
|
// ChainSource is the primary chain interface. This is used to operate
|
||||||
// the wallet and do things such as rescanning, sending transactions,
|
// the wallet and do things such as rescanning, sending transactions,
|
||||||
// notifications for received funds, etc.
|
// notifications for received funds, etc.
|
||||||
@ -235,8 +195,40 @@ type ChainControl struct {
|
|||||||
ChannelConstraints channeldb.ChannelConstraints
|
ChannelConstraints channeldb.ChannelConstraints
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenDefaultBtcChannelConstraints generates the default set of channel
|
// ChainControl couples the three primary interfaces lnd utilizes for a
|
||||||
// constraints that are to be used when funding a Bitcoin channel.
|
// particular chain together. A single ChainControl instance will exist for all
|
||||||
|
// the chains lnd is currently active on.
|
||||||
|
type ChainControl struct {
|
||||||
|
// PartialChainControl is the part of the chain control that was
|
||||||
|
// initialized purely from the configuration and doesn't contain any
|
||||||
|
// wallet related elements.
|
||||||
|
*PartialChainControl
|
||||||
|
|
||||||
|
// ChainIO represents an abstraction over a source that can query the
|
||||||
|
// blockchain.
|
||||||
|
ChainIO lnwallet.BlockChainIO
|
||||||
|
|
||||||
|
// Signer is used to provide signatures over things like transactions.
|
||||||
|
Signer input.Signer
|
||||||
|
|
||||||
|
// KeyRing represents a set of keys that we have the private keys to.
|
||||||
|
KeyRing keychain.SecretKeyRing
|
||||||
|
|
||||||
|
// Wc is an abstraction over some basic wallet commands. This base set
|
||||||
|
// of commands will be provided to the Wallet *LightningWallet raw
|
||||||
|
// pointer below.
|
||||||
|
Wc lnwallet.WalletController
|
||||||
|
|
||||||
|
// MsgSigner is used to sign arbitrary messages.
|
||||||
|
MsgSigner lnwallet.MessageSigner
|
||||||
|
|
||||||
|
// Wallet is our LightningWallet that also contains the abstract Wc
|
||||||
|
// above. This wallet handles all of the lightning operations.
|
||||||
|
Wallet *lnwallet.LightningWallet
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenDefaultBtcConstraints generates the default set of channel constraints
|
||||||
|
// that are to be used when funding a Bitcoin channel.
|
||||||
func GenDefaultBtcConstraints() channeldb.ChannelConstraints {
|
func GenDefaultBtcConstraints() channeldb.ChannelConstraints {
|
||||||
// We use the dust limit for the maximally sized witness program with
|
// We use the dust limit for the maximally sized witness program with
|
||||||
// a 40-byte data push.
|
// a 40-byte data push.
|
||||||
@ -248,23 +240,21 @@ func GenDefaultBtcConstraints() channeldb.ChannelConstraints {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewChainControl attempts to create a ChainControl instance according
|
// NewPartialChainControl creates a new partial chain control that contains all
|
||||||
// to the parameters in the passed configuration. Currently three
|
// the parts that can be purely constructed from the passed in global
|
||||||
// branches of ChainControl instances exist: one backed by a running btcd
|
// configuration and doesn't need any wallet instance yet.
|
||||||
// full-node, another backed by a running bitcoind full-node, and the other
|
func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
|
||||||
// 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, func(), error) {
|
|
||||||
// Set the RPC config from the "home" chain. Multi-chain isn't yet
|
// 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.
|
// active, so we'll restrict usage to a particular chain for now.
|
||||||
homeChainConfig := cfg.Bitcoin
|
homeChainConfig := cfg.Bitcoin
|
||||||
if cfg.PrimaryChain() == LitecoinChain {
|
if cfg.PrimaryChain() == LitecoinChain {
|
||||||
homeChainConfig = cfg.Litecoin
|
homeChainConfig = cfg.Litecoin
|
||||||
}
|
}
|
||||||
log.Infof("Primary chain is set to: %v",
|
log.Infof("Primary chain is set to: %v", cfg.PrimaryChain())
|
||||||
cfg.PrimaryChain())
|
|
||||||
|
|
||||||
cc := &ChainControl{}
|
cc := &PartialChainControl{
|
||||||
|
Cfg: cfg,
|
||||||
|
}
|
||||||
|
|
||||||
switch cfg.PrimaryChain() {
|
switch cfg.PrimaryChain() {
|
||||||
case BitcoinChain:
|
case BitcoinChain:
|
||||||
@ -296,7 +286,6 @@ func NewChainControl(cfg *Config) (*ChainControl, func(), error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
heightHintCacheConfig := chainntnfs.CacheConfig{
|
heightHintCacheConfig := chainntnfs.CacheConfig{
|
||||||
QueryDisable: cfg.HeightHintCacheQueryDisable,
|
QueryDisable: cfg.HeightHintCacheQueryDisable,
|
||||||
}
|
}
|
||||||
@ -643,12 +632,6 @@ func NewChainControl(cfg *Config) (*ChainControl, func(), error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ccCleanup := func() {
|
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 cc.FeeEstimator != nil {
|
||||||
if err := cc.FeeEstimator.Stop(); err != nil {
|
if err := cc.FeeEstimator.Stop(); err != nil {
|
||||||
log.Errorf("Failed to stop feeEstimator: %v", err)
|
log.Errorf("Failed to stop feeEstimator: %v", err)
|
||||||
@ -667,20 +650,31 @@ func NewChainControl(cfg *Config) (*ChainControl, func(), error) {
|
|||||||
cc.ChannelConstraints = DefaultLtcChannelConstraints
|
cc.ChannelConstraints = DefaultLtcChannelConstraints
|
||||||
}
|
}
|
||||||
|
|
||||||
walletConfig := &btcwallet.Config{
|
return cc, ccCleanup, nil
|
||||||
PrivatePass: cfg.PrivateWalletPw,
|
}
|
||||||
PublicPass: cfg.PublicWalletPw,
|
|
||||||
Birthday: cfg.Birthday,
|
// NewChainControl attempts to create a ChainControl instance according
|
||||||
RecoveryWindow: cfg.RecoveryWindow,
|
// to the parameters in the passed configuration. Currently three
|
||||||
NetParams: cfg.ActiveNetParams.Params,
|
// branches of ChainControl instances exist: one backed by a running btcd
|
||||||
CoinType: cfg.ActiveNetParams.CoinType,
|
// full-node, another backed by a running bitcoind full-node, and the other
|
||||||
Wallet: cfg.Wallet,
|
// backed by a running neutrino light client instance. When running with a
|
||||||
LoaderOptions: cfg.LoaderOptions,
|
// neutrino light client instance, `neutrinoCS` must be non-nil.
|
||||||
CoinSelectionStrategy: cfg.CoinSelectionStrategy,
|
func NewChainControl(walletConfig *btcwallet.Config,
|
||||||
ChainSource: cc.ChainSource,
|
pcc *PartialChainControl) (*ChainControl, func(), error) {
|
||||||
|
|
||||||
|
cc := &ChainControl{
|
||||||
|
PartialChainControl: pcc,
|
||||||
}
|
}
|
||||||
|
|
||||||
wc, err := btcwallet.New(*walletConfig, cfg.BlockCache)
|
ccCleanup := func() {
|
||||||
|
if cc.Wallet != nil {
|
||||||
|
if err := cc.Wallet.Shutdown(); err != nil {
|
||||||
|
log.Errorf("Failed to shutdown wallet: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wc, err := btcwallet.New(*walletConfig, pcc.Cfg.BlockCache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("unable to create wallet controller: %v\n", err)
|
fmt.Printf("unable to create wallet controller: %v\n", err)
|
||||||
return nil, ccCleanup, err
|
return nil, ccCleanup, err
|
||||||
@ -692,14 +686,14 @@ func NewChainControl(cfg *Config) (*ChainControl, func(), error) {
|
|||||||
cc.Wc = wc
|
cc.Wc = wc
|
||||||
|
|
||||||
keyRing := keychain.NewBtcWalletKeyRing(
|
keyRing := keychain.NewBtcWalletKeyRing(
|
||||||
wc.InternalWallet(), cfg.ActiveNetParams.CoinType,
|
wc.InternalWallet(), walletConfig.CoinType,
|
||||||
)
|
)
|
||||||
cc.KeyRing = keyRing
|
cc.KeyRing = keyRing
|
||||||
|
|
||||||
// Create, and start the lnwallet, which handles the core payment
|
// Create, and start the lnwallet, which handles the core payment
|
||||||
// channel logic, and exposes control via proxy state machines.
|
// channel logic, and exposes control via proxy state machines.
|
||||||
walletCfg := lnwallet.Config{
|
walletCfg := lnwallet.Config{
|
||||||
Database: cfg.ChanStateDB,
|
Database: pcc.Cfg.ChanStateDB,
|
||||||
Notifier: cc.ChainNotifier,
|
Notifier: cc.ChainNotifier,
|
||||||
WalletController: wc,
|
WalletController: wc,
|
||||||
Signer: cc.Signer,
|
Signer: cc.Signer,
|
||||||
@ -707,7 +701,7 @@ func NewChainControl(cfg *Config) (*ChainControl, func(), error) {
|
|||||||
SecretKeyRing: keyRing,
|
SecretKeyRing: keyRing,
|
||||||
ChainIO: cc.ChainIO,
|
ChainIO: cc.ChainIO,
|
||||||
DefaultConstraints: cc.ChannelConstraints,
|
DefaultConstraints: cc.ChannelConstraints,
|
||||||
NetParams: *cfg.ActiveNetParams.Params,
|
NetParams: *walletConfig.NetParams,
|
||||||
}
|
}
|
||||||
lnWallet, err := lnwallet.NewLightningWallet(walletCfg)
|
lnWallet, err := lnwallet.NewLightningWallet(walletCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
43
lnd.go
43
lnd.go
@ -718,36 +718,59 @@ func Main(cfg *Config, lisCfg ListenerCfg, interceptor signal.Interceptor) error
|
|||||||
LtcdMode: cfg.LtcdMode,
|
LtcdMode: cfg.LtcdMode,
|
||||||
HeightHintDB: dbs.heightHintDB,
|
HeightHintDB: dbs.heightHintDB,
|
||||||
ChanStateDB: dbs.chanStateDB.ChannelStateDB(),
|
ChanStateDB: dbs.chanStateDB.ChannelStateDB(),
|
||||||
PrivateWalletPw: privateWalletPw,
|
|
||||||
PublicWalletPw: publicWalletPw,
|
|
||||||
Birthday: walletInitParams.Birthday,
|
|
||||||
RecoveryWindow: walletInitParams.RecoveryWindow,
|
|
||||||
Wallet: walletInitParams.Wallet,
|
|
||||||
NeutrinoCS: neutrinoCS,
|
NeutrinoCS: neutrinoCS,
|
||||||
ActiveNetParams: cfg.ActiveNetParams,
|
ActiveNetParams: cfg.ActiveNetParams,
|
||||||
FeeURL: cfg.FeeURL,
|
FeeURL: cfg.FeeURL,
|
||||||
Dialer: func(addr string) (net.Conn, error) {
|
Dialer: func(addr string) (net.Conn, error) {
|
||||||
return cfg.net.Dial("tcp", addr, cfg.ConnectionTimeout)
|
return cfg.net.Dial("tcp", addr, cfg.ConnectionTimeout)
|
||||||
},
|
},
|
||||||
BlockCache: blockCache,
|
BlockCache: blockCache,
|
||||||
LoaderOptions: []btcwallet.LoaderOption{dbs.walletDB},
|
}
|
||||||
|
|
||||||
|
// Let's go ahead and create the partial chain control now that is only
|
||||||
|
// dependent on our configuration and doesn't require any wallet
|
||||||
|
// specific information.
|
||||||
|
partialChainControl, cleanup, err := chainreg.NewPartialChainControl(
|
||||||
|
chainControlCfg,
|
||||||
|
)
|
||||||
|
if cleanup != nil {
|
||||||
|
defer cleanup()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("unable to create partial chain control: %v",
|
||||||
|
err)
|
||||||
|
ltndLog.Error(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
walletConfig := &btcwallet.Config{
|
||||||
|
PrivatePass: privateWalletPw,
|
||||||
|
PublicPass: publicWalletPw,
|
||||||
|
Birthday: walletInitParams.Birthday,
|
||||||
|
RecoveryWindow: walletInitParams.RecoveryWindow,
|
||||||
|
NetParams: cfg.ActiveNetParams.Params,
|
||||||
|
CoinType: cfg.ActiveNetParams.CoinType,
|
||||||
|
Wallet: walletInitParams.Wallet,
|
||||||
|
LoaderOptions: []btcwallet.LoaderOption{dbs.walletDB},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse coin selection strategy.
|
// Parse coin selection strategy.
|
||||||
switch cfg.CoinSelectionStrategy {
|
switch cfg.CoinSelectionStrategy {
|
||||||
case "largest":
|
case "largest":
|
||||||
chainControlCfg.CoinSelectionStrategy = wallet.CoinSelectionLargest
|
walletConfig.CoinSelectionStrategy = wallet.CoinSelectionLargest
|
||||||
|
|
||||||
case "random":
|
case "random":
|
||||||
chainControlCfg.CoinSelectionStrategy = wallet.CoinSelectionRandom
|
walletConfig.CoinSelectionStrategy = wallet.CoinSelectionRandom
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown coin selection strategy %v",
|
return fmt.Errorf("unknown coin selection strategy %v",
|
||||||
cfg.CoinSelectionStrategy)
|
cfg.CoinSelectionStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We've created the wallet configuration now, so we can finish
|
||||||
|
// initializing the main chain control.
|
||||||
activeChainControl, cleanup, err := chainreg.NewChainControl(
|
activeChainControl, cleanup, err := chainreg.NewChainControl(
|
||||||
chainControlCfg,
|
walletConfig, partialChainControl,
|
||||||
)
|
)
|
||||||
if cleanup != nil {
|
if cleanup != nil {
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
Reference in New Issue
Block a user