mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-04 01:36:24 +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/kvdb"
|
||||||
"github.com/lightningnetwork/lnd/lncfg"
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/routing/chainview"
|
"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
|
// 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
|
// backed by a running neutrino light client instance. When running with a
|
||||||
// neutrino light client instance, `neutrinoCS` must be non-nil.
|
// 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) {
|
pcc *PartialChainControl) (*ChainControl, func(), error) {
|
||||||
|
|
||||||
cc := &ChainControl{
|
cc := &ChainControl{
|
||||||
PartialChainControl: pcc,
|
PartialChainControl: pcc,
|
||||||
|
MsgSigner: msgSigner,
|
||||||
|
Signer: walletConfig.Signer,
|
||||||
|
ChainIO: walletConfig.ChainIO,
|
||||||
|
Wc: walletConfig.WalletController,
|
||||||
|
KeyRing: walletConfig.SecretKeyRing,
|
||||||
}
|
}
|
||||||
|
|
||||||
ccCleanup := func() {
|
ccCleanup := func() {
|
||||||
|
@ -679,36 +684,7 @@ func NewChainControl(walletConfig *btcwallet.Config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wc, err := btcwallet.New(*walletConfig, pcc.Cfg.BlockCache)
|
lnWallet, err := lnwallet.NewLightningWallet(walletConfig)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("unable to create wallet: %v\n", err)
|
fmt.Printf("unable to create wallet: %v\n", err)
|
||||||
return nil, ccCleanup, err
|
return nil, ccCleanup, err
|
||||||
|
|
|
@ -1547,6 +1547,7 @@ func (c *Config) ImplementationConfig(
|
||||||
RestRegistrar: defaultImpl,
|
RestRegistrar: defaultImpl,
|
||||||
ExternalValidator: defaultImpl,
|
ExternalValidator: defaultImpl,
|
||||||
DatabaseBuilder: NewDefaultDatabaseBuilder(c, ltndLog),
|
DatabaseBuilder: NewDefaultDatabaseBuilder(c, ltndLog),
|
||||||
|
WalletConfigBuilder: defaultImpl,
|
||||||
ChainControlBuilder: defaultImpl,
|
ChainControlBuilder: defaultImpl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,15 +86,24 @@ type DatabaseBuilder interface {
|
||||||
BuildDatabase(ctx context.Context) (*DatabaseInstances, func(), error)
|
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
|
// ChainControlBuilder is an interface that must be satisfied by a custom wallet
|
||||||
// implementation.
|
// implementation.
|
||||||
type ChainControlBuilder interface {
|
type ChainControlBuilder interface {
|
||||||
// BuildChainControl is responsible for creating or unlocking and then
|
// BuildChainControl is responsible for creating a fully populated chain
|
||||||
// fully initializing a wallet and returning it as part of a fully
|
// control instance from a wallet.
|
||||||
// populated chain control instance.
|
BuildChainControl(*chainreg.PartialChainControl,
|
||||||
BuildChainControl(context.Context, *DatabaseInstances,
|
*btcwallet.Config) (*chainreg.ChainControl, func(), error)
|
||||||
*rpcperms.InterceptorChain,
|
|
||||||
[]*ListenerWithSignal) (*chainreg.ChainControl, func(), error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImplementationCfg is a struct that holds all configuration items for
|
// ImplementationCfg is a struct that holds all configuration items for
|
||||||
|
@ -116,6 +125,10 @@ type ImplementationCfg struct {
|
||||||
// backend instances.
|
// backend instances.
|
||||||
DatabaseBuilder
|
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
|
// ChainControlBuilder is a type that can provide a custom wallet
|
||||||
// implementation.
|
// implementation.
|
||||||
ChainControlBuilder
|
ChainControlBuilder
|
||||||
|
@ -195,15 +208,14 @@ func (d *DefaultWalletImpl) Permissions() map[string][]bakery.Op {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildChainControl is responsible for creating or unlocking and then fully
|
// BuildWalletConfig is responsible for creating or unlocking and then
|
||||||
// initializing a wallet and returning it as part of a fully populated chain
|
// fully initializing a wallet.
|
||||||
// control instance.
|
|
||||||
//
|
//
|
||||||
// NOTE: This is part of the ChainControlBuilder interface.
|
// NOTE: This is part of the WalletConfigBuilder interface.
|
||||||
func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
|
||||||
dbs *DatabaseInstances, interceptorChain *rpcperms.InterceptorChain,
|
dbs *DatabaseInstances, interceptorChain *rpcperms.InterceptorChain,
|
||||||
grpcListeners []*ListenerWithSignal) (*chainreg.ChainControl, func(),
|
grpcListeners []*ListenerWithSignal) (*chainreg.PartialChainControl,
|
||||||
error) {
|
*btcwallet.Config, func(), error) {
|
||||||
|
|
||||||
// Keep track of our various cleanup functions. We use a defer function
|
// Keep track of our various cleanup functions. We use a defer function
|
||||||
// as well to not repeat ourselves with every return statement.
|
// 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 "+
|
err := fmt.Errorf("unable to initialize neutrino "+
|
||||||
"backend: %v", err)
|
"backend: %v", err)
|
||||||
d.logger.Error(err)
|
d.logger.Error(err)
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
cleanUpTasks = append(cleanUpTasks, neutrinoCleanUp)
|
cleanUpTasks = append(cleanUpTasks, neutrinoCleanUp)
|
||||||
neutrinoCS = neutrinoBackend
|
neutrinoCS = neutrinoBackend
|
||||||
|
@ -270,7 +282,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
||||||
d.pwService.SetMacaroonDB(dbs.MacaroonDB)
|
d.pwService.SetMacaroonDB(dbs.MacaroonDB)
|
||||||
walletExists, err := d.pwService.WalletExists()
|
walletExists, err := d.pwService.WalletExists()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !walletExists {
|
if !walletExists {
|
||||||
|
@ -287,9 +299,9 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
||||||
if d.cfg.WalletUnlockPasswordFile != "" && !walletExists &&
|
if d.cfg.WalletUnlockPasswordFile != "" && !walletExists &&
|
||||||
!d.cfg.WalletUnlockAllowCreate {
|
!d.cfg.WalletUnlockAllowCreate {
|
||||||
|
|
||||||
return nil, nil, fmt.Errorf("wallet unlock password file was " +
|
return nil, nil, nil, fmt.Errorf("wallet unlock password file " +
|
||||||
"specified but wallet does not exist; initialize the " +
|
"was specified but wallet does not exist; initialize " +
|
||||||
"wallet before using auto unlocking")
|
"the wallet before using auto unlocking")
|
||||||
}
|
}
|
||||||
|
|
||||||
// What wallet mode are we running in? We've already made sure the no
|
// 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")
|
"password provided in file")
|
||||||
pwBytes, err := ioutil.ReadFile(d.cfg.WalletUnlockPasswordFile)
|
pwBytes, err := ioutil.ReadFile(d.cfg.WalletUnlockPasswordFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("error reading password "+
|
return nil, nil, nil, fmt.Errorf("error reading "+
|
||||||
"from file %s: %v",
|
"password from file %s: %v",
|
||||||
d.cfg.WalletUnlockPasswordFile, err)
|
d.cfg.WalletUnlockPasswordFile, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,8 +334,8 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
||||||
pwBytes, 0,
|
pwBytes, 0,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("error unlocking wallet "+
|
return nil, nil, nil, fmt.Errorf("error unlocking "+
|
||||||
"with password from file: %v", err)
|
"wallet with password from file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanUpTasks = append(cleanUpTasks, func() {
|
cleanUpTasks = append(cleanUpTasks, func() {
|
||||||
|
@ -343,7 +355,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
||||||
// over RPC.
|
// over RPC.
|
||||||
default:
|
default:
|
||||||
if err := d.interceptor.Notifier.NotifyReady(false); err != nil {
|
if err := d.interceptor.Notifier.NotifyReady(false); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
params, err := waitForWalletPassword(
|
params, err := waitForWalletPassword(
|
||||||
|
@ -354,7 +366,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
||||||
err := fmt.Errorf("unable to set up wallet password "+
|
err := fmt.Errorf("unable to set up wallet password "+
|
||||||
"listeners: %v", err)
|
"listeners: %v", err)
|
||||||
d.logger.Error(err)
|
d.logger.Error(err)
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
walletInitParams = *params
|
walletInitParams = *params
|
||||||
|
@ -386,7 +398,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
||||||
err := fmt.Errorf("unable to set up macaroon "+
|
err := fmt.Errorf("unable to set up macaroon "+
|
||||||
"authentication: %v", err)
|
"authentication: %v", err)
|
||||||
d.logger.Error(err)
|
d.logger.Error(err)
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
cleanUpTasks = append(cleanUpTasks, func() {
|
cleanUpTasks = append(cleanUpTasks, func() {
|
||||||
if err := macaroonService.Close(); err != nil {
|
if err := macaroonService.Close(); err != nil {
|
||||||
|
@ -402,7 +414,7 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
||||||
if err != nil && err != macaroons.ErrAlreadyUnlocked {
|
if err != nil && err != macaroons.ErrAlreadyUnlocked {
|
||||||
err := fmt.Errorf("unable to unlock macaroons: %v", err)
|
err := fmt.Errorf("unable to unlock macaroons: %v", err)
|
||||||
d.logger.Error(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
|
// 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(),
|
ctx, macaroonService, adminPermissions(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// The channel is buffered by one element so writing
|
// 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 "+
|
err := fmt.Errorf("unable to create macaroons "+
|
||||||
"%v", err)
|
"%v", err)
|
||||||
d.logger.Error(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 := fmt.Errorf("unable to create partial chain control: %v",
|
||||||
err)
|
err)
|
||||||
d.logger.Error(err)
|
d.logger.Error(err)
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
walletConfig := &btcwallet.Config{
|
walletConfig := &btcwallet.Config{
|
||||||
|
@ -562,23 +574,60 @@ func (d *DefaultWalletImpl) BuildChainControl(ctx context.Context,
|
||||||
walletConfig.CoinSelectionStrategy = wallet.CoinSelectionRandom
|
walletConfig.CoinSelectionStrategy = wallet.CoinSelectionRandom
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("unknown coin selection strategy "+
|
return nil, nil, nil, fmt.Errorf("unknown coin selection "+
|
||||||
"%v", d.cfg.CoinSelectionStrategy)
|
"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
|
// We've created the wallet configuration now, so we can finish
|
||||||
// initializing the main chain control.
|
// initializing the main chain control.
|
||||||
activeChainControl, ccCleanup, err := chainreg.NewChainControl(
|
activeChainControl, cleanUp, err := chainreg.NewChainControl(
|
||||||
walletConfig, partialChainControl,
|
lnWalletConfig, walletController, partialChainControl,
|
||||||
)
|
)
|
||||||
cleanUpTasks = append(cleanUpTasks, ccCleanup)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("unable to create chain control: %v", err)
|
err := fmt.Errorf("unable to create chain control: %v", err)
|
||||||
d.logger.Error(err)
|
d.logger.Error(err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
earlyExit = false
|
|
||||||
return activeChainControl, cleanUp, nil
|
return activeChainControl, cleanUp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
lnd.go
11
lnd.go
|
@ -361,9 +361,18 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg,
|
||||||
|
|
||||||
defer cleanUp()
|
defer cleanUp()
|
||||||
|
|
||||||
activeChainControl, cleanUp, err := implCfg.BuildChainControl(
|
partialChainControl, walletConfig, cleanUp, err := implCfg.BuildWalletConfig(
|
||||||
ctx, dbs, interceptorChain, grpcListeners,
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("error loading chain control: %v", err)
|
return fmt.Errorf("error loading chain control: %v", err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue