mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-03 17:26:57 +01:00
multi: extract key ring creation from chain control
To make it possible to supply our own implementation of a secret key ring, we extract that part from the chain control and split the whole chain control creation into two parts.
This commit is contained in:
parent
1309c6afea
commit
9fa9dd8e43
4 changed files with 103 additions and 68 deletions
|
@ -30,7 +30,6 @@ import (
|
|||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lncfg"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/routing/chainview"
|
||||
|
@ -664,11 +663,17 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
|
|||
// 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(walletConfig *btcwallet.Config,
|
||||
func NewChainControl(walletConfig lnwallet.Config,
|
||||
msgSigner lnwallet.MessageSigner,
|
||||
pcc *PartialChainControl) (*ChainControl, func(), error) {
|
||||
|
||||
cc := &ChainControl{
|
||||
PartialChainControl: pcc,
|
||||
MsgSigner: msgSigner,
|
||||
Signer: walletConfig.Signer,
|
||||
ChainIO: walletConfig.ChainIO,
|
||||
Wc: walletConfig.WalletController,
|
||||
KeyRing: walletConfig.SecretKeyRing,
|
||||
}
|
||||
|
||||
ccCleanup := func() {
|
||||
|
@ -679,36 +684,7 @@ func NewChainControl(walletConfig *btcwallet.Config,
|
|||
}
|
||||
}
|
||||
|
||||
wc, err := btcwallet.New(*walletConfig, pcc.Cfg.BlockCache)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to create wallet controller: %v\n", err)
|
||||
return nil, ccCleanup, err
|
||||
}
|
||||
|
||||
cc.MsgSigner = wc
|
||||
cc.Signer = wc
|
||||
cc.ChainIO = wc
|
||||
cc.Wc = wc
|
||||
|
||||
keyRing := keychain.NewBtcWalletKeyRing(
|
||||
wc.InternalWallet(), walletConfig.CoinType,
|
||||
)
|
||||
cc.KeyRing = keyRing
|
||||
|
||||
// Create, and start the lnwallet, which handles the core payment
|
||||
// channel logic, and exposes control via proxy state machines.
|
||||
walletCfg := lnwallet.Config{
|
||||
Database: pcc.Cfg.ChanStateDB,
|
||||
Notifier: cc.ChainNotifier,
|
||||
WalletController: wc,
|
||||
Signer: cc.Signer,
|
||||
FeeEstimator: cc.FeeEstimator,
|
||||
SecretKeyRing: keyRing,
|
||||
ChainIO: cc.ChainIO,
|
||||
DefaultConstraints: cc.ChannelConstraints,
|
||||
NetParams: *walletConfig.NetParams,
|
||||
}
|
||||
lnWallet, err := lnwallet.NewLightningWallet(walletCfg)
|
||||
lnWallet, err := lnwallet.NewLightningWallet(walletConfig)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to create wallet: %v\n", err)
|
||||
return nil, ccCleanup, err
|
||||
|
|
|
@ -1547,6 +1547,7 @@ func (c *Config) ImplementationConfig(
|
|||
RestRegistrar: defaultImpl,
|
||||
ExternalValidator: defaultImpl,
|
||||
DatabaseBuilder: NewDefaultDatabaseBuilder(c, ltndLog),
|
||||
WalletConfigBuilder: defaultImpl,
|
||||
ChainControlBuilder: defaultImpl,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,15 +86,24 @@ type DatabaseBuilder interface {
|
|||
BuildDatabase(ctx context.Context) (*DatabaseInstances, func(), error)
|
||||
}
|
||||
|
||||
// WalletConfigBuilder is an interface that must be satisfied by a custom wallet
|
||||
// implementation.
|
||||
type WalletConfigBuilder interface {
|
||||
// BuildWalletConfig is responsible for creating or unlocking and then
|
||||
// fully initializing a wallet.
|
||||
BuildWalletConfig(context.Context, *DatabaseInstances,
|
||||
*rpcperms.InterceptorChain,
|
||||
[]*ListenerWithSignal) (*chainreg.PartialChainControl,
|
||||
*btcwallet.Config, func(), error)
|
||||
}
|
||||
|
||||
// ChainControlBuilder is an interface that must be satisfied by a custom wallet
|
||||
// implementation.
|
||||
type ChainControlBuilder interface {
|
||||
// BuildChainControl is responsible for creating or unlocking and then
|
||||
// fully initializing a wallet and returning it as part of a fully
|
||||
// populated chain control instance.
|
||||
BuildChainControl(context.Context, *DatabaseInstances,
|
||||
*rpcperms.InterceptorChain,
|
||||
[]*ListenerWithSignal) (*chainreg.ChainControl, func(), error)
|
||||
// BuildChainControl is responsible for creating a fully populated chain
|
||||
// control instance from a wallet.
|
||||
BuildChainControl(*chainreg.PartialChainControl,
|
||||
*btcwallet.Config) (*chainreg.ChainControl, func(), error)
|
||||
}
|
||||
|
||||
// ImplementationCfg is a struct that holds all configuration items for
|
||||
|
@ -116,6 +125,10 @@ type ImplementationCfg struct {
|
|||
// backend instances.
|
||||
DatabaseBuilder
|
||||
|
||||
// WalletConfigBuilder is a type that can provide a wallet configuration
|
||||
// with a fully loaded and unlocked wallet.
|
||||
WalletConfigBuilder
|
||||
|
||||
// ChainControlBuilder is a type that can provide a custom wallet
|
||||
// implementation.
|
||||
ChainControlBuilder
|
||||
|
@ -195,15 +208,14 @@ func (d *DefaultWalletImpl) Permissions() map[string][]bakery.Op {
|
|||
return nil
|
||||
}
|
||||
|
||||
// BuildChainControl is responsible for creating or unlocking and then fully
|
||||
// initializing a wallet and returning it as part of a fully populated chain
|
||||
// control instance.
|
||||
// BuildWalletConfig is responsible for creating or unlocking and then
|
||||
// fully initializing a wallet.
|
||||
//
|
||||
// NOTE: This is part of the ChainControlBuilder interface.
|
||||
func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
||||
// NOTE: This is part of the WalletConfigBuilder interface.
|
||||
func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
|
||||
dbs *DatabaseInstances, interceptorChain *rpcperms.InterceptorChain,
|
||||
grpcListeners []*ListenerWithSignal) (*chainreg.ChainControl, func(),
|
||||
error) {
|
||||
grpcListeners []*ListenerWithSignal) (*chainreg.PartialChainControl,
|
||||
*btcwallet.Config, func(), error) {
|
||||
|
||||
// Keep track of our various cleanup functions. We use a defer function
|
||||
// as well to not repeat ourselves with every return statement.
|
||||
|
@ -245,7 +257,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
err := fmt.Errorf("unable to initialize neutrino "+
|
||||
"backend: %v", err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
cleanUpTasks = append(cleanUpTasks, neutrinoCleanUp)
|
||||
neutrinoCS = neutrinoBackend
|
||||
|
@ -270,7 +282,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
d.pwService.SetMacaroonDB(dbs.MacaroonDB)
|
||||
walletExists, err := d.pwService.WalletExists()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
if !walletExists {
|
||||
|
@ -287,9 +299,9 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
if d.cfg.WalletUnlockPasswordFile != "" && !walletExists &&
|
||||
!d.cfg.WalletUnlockAllowCreate {
|
||||
|
||||
return nil, nil, fmt.Errorf("wallet unlock password file was " +
|
||||
"specified but wallet does not exist; initialize the " +
|
||||
"wallet before using auto unlocking")
|
||||
return nil, nil, nil, fmt.Errorf("wallet unlock password file " +
|
||||
"was specified but wallet does not exist; initialize " +
|
||||
"the wallet before using auto unlocking")
|
||||
}
|
||||
|
||||
// What wallet mode are we running in? We've already made sure the no
|
||||
|
@ -306,8 +318,8 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
"password provided in file")
|
||||
pwBytes, err := ioutil.ReadFile(d.cfg.WalletUnlockPasswordFile)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error reading password "+
|
||||
"from file %s: %v",
|
||||
return nil, nil, nil, fmt.Errorf("error reading "+
|
||||
"password from file %s: %v",
|
||||
d.cfg.WalletUnlockPasswordFile, err)
|
||||
}
|
||||
|
||||
|
@ -322,8 +334,8 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
pwBytes, 0,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error unlocking wallet "+
|
||||
"with password from file: %v", err)
|
||||
return nil, nil, nil, fmt.Errorf("error unlocking "+
|
||||
"wallet with password from file: %v", err)
|
||||
}
|
||||
|
||||
cleanUpTasks = append(cleanUpTasks, func() {
|
||||
|
@ -343,7 +355,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
// over RPC.
|
||||
default:
|
||||
if err := d.interceptor.Notifier.NotifyReady(false); err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
params, err := waitForWalletPassword(
|
||||
|
@ -354,7 +366,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
err := fmt.Errorf("unable to set up wallet password "+
|
||||
"listeners: %v", err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
walletInitParams = *params
|
||||
|
@ -386,7 +398,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
err := fmt.Errorf("unable to set up macaroon "+
|
||||
"authentication: %v", err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
cleanUpTasks = append(cleanUpTasks, func() {
|
||||
if err := macaroonService.Close(); err != nil {
|
||||
|
@ -402,7 +414,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
if err != nil && err != macaroons.ErrAlreadyUnlocked {
|
||||
err := fmt.Errorf("unable to unlock macaroons: %v", err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
// In case we actually needed to unlock the wallet, we now need
|
||||
|
@ -415,7 +427,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
ctx, macaroonService, adminPermissions(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
// The channel is buffered by one element so writing
|
||||
|
@ -446,7 +458,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
err := fmt.Errorf("unable to create macaroons "+
|
||||
"%v", err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -538,7 +550,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
err := fmt.Errorf("unable to create partial chain control: %v",
|
||||
err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
walletConfig := &btcwallet.Config{
|
||||
|
@ -562,23 +574,60 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
|||
walletConfig.CoinSelectionStrategy = wallet.CoinSelectionRandom
|
||||
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("unknown coin selection strategy "+
|
||||
"%v", d.cfg.CoinSelectionStrategy)
|
||||
return nil, nil, nil, fmt.Errorf("unknown coin selection "+
|
||||
"strategy %v", d.cfg.CoinSelectionStrategy)
|
||||
}
|
||||
|
||||
earlyExit = false
|
||||
return partialChainControl, walletConfig, cleanUp, nil
|
||||
}
|
||||
|
||||
// BuildChainControl is responsible for creating a fully populated chain
|
||||
// control instance from a wallet.
|
||||
//
|
||||
// NOTE: This is part of the ChainControlBuilder interface.
|
||||
func (d *DefaultWalletImpl) BuildChainControl(
|
||||
partialChainControl *chainreg.PartialChainControl,
|
||||
walletConfig *btcwallet.Config) (*chainreg.ChainControl, func(), error) {
|
||||
|
||||
walletController, err := btcwallet.New(
|
||||
*walletConfig, partialChainControl.Cfg.BlockCache,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Printf("unable to create wallet controller: %v\n", err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
keyRing := keychain.NewBtcWalletKeyRing(
|
||||
walletController.InternalWallet(), walletConfig.CoinType,
|
||||
)
|
||||
|
||||
// Create, and start the lnwallet, which handles the core payment
|
||||
// channel logic, and exposes control via proxy state machines.
|
||||
lnWalletConfig := lnwallet.Config{
|
||||
Database: partialChainControl.Cfg.ChanStateDB,
|
||||
Notifier: partialChainControl.ChainNotifier,
|
||||
WalletController: walletController,
|
||||
Signer: walletController,
|
||||
FeeEstimator: partialChainControl.FeeEstimator,
|
||||
SecretKeyRing: keyRing,
|
||||
ChainIO: walletController,
|
||||
DefaultConstraints: partialChainControl.ChannelConstraints,
|
||||
NetParams: *walletConfig.NetParams,
|
||||
}
|
||||
|
||||
// We've created the wallet configuration now, so we can finish
|
||||
// initializing the main chain control.
|
||||
activeChainControl, ccCleanup, err := chainreg.NewChainControl(
|
||||
walletConfig, partialChainControl,
|
||||
activeChainControl, cleanUp, err := chainreg.NewChainControl(
|
||||
lnWalletConfig, walletController, partialChainControl,
|
||||
)
|
||||
cleanUpTasks = append(cleanUpTasks, ccCleanup)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("unable to create chain control: %v", err)
|
||||
d.logger.Error(err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
earlyExit = false
|
||||
return activeChainControl, cleanUp, nil
|
||||
}
|
||||
|
||||
|
|
11
lnd.go
11
lnd.go
|
@ -361,9 +361,18 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg,
|
|||
|
||||
defer cleanUp()
|
||||
|
||||
activeChainControl, cleanUp, err := implCfg.BuildChainControl(
|
||||
partialChainControl, walletConfig, cleanUp, err := implCfg.BuildWalletConfig(
|
||||
ctx, dbs, interceptorChain, grpcListeners,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating wallet config: %v", err)
|
||||
}
|
||||
|
||||
defer cleanUp()
|
||||
|
||||
activeChainControl, cleanUp, err := implCfg.BuildChainControl(
|
||||
partialChainControl, walletConfig,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading chain control: %v", err)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue