mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-05-04 08:50:20 +02:00
lnd: shutdown wallet unlocker after macaroon creation
Because we'll need to return the macaroon through the wallet unlocker we cannot shut down its service before we have done so, otherwise we'll end up in a deadlock. That's why we collect all shutdown tasks and return them as a function that can be called after we've initialized the macaroon service.
This commit is contained in:
parent
71ba2a8e60
commit
b685a97fcd
67
lnd.go
67
lnd.go
@ -318,6 +318,7 @@ func Main(cfg *Config, lisCfg ListenerCfg, shutdownChan <-chan struct{}) error {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
walletInitParams WalletUnlockParams
|
walletInitParams WalletUnlockParams
|
||||||
|
shutdownUnlocker = func() {}
|
||||||
privateWalletPw = lnwallet.DefaultPrivatePassphrase
|
privateWalletPw = lnwallet.DefaultPrivatePassphrase
|
||||||
publicWalletPw = lnwallet.DefaultPublicPassphrase
|
publicWalletPw = lnwallet.DefaultPublicPassphrase
|
||||||
)
|
)
|
||||||
@ -377,7 +378,7 @@ func Main(cfg *Config, lisCfg ListenerCfg, shutdownChan <-chan struct{}) error {
|
|||||||
// started with the --noseedbackup flag, we use the default password
|
// started with the --noseedbackup flag, we use the default password
|
||||||
// for wallet encryption.
|
// for wallet encryption.
|
||||||
if !cfg.NoSeedBackup {
|
if !cfg.NoSeedBackup {
|
||||||
params, err := waitForWalletPassword(
|
params, shutdown, err := waitForWalletPassword(
|
||||||
cfg, cfg.RESTListeners, serverOpts, restDialOpts,
|
cfg, cfg.RESTListeners, serverOpts, restDialOpts,
|
||||||
restProxyDest, tlsCfg, walletUnlockerListeners,
|
restProxyDest, tlsCfg, walletUnlockerListeners,
|
||||||
)
|
)
|
||||||
@ -389,6 +390,7 @@ func Main(cfg *Config, lisCfg ListenerCfg, shutdownChan <-chan struct{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
walletInitParams = *params
|
walletInitParams = *params
|
||||||
|
shutdownUnlocker = shutdown
|
||||||
privateWalletPw = walletInitParams.Password
|
privateWalletPw = walletInitParams.Password
|
||||||
publicWalletPw = walletInitParams.Password
|
publicWalletPw = walletInitParams.Password
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -443,6 +445,10 @@ func Main(cfg *Config, lisCfg ListenerCfg, shutdownChan <-chan struct{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now we're definitely done with the unlocker, shut it down so we can
|
||||||
|
// start the main RPC service later.
|
||||||
|
shutdownUnlocker()
|
||||||
|
|
||||||
// With the information parsed from the configuration, create valid
|
// With the information parsed from the configuration, create valid
|
||||||
// instances of the pertinent interfaces required to operate the
|
// instances of the pertinent interfaces required to operate the
|
||||||
// Lightning Network Daemon.
|
// Lightning Network Daemon.
|
||||||
@ -1041,7 +1047,7 @@ type WalletUnlockParams struct {
|
|||||||
func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
||||||
serverOpts []grpc.ServerOption, restDialOpts []grpc.DialOption,
|
serverOpts []grpc.ServerOption, restDialOpts []grpc.DialOption,
|
||||||
restProxyDest string, tlsConf *tls.Config,
|
restProxyDest string, tlsConf *tls.Config,
|
||||||
getListeners rpcListeners) (*WalletUnlockParams, error) {
|
getListeners rpcListeners) (*WalletUnlockParams, func(), error) {
|
||||||
|
|
||||||
chainConfig := cfg.Bitcoin
|
chainConfig := cfg.Bitcoin
|
||||||
if cfg.registeredChains.PrimaryChain() == chainreg.LitecoinChain {
|
if cfg.registeredChains.PrimaryChain() == chainreg.LitecoinChain {
|
||||||
@ -1064,16 +1070,23 @@ func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
|||||||
// Set up a new PasswordService, which will listen for passwords
|
// Set up a new PasswordService, which will listen for passwords
|
||||||
// provided over RPC.
|
// provided over RPC.
|
||||||
grpcServer := grpc.NewServer(serverOpts...)
|
grpcServer := grpc.NewServer(serverOpts...)
|
||||||
defer grpcServer.GracefulStop()
|
|
||||||
lnrpc.RegisterWalletUnlockerServer(grpcServer, pwService)
|
lnrpc.RegisterWalletUnlockerServer(grpcServer, pwService)
|
||||||
|
|
||||||
|
var shutdownFuncs []func()
|
||||||
|
shutdown := func() {
|
||||||
|
for _, shutdownFn := range shutdownFuncs {
|
||||||
|
shutdownFn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
shutdownFuncs = append(shutdownFuncs, grpcServer.GracefulStop)
|
||||||
|
|
||||||
// Start a gRPC server listening for HTTP/2 connections, solely used
|
// Start a gRPC server listening for HTTP/2 connections, solely used
|
||||||
// for getting the encryption password from the client.
|
// for getting the encryption password from the client.
|
||||||
listeners, cleanup, err := getListeners()
|
listeners, cleanup, err := getListeners()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, shutdown, err
|
||||||
}
|
}
|
||||||
defer cleanup()
|
shutdownFuncs = append(shutdownFuncs, cleanup)
|
||||||
|
|
||||||
// Use a WaitGroup so we can be sure the instructions on how to input the
|
// Use a WaitGroup so we can be sure the instructions on how to input the
|
||||||
// password is the last thing to be printed to the console.
|
// password is the last thing to be printed to the console.
|
||||||
@ -1082,21 +1095,21 @@ func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
|||||||
for _, lis := range listeners {
|
for _, lis := range listeners {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(lis *ListenerWithSignal) {
|
go func(lis *ListenerWithSignal) {
|
||||||
rpcsLog.Infof("password RPC server listening on %s",
|
rpcsLog.Infof("Password RPC server listening on %s",
|
||||||
lis.Addr())
|
lis.Addr())
|
||||||
|
|
||||||
// Close the ready chan to indicate we are listening.
|
// Close the ready chan to indicate we are listening.
|
||||||
close(lis.Ready)
|
close(lis.Ready)
|
||||||
|
|
||||||
wg.Done()
|
wg.Done()
|
||||||
grpcServer.Serve(lis)
|
_ = grpcServer.Serve(lis)
|
||||||
}(lis)
|
}(lis)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a REST proxy for our gRPC server above.
|
// Start a REST proxy for our gRPC server above.
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
shutdownFuncs = append(shutdownFuncs, cancel)
|
||||||
|
|
||||||
mux := proxy.NewServeMux()
|
mux := proxy.NewServeMux()
|
||||||
|
|
||||||
@ -1104,7 +1117,7 @@ func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
|||||||
ctx, mux, restProxyDest, restDialOpts,
|
ctx, mux, restProxyDest, restDialOpts,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, shutdown, err
|
||||||
}
|
}
|
||||||
|
|
||||||
srv := &http.Server{Handler: allowCORS(mux, cfg.RestCORS)}
|
srv := &http.Server{Handler: allowCORS(mux, cfg.RestCORS)}
|
||||||
@ -1112,22 +1125,24 @@ func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
|||||||
for _, restEndpoint := range restEndpoints {
|
for _, restEndpoint := range restEndpoints {
|
||||||
lis, err := lncfg.TLSListenOnAddress(restEndpoint, tlsConf)
|
lis, err := lncfg.TLSListenOnAddress(restEndpoint, tlsConf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ltndLog.Errorf(
|
ltndLog.Errorf("Password gRPC proxy unable to listen "+
|
||||||
"password gRPC proxy unable to listen on %s",
|
"on %s", restEndpoint)
|
||||||
restEndpoint,
|
return nil, shutdown, err
|
||||||
)
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
defer lis.Close()
|
shutdownFuncs = append(shutdownFuncs, func() {
|
||||||
|
err := lis.Close()
|
||||||
|
if err != nil {
|
||||||
|
rpcsLog.Errorf("Error closing listener: %v",
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
rpcsLog.Infof(
|
rpcsLog.Infof("Password gRPC proxy started at %s",
|
||||||
"password gRPC proxy started at %s",
|
lis.Addr())
|
||||||
lis.Addr(),
|
|
||||||
)
|
|
||||||
wg.Done()
|
wg.Done()
|
||||||
srv.Serve(lis)
|
_ = srv.Serve(lis)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1158,8 +1173,8 @@ func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
|||||||
// version, then we'll return an error as we don't understand
|
// version, then we'll return an error as we don't understand
|
||||||
// this.
|
// this.
|
||||||
if cipherSeed.InternalVersion != keychain.KeyDerivationVersion {
|
if cipherSeed.InternalVersion != keychain.KeyDerivationVersion {
|
||||||
return nil, fmt.Errorf("invalid internal seed version "+
|
return nil, shutdown, fmt.Errorf("invalid internal "+
|
||||||
"%v, current version is %v",
|
"seed version %v, current version is %v",
|
||||||
cipherSeed.InternalVersion,
|
cipherSeed.InternalVersion,
|
||||||
keychain.KeyDerivationVersion)
|
keychain.KeyDerivationVersion)
|
||||||
}
|
}
|
||||||
@ -1185,7 +1200,7 @@ func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
|||||||
ltndLog.Errorf("Could not unload new "+
|
ltndLog.Errorf("Could not unload new "+
|
||||||
"wallet: %v", err)
|
"wallet: %v", err)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, shutdown, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &WalletUnlockParams{
|
return &WalletUnlockParams{
|
||||||
@ -1195,7 +1210,7 @@ func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
|||||||
Wallet: newWallet,
|
Wallet: newWallet,
|
||||||
ChansToRestore: initMsg.ChanBackups,
|
ChansToRestore: initMsg.ChanBackups,
|
||||||
UnloadWallet: loader.UnloadWallet,
|
UnloadWallet: loader.UnloadWallet,
|
||||||
}, nil
|
}, shutdown, nil
|
||||||
|
|
||||||
// The wallet has already been created in the past, and is simply being
|
// The wallet has already been created in the past, and is simply being
|
||||||
// unlocked. So we'll just return these passphrases.
|
// unlocked. So we'll just return these passphrases.
|
||||||
@ -1206,10 +1221,10 @@ func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
|||||||
Wallet: unlockMsg.Wallet,
|
Wallet: unlockMsg.Wallet,
|
||||||
ChansToRestore: unlockMsg.ChanBackups,
|
ChansToRestore: unlockMsg.ChanBackups,
|
||||||
UnloadWallet: unlockMsg.UnloadWallet,
|
UnloadWallet: unlockMsg.UnloadWallet,
|
||||||
}, nil
|
}, shutdown, nil
|
||||||
|
|
||||||
case <-signal.ShutdownChannel():
|
case <-signal.ShutdownChannel():
|
||||||
return nil, fmt.Errorf("shutting down")
|
return nil, shutdown, fmt.Errorf("shutting down")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user