Skip to content
This repository was archived by the owner on Jun 1, 2025. It is now read-only.

Commit 83f0fd4

Browse files
ziggie1984adrienlacombe
authored andcommitted
remember state of the wallet when restarting lss
1 parent aadaea5 commit 83f0fd4

File tree

8 files changed

+485
-15
lines changed

8 files changed

+485
-15
lines changed

bus/chain.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ func (b *Bus) GetBestBlockHash() (*chainhash.Hash, error) {
1212
return b.mainClient.GetBestBlockHash()
1313
}
1414

15+
func (b *Bus) GetBlockCount() (int64, error) {
16+
return b.mainClient.GetBlockCount()
17+
18+
}
19+
1520
func (b *Bus) GetBlockHash(height int64) (*chainhash.Hash, error) {
1621
return b.mainClient.GetBlockHash(height)
1722
}

bus/infrastructure.go

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@ import (
55
"encoding/json"
66
"fmt"
77
"os"
8+
"strconv"
89
"strings"
10+
"time"
911

1012
"github.com/btcsuite/btcd/chaincfg"
1113

1214
"github.com/btcsuite/btcd/btcjson"
1315
"github.com/btcsuite/btcd/chaincfg/chainhash"
1416
"github.com/btcsuite/btcd/rpcclient"
17+
"github.com/ledgerhq/satstack/config"
1518
"github.com/ledgerhq/satstack/utils"
19+
"github.com/ledgerhq/satstack/version"
1620
"github.com/patrickmn/go-cache"
1721
log "github.com/sirupsen/logrus"
1822
)
@@ -43,6 +47,12 @@ const (
4347
errWalletAlreadyLoadedMsgNew = "Wallet file verification failed. SQLiteDatabase: Unable to obtain an exclusive lock on the database"
4448
)
4549

50+
var (
51+
// A new wallet needs to import the descriptors therefore
52+
// we need this information when starting the import worker
53+
isNewWallet bool
54+
)
55+
4656
// Bus represents a transport allowing access to Bitcoin RPC methods.
4757
//
4858
// It maintains a pool of btcd rpcclient objects in a buffered channel to allow
@@ -75,8 +85,8 @@ type Bus struct {
7585
Params *chaincfg.Params
7686

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

161-
isNewWallet, err := loadOrCreateWallet(mainClient)
171+
isNewWallet, err = loadOrCreateWallet(mainClient)
162172
if err != nil {
163173
return nil, err
164174
}
@@ -456,3 +466,32 @@ func (b *Bus) UnloadWallet() {
456466

457467
b.janitorClient.Shutdown()
458468
}
469+
470+
func (b *Bus) DumpLatestRescanTime() error {
471+
472+
currentHeight, err := b.GetBlockCount()
473+
474+
if err != nil {
475+
log.WithFields(log.Fields{
476+
"prefix": "worker",
477+
}).Error("Error fetching blockheight: %s", err)
478+
return err
479+
480+
}
481+
data := &config.ConfigurationRescan{
482+
TimeStamp: strconv.Itoa(int(time.Now().Unix())),
483+
LastSyncTime: time.Now().Format(time.ANSIC),
484+
LastBlock: currentHeight,
485+
SatstackVersion: version.Version,
486+
}
487+
err = config.WriteRescanConf(data)
488+
if err != nil {
489+
log.WithFields(log.Fields{
490+
"prefix": "worker",
491+
}).Error("Error savng last timestamp to file: %s", err)
492+
return err
493+
}
494+
495+
return nil
496+
497+
}

bus/wallet.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package bus
22

33
import (
44
"encoding/json"
5+
"time"
56

67
"fmt"
78

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

51+
type RescanResult struct {
52+
StartHeight uint32 `json:"start_height"`
53+
StopHeight uint32 `json:"stop_height"`
54+
}
55+
5056
// see https://developer.bitcoin.org/reference/rpc/importdescriptors.html for specs
5157
type ImportDesciptorRequest struct {
5258
Descriptor string `json:"desc"` //(string, required) Descriptor to import.
@@ -178,3 +184,142 @@ func (b *Bus) GetTransaction(hash string) (*types.Transaction, error) {
178184

179185
return tx, nil
180186
}
187+
188+
func (b *Bus) checkWalletSyncStatus() error {
189+
190+
client, err := b.ClientFactory()
191+
if err != nil {
192+
return err
193+
}
194+
195+
defer client.Shutdown()
196+
197+
log.Debug("checkWalletSyncStatus")
198+
199+
walletInfo, err := client.GetWalletInfo()
200+
if err != nil {
201+
return err
202+
}
203+
204+
switch v := walletInfo.Scanning.Value.(type) {
205+
case btcjson.ScanProgress:
206+
log.WithFields(log.Fields{
207+
"progress": fmt.Sprintf("%.2f%%", v.Progress*100),
208+
"duration": utils.HumanizeDuration(
209+
time.Duration(v.Duration) * time.Second),
210+
}).Debug("satsstack wallet is syncing")
211+
b.IsPendingScan = true
212+
default:
213+
// Not scanning currently, or scan is complete.
214+
log.Debug("wallet is not syncing")
215+
b.IsPendingScan = false
216+
}
217+
218+
return nil
219+
}
220+
221+
// Triggers the bitcoind api to rescan the wallet, in case the wallet
222+
// satstack already existed
223+
func (b *Bus) rescanWallet(startHeight int64, endHeight int64) error {
224+
225+
client, err := b.ClientFactory()
226+
if err != nil {
227+
return err
228+
}
229+
230+
defer client.Shutdown()
231+
232+
log.WithFields(log.Fields{
233+
"prefix": "RescanWallet",
234+
}).Infof("Rescanning Wallet start_height: %d, end_height %d", startHeight, endHeight)
235+
236+
b.IsPendingScan = true
237+
238+
var params []json.RawMessage
239+
var rescanResult RescanResult
240+
241+
myIn, mErr := json.Marshal(startHeight)
242+
243+
if mErr != nil {
244+
log.Error(`mErr`, mErr)
245+
return mErr
246+
}
247+
248+
myInRaw := json.RawMessage(myIn)
249+
params = append(params, myInRaw)
250+
251+
myIn, mErr = json.Marshal(uint32(endHeight))
252+
253+
if mErr != nil {
254+
log.Error(`mErr`, mErr)
255+
return mErr
256+
}
257+
258+
myInRaw = json.RawMessage(myIn)
259+
params = append(params, myInRaw)
260+
261+
result, err := client.RawRequest("rescanblockchain", params)
262+
263+
if err != nil {
264+
log.WithFields(log.Fields{
265+
"prefix": "RescanWallet",
266+
"error": err,
267+
}).Error("Failed to Rescan Blockchain")
268+
269+
return err
270+
}
271+
272+
umerr := json.Unmarshal(result, &rescanResult)
273+
274+
if umerr != nil {
275+
log.Error(`umerr`, umerr)
276+
return umerr
277+
}
278+
279+
log.WithFields(log.Fields{
280+
"prefix": "RescanWallet",
281+
}).Infof("Rescan wallet was successful: start_height: %d, stop_height: %d", rescanResult.StartHeight, rescanResult.StopHeight)
282+
283+
b.IsPendingScan = false
284+
285+
return nil
286+
287+
}
288+
289+
func (b *Bus) AbortRescan() error {
290+
291+
var params []json.RawMessage
292+
var abortRescan bool
293+
294+
client, err := b.ClientFactory()
295+
if err != nil {
296+
return err
297+
}
298+
299+
defer client.Shutdown()
300+
301+
result, err := client.RawRequest("abortrescan", params)
302+
303+
if err != nil {
304+
log.WithFields(log.Fields{
305+
"prefix": "AbortRescan",
306+
"error": err,
307+
}).Error("Failed to abort wallet rescan")
308+
309+
return err
310+
}
311+
312+
umerr := json.Unmarshal(result, &abortRescan)
313+
314+
if umerr != nil {
315+
log.Error(`umerr`, umerr)
316+
return umerr
317+
}
318+
319+
log.WithFields(log.Fields{
320+
"prefix": "AbortRescan",
321+
}).Infof("Abort rescan successful: %t", abortRescan)
322+
323+
return nil
324+
325+
}

0 commit comments

Comments
 (0)