IsInitialized > walletLoaded & panic recovery (#266)

* isInitialized update
update walletInitialized to return true is walled.db exist,
add walletLoaded that check if wallet property is nil

* panic handler
This commit is contained in:
Dusan Sekulic
2024-08-19 18:57:52 +02:00
committed by GitHub
parent 250dd7eea2
commit 07139786e6
4 changed files with 404 additions and 15 deletions

View File

@@ -68,10 +68,10 @@ const (
)
var (
ErrWalletNotInitialized = fmt.Errorf("wallet not initialized")
p2wpkhKeyScope = waddrmgr.KeyScopeBIP0084
p2trKeyScope = waddrmgr.KeyScopeBIP0086
outputLockDuration = time.Minute
ErrWalletNotLoaded = fmt.Errorf("wallet not loaded, create or unlock it first")
p2wpkhKeyScope = waddrmgr.KeyScopeBIP0084
p2trKeyScope = waddrmgr.KeyScopeBIP0086
outputLockDuration = time.Minute
)
type service struct {
@@ -222,7 +222,7 @@ func NewService(cfg WalletConfig, options ...WalletOption) (ports.WalletService,
}
func (s *service) Close() {
if s.isInitialized() {
if s.walletLoaded() {
if err := s.wallet.Stop(); err != nil {
log.WithError(err).Warn("failed to gracefully stop the wallet, forcing shutdown")
}
@@ -246,7 +246,7 @@ func (s *service) Restore(_ context.Context, seed, password string) error {
}
func (s *service) Unlock(_ context.Context, password string) error {
if !s.isInitialized() {
if !s.walletLoaded() {
pwd := []byte(password)
opt := btcwallet.LoaderWithLocalWalletDB(s.cfg.Datadir, false, time.Minute)
config := btcwallet.Config{
@@ -326,8 +326,8 @@ func (s *service) Unlock(_ context.Context, password string) error {
}
func (s *service) Lock(_ context.Context, _ string) error {
if !s.isInitialized() {
return ErrWalletNotInitialized
if !s.walletLoaded() {
return ErrWalletNotLoaded
}
s.wallet.InternalWallet().Lock()
@@ -584,8 +584,10 @@ func (s *service) SignTransactionTapscript(ctx context.Context, partialTx string
}
func (s *service) Status(ctx context.Context) (ports.WalletStatus, error) {
if !s.isInitialized() {
return status{}, nil
if !s.walletLoaded() {
return status{
initialized: s.walletInitialized(),
}, nil
}
w := s.wallet.InternalWallet()
@@ -907,8 +909,8 @@ func (s *service) initWallet(wallet *btcwallet.BtcWallet) error {
}
func (s *service) getBalance(account accountName) (uint64, error) {
if !s.isInitialized() {
return 0, ErrWalletNotInitialized
if !s.walletLoaded() {
return 0, ErrWalletNotLoaded
}
balance, err := s.wallet.ConfirmedBalance(0, string(account))
@@ -921,17 +923,31 @@ func (s *service) getBalance(account accountName) (uint64, error) {
// this only supports deriving segwit v0 accounts
func (s *service) deriveNextAddress(account accountName) (btcutil.Address, error) {
if !s.isInitialized() {
return nil, ErrWalletNotInitialized
if !s.walletLoaded() {
return nil, ErrWalletNotLoaded
}
return s.wallet.NewAddress(lnwallet.WitnessPubKey, false, string(account))
}
func (s *service) isInitialized() bool {
func (s *service) walletLoaded() bool {
return s.wallet != nil
}
func (s *service) walletInitialized() bool {
opts := []btcwallet.LoaderOption{btcwallet.LoaderWithLocalWalletDB(s.cfg.Datadir, false, time.Minute)}
loader, err := btcwallet.NewWalletLoader(
s.cfg.chainParams(), 0, opts...,
)
if err != nil {
return false
}
exist, _ := loader.WalletExists()
return exist
}
func withChainSource(chainSource chain.Interface) WalletOption {
return func(s *service) error {
if s.chainSource != nil {

View File

@@ -9,6 +9,7 @@ import (
// UnaryInterceptor returns the unary interceptor
func UnaryInterceptor(svc *macaroons.Service) grpc.ServerOption {
return grpc.UnaryInterceptor(middleware.ChainUnaryServer(
unaryPanicRecoveryInterceptor(),
unaryLogger,
unaryMacaroonAuthHandler(svc),
))
@@ -17,6 +18,7 @@ func UnaryInterceptor(svc *macaroons.Service) grpc.ServerOption {
// StreamInterceptor returns the stream interceptor with a logrus log
func StreamInterceptor(svc *macaroons.Service) grpc.ServerOption {
return grpc.StreamInterceptor(middleware.ChainStreamServer(
streamPanicRecoveryInterceptor(),
streamLogger,
streamMacaroonAuthHandler(svc),
))

View File

@@ -0,0 +1,45 @@
package interceptors
import (
"context"
"runtime/debug"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
)
func unaryPanicRecoveryInterceptor() grpc.UnaryServerInterceptor {
return func(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (interface{}, error) {
defer func() {
if r := recover(); r != nil {
log.Errorf("panic-recovery middleware recovered from panic: %v", r)
log.Tracef("panic-recovery middleware recovered from panic: %v", string(debug.Stack()))
}
}()
return handler(ctx, req)
}
}
func streamPanicRecoveryInterceptor() grpc.StreamServerInterceptor {
return func(
srv interface{},
stream grpc.ServerStream,
info *grpc.StreamServerInfo,
handler grpc.StreamHandler,
) error {
defer func() {
if r := recover(); r != nil {
log.Errorf("panic-recovery middleware recovered from panic: %v", r)
log.Tracef("panic-recovery middleware recovered from panic: %v", string(debug.Stack()))
}
}()
return handler(srv, stream)
}
}