Skip to content

Commit

Permalink
remember state of the wallet when restarting lss
Browse files Browse the repository at this point in the history
  • Loading branch information
ziggie1984 authored and adrienlacombe committed Jan 11, 2023
1 parent aadaea5 commit 83f0fd4
Show file tree
Hide file tree
Showing 8 changed files with 485 additions and 15 deletions.
5 changes: 5 additions & 0 deletions bus/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ func (b *Bus) GetBestBlockHash() (*chainhash.Hash, error) {
return b.mainClient.GetBestBlockHash()
}

func (b *Bus) GetBlockCount() (int64, error) {
return b.mainClient.GetBlockCount()

}

func (b *Bus) GetBlockHash(height int64) (*chainhash.Hash, error) {
return b.mainClient.GetBlockHash(height)
}
Expand Down
45 changes: 42 additions & 3 deletions bus/infrastructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"time"

"github.com/btcsuite/btcd/chaincfg"

"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/rpcclient"
"github.com/ledgerhq/satstack/config"
"github.com/ledgerhq/satstack/utils"
"github.com/ledgerhq/satstack/version"
"github.com/patrickmn/go-cache"
log "github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -43,6 +47,12 @@ const (
errWalletAlreadyLoadedMsgNew = "Wallet file verification failed. SQLiteDatabase: Unable to obtain an exclusive lock on the database"
)

var (
// A new wallet needs to import the descriptors therefore
// we need this information when starting the import worker
isNewWallet bool
)

// Bus represents a transport allowing access to Bitcoin RPC methods.
//
// It maintains a pool of btcd rpcclient objects in a buffered channel to allow
Expand Down Expand Up @@ -75,8 +85,8 @@ type Bus struct {
Params *chaincfg.Params

// IsPendingScan is a boolean field to indicate if satstack is currently
// waiting for descriptors to be scanned. One such example is when satstack
// is "running the numbers".
// waiting for descriptors to be scanned or other initial operations like "running the numbers"
// before the bridge can operate correctly
//
// This value can be exported for use by other packages to avoid making
// explorer requests before satstack is able to serve them.
Expand Down Expand Up @@ -158,7 +168,7 @@ func New(host string, user string, pass string, proxy string, noTLS bool, unload
os.Exit(1)
}

isNewWallet, err := loadOrCreateWallet(mainClient)
isNewWallet, err = loadOrCreateWallet(mainClient)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -456,3 +466,32 @@ func (b *Bus) UnloadWallet() {

b.janitorClient.Shutdown()
}

func (b *Bus) DumpLatestRescanTime() error {

currentHeight, err := b.GetBlockCount()

if err != nil {
log.WithFields(log.Fields{
"prefix": "worker",
}).Error("Error fetching blockheight: %s", err)
return err

}
data := &config.ConfigurationRescan{
TimeStamp: strconv.Itoa(int(time.Now().Unix())),
LastSyncTime: time.Now().Format(time.ANSIC),
LastBlock: currentHeight,
SatstackVersion: version.Version,
}
err = config.WriteRescanConf(data)
if err != nil {
log.WithFields(log.Fields{
"prefix": "worker",
}).Error("Error savng last timestamp to file: %s", err)
return err
}

return nil

}
145 changes: 145 additions & 0 deletions bus/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bus

import (
"encoding/json"
"time"

"fmt"

Expand Down Expand Up @@ -47,6 +48,11 @@ func (b *Bus) GetTransactionHex(hash *chainhash.Hash) (string, error) {
return tx.Hex, nil
}

type RescanResult struct {
StartHeight uint32 `json:"start_height"`
StopHeight uint32 `json:"stop_height"`
}

// see https://developer.bitcoin.org/reference/rpc/importdescriptors.html for specs
type ImportDesciptorRequest struct {
Descriptor string `json:"desc"` //(string, required) Descriptor to import.
Expand Down Expand Up @@ -178,3 +184,142 @@ func (b *Bus) GetTransaction(hash string) (*types.Transaction, error) {

return tx, nil
}

func (b *Bus) checkWalletSyncStatus() error {

client, err := b.ClientFactory()
if err != nil {
return err
}

defer client.Shutdown()

log.Debug("checkWalletSyncStatus")

walletInfo, err := client.GetWalletInfo()
if err != nil {
return err
}

switch v := walletInfo.Scanning.Value.(type) {
case btcjson.ScanProgress:
log.WithFields(log.Fields{
"progress": fmt.Sprintf("%.2f%%", v.Progress*100),
"duration": utils.HumanizeDuration(
time.Duration(v.Duration) * time.Second),
}).Debug("satsstack wallet is syncing")
b.IsPendingScan = true
default:
// Not scanning currently, or scan is complete.
log.Debug("wallet is not syncing")
b.IsPendingScan = false
}

return nil
}

// Triggers the bitcoind api to rescan the wallet, in case the wallet
// satstack already existed
func (b *Bus) rescanWallet(startHeight int64, endHeight int64) error {

client, err := b.ClientFactory()
if err != nil {
return err
}

defer client.Shutdown()

log.WithFields(log.Fields{
"prefix": "RescanWallet",
}).Infof("Rescanning Wallet start_height: %d, end_height %d", startHeight, endHeight)

b.IsPendingScan = true

var params []json.RawMessage
var rescanResult RescanResult

myIn, mErr := json.Marshal(startHeight)

if mErr != nil {
log.Error(`mErr`, mErr)
return mErr
}

myInRaw := json.RawMessage(myIn)
params = append(params, myInRaw)

myIn, mErr = json.Marshal(uint32(endHeight))

if mErr != nil {
log.Error(`mErr`, mErr)
return mErr
}

myInRaw = json.RawMessage(myIn)
params = append(params, myInRaw)

result, err := client.RawRequest("rescanblockchain", params)

if err != nil {
log.WithFields(log.Fields{
"prefix": "RescanWallet",
"error": err,
}).Error("Failed to Rescan Blockchain")

return err
}

umerr := json.Unmarshal(result, &rescanResult)

if umerr != nil {
log.Error(`umerr`, umerr)
return umerr
}

log.WithFields(log.Fields{
"prefix": "RescanWallet",
}).Infof("Rescan wallet was successful: start_height: %d, stop_height: %d", rescanResult.StartHeight, rescanResult.StopHeight)

b.IsPendingScan = false

return nil

}

func (b *Bus) AbortRescan() error {

var params []json.RawMessage
var abortRescan bool

client, err := b.ClientFactory()
if err != nil {
return err
}

defer client.Shutdown()

result, err := client.RawRequest("abortrescan", params)

if err != nil {
log.WithFields(log.Fields{
"prefix": "AbortRescan",
"error": err,
}).Error("Failed to abort wallet rescan")

return err
}

umerr := json.Unmarshal(result, &abortRescan)

if umerr != nil {
log.Error(`umerr`, umerr)
return umerr
}

log.WithFields(log.Fields{
"prefix": "AbortRescan",
}).Infof("Abort rescan successful: %t", abortRescan)

return nil

}
Loading

0 comments on commit 83f0fd4

Please sign in to comment.