From a7fdad557d13d7508aa9bdbed4371a135b19c87d Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Thu, 11 Jan 2024 22:35:02 +0100 Subject: [PATCH] recoverloopin: add sqlite option This commit will allow to recover loop ins that have been made with sqlite. --- cmd/chantools/recoverloopin.go | 94 +++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/cmd/chantools/recoverloopin.go b/cmd/chantools/recoverloopin.go index 8c372a9..9614f2d 100644 --- a/cmd/chantools/recoverloopin.go +++ b/cmd/chantools/recoverloopin.go @@ -2,8 +2,11 @@ package main import ( "bytes" + "context" "encoding/hex" "fmt" + "path/filepath" + "time" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" @@ -14,6 +17,7 @@ import ( "github.com/lightninglabs/loop/swap" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/spf13/cobra" ) @@ -30,7 +34,8 @@ type recoverLoopInCommand struct { APIURL string Publish bool - LoopDbDir string + LoopDbDir string + SqliteFile string rootKey *rootKey cmd *cobra.Command @@ -92,6 +97,10 @@ func newRecoverLoopInCommand() *cobra.Command { &cc.Publish, "publish", false, "publish sweep TX to the chain "+ "API instead of just printing the TX", ) + cc.cmd.Flags().StringVar( + &cc.SqliteFile, "sqlite_file", "", "optional path to the loop "+ + "sqlite database file", + ) cc.rootKey = newRootKey(cc.cmd, "deriving starting key") @@ -125,32 +134,72 @@ func (c *recoverLoopInCommand) Execute(_ *cobra.Command, _ []string) error { } api := newExplorerAPI(c.APIURL) + ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) + defer cancel() + signer := &lnd.Signer{ ExtendedKey: extendedKey, ChainParams: chainParams, } - // Try to fetch the swap from the database. - store, err := loopdb.NewBoltSwapStore(c.LoopDbDir, chainParams) - if err != nil { - return err + // Try to fetch the swap from the boltdb. + var store loopdb.SwapStore + // First check if a boltdb file exists. + if lnrpc.FileExists(filepath.Join(c.LoopDbDir, "loop.db")) { + store, err = loopdb.NewBoltSwapStore(c.LoopDbDir, chainParams) + if err != nil { + return err + } + defer store.Close() } - defer store.Close() - swaps, err := store.FetchLoopInSwaps() - if err != nil { - return err + // Now check if a backup boltdb file exists. + if lnrpc.FileExists(filepath.Join(c.LoopDbDir, "loop.db.bk")) { + store, err = loopdb.NewBoltSwapStore(c.LoopDbDir, chainParams) + if err != nil { + return err + } + defer store.Close() } + // If one of the boltdb files exists, try to fetch the loopin from + // there. var loopIn *loopdb.LoopIn - for _, s := range swaps { - if s.Hash.String() == c.SwapHash { - loopIn = s - break + if store != nil { + loopIn, err = findLoopInSwap(ctx, store, c.SwapHash) + if err != nil { + return err + } + } + + // If the loopin is not found yet, try to fetch it from the sqlite db. + if loopIn == nil { + if c.SqliteFile == "" { + c.SqliteFile = filepath.Join( + c.LoopDbDir, "loop_sqlite.db", + ) + } + + sqliteDb, err := loopdb.NewSqliteStore( + &loopdb.SqliteConfig{ + DatabaseFileName: c.SqliteFile, + SkipMigrations: true, + }, chainParams, + ) + if err != nil { + return err + } + defer sqliteDb.Close() + + loopIn, err = findLoopInSwap(ctx, sqliteDb, c.SwapHash) + if err != nil { + return err } } + + // If the loopin is still not found, return an error. if loopIn == nil { - return fmt.Errorf("swap not found") + return fmt.Errorf("loop in swap not found") } fmt.Println("Loop expires at block height", loopIn.Contract.CltvExpiry) @@ -331,6 +380,23 @@ func getSignedTx(signer *lnd.Signer, loopIn *loopdb.LoopIn, sweepTx *wire.MsgTx, return rawTx, nil } +func findLoopInSwap(ctx context.Context, store loopdb.SwapStore, + swapHash string) (*loopdb.LoopIn, error) { + + swaps, err := store.FetchLoopInSwaps(ctx) + if err != nil { + return nil, err + } + + for _, s := range swaps { + if s.Hash.String() == swapHash { + return s, nil + } + } + + return nil, nil +} + // encodeTx encodes a tx to raw bytes. func encodeTx(tx *wire.MsgTx) ([]byte, error) { var buffer bytes.Buffer