11package accounts
22
33import (
4+ "bytes"
45 "context"
56 "database/sql"
67 "errors"
@@ -11,6 +12,7 @@ import (
1112
1213 "github.com/davecgh/go-spew/spew"
1314 "github.com/lightninglabs/lightning-terminal/db/sqlc"
15+ "github.com/lightningnetwork/lnd/kvdb"
1416 "github.com/pmezard/go-difflib/difflib"
1517)
1618
2426// MigrateAccountStoreToSQL runs the migration of all accounts and indices from
2527// the KV database to the SQL database. The migration is done in a single
2628// transaction to ensure that all accounts are migrated or none at all.
27- func MigrateAccountStoreToSQL (ctx context.Context , kvStore * BoltStore ,
29+ func MigrateAccountStoreToSQL (ctx context.Context , kvStore kvdb. Backend ,
2830 tx SQLQueries ) error {
2931
3032 log .Infof ("Starting migration of the KV accounts store to SQL" )
@@ -47,12 +49,12 @@ func MigrateAccountStoreToSQL(ctx context.Context, kvStore *BoltStore,
4749// migrateAccountsToSQL runs the migration of all accounts from the KV database
4850// to the SQL database. The migration is done in a single transaction to ensure
4951// that all accounts are migrated or none at all.
50- func migrateAccountsToSQL (ctx context.Context , kvStore * BoltStore ,
52+ func migrateAccountsToSQL (ctx context.Context , kvStore kvdb. Backend ,
5153 tx SQLQueries ) error {
5254
5355 log .Infof ("Starting migration of accounts from KV to SQL" )
5456
55- kvAccounts , err := kvStore . Accounts ( ctx )
57+ kvAccounts , err := getBBoltAccounts ( kvStore )
5658 if err != nil {
5759 return err
5860 }
@@ -104,6 +106,51 @@ func migrateAccountsToSQL(ctx context.Context, kvStore *BoltStore,
104106 return nil
105107}
106108
109+ // getBBoltAccounts is a helper function that fetches all accounts from the
110+ // Bbolt store, by iterating directly over the buckets, without needing to
111+ // use any public functions of the BoltStore struct.
112+ func getBBoltAccounts (db kvdb.Backend ) ([]* OffChainBalanceAccount , error ) {
113+ var accounts []* OffChainBalanceAccount
114+ err := db .View (func (tx kvdb.RTx ) error {
115+ // This function will be called in the ForEach and receive
116+ // the key and value of each account in the DB. The key, which
117+ // is also the ID is not used because it is also marshaled into
118+ // the value.
119+ readFn := func (k , v []byte ) error {
120+ // Skip the two special purpose keys.
121+ if bytes .Equal (k , lastAddIndexKey ) ||
122+ bytes .Equal (k , lastSettleIndexKey ) {
123+
124+ return nil
125+ }
126+
127+ // There should be no sub-buckets.
128+ if v == nil {
129+ return fmt .Errorf ("invalid bucket structure" )
130+ }
131+
132+ account , err := deserializeAccount (v )
133+ if err != nil {
134+ return err
135+ }
136+
137+ accounts = append (accounts , account )
138+ return nil
139+ }
140+
141+ // We know the bucket should exist since it's created when
142+ // the account storage is initialized.
143+ return tx .ReadBucket (accountBucketName ).ForEach (readFn )
144+ }, func () {
145+ accounts = nil
146+ })
147+ if err != nil {
148+ return nil , err
149+ }
150+
151+ return accounts , nil
152+ }
153+
107154// migrateSingleAccountToSQL runs the migration for a single account from the
108155// KV database to the SQL database.
109156func migrateSingleAccountToSQL (ctx context.Context ,
@@ -163,12 +210,12 @@ func migrateSingleAccountToSQL(ctx context.Context,
163210
164211// migrateAccountsIndicesToSQL runs the migration for the account indices from
165212// the KV database to the SQL database.
166- func migrateAccountsIndicesToSQL (ctx context.Context , kvStore * BoltStore ,
213+ func migrateAccountsIndicesToSQL (ctx context.Context , kvStore kvdb. Backend ,
167214 tx SQLQueries ) error {
168215
169216 log .Infof ("Starting migration of accounts indices from KV to SQL" )
170217
171- addIndex , settleIndex , err := kvStore . LastIndexes ( ctx )
218+ addIndex , settleIndex , err := getBBoltIndices ( kvStore )
172219 if errors .Is (err , ErrNoInvoiceIndexKnown ) {
173220 log .Infof ("No indices found in KV store, skipping migration" )
174221 return nil
@@ -211,6 +258,40 @@ func migrateAccountsIndicesToSQL(ctx context.Context, kvStore *BoltStore,
211258 return nil
212259}
213260
261+ // getBBoltIndices is a helper function that fetches the índices from the
262+ // Bbolt store, by iterating directly over the buckets, without needing to
263+ // use any public functions of the BoltStore struct.
264+ func getBBoltIndices (db kvdb.Backend ) (uint64 , uint64 , error ) {
265+ var (
266+ addValue , settleValue []byte
267+ )
268+ err := db .View (func (tx kvdb.RTx ) error {
269+ bucket := tx .ReadBucket (accountBucketName )
270+ if bucket == nil {
271+ return ErrAccountBucketNotFound
272+ }
273+
274+ addValue = bucket .Get (lastAddIndexKey )
275+ if len (addValue ) == 0 {
276+ return ErrNoInvoiceIndexKnown
277+ }
278+
279+ settleValue = bucket .Get (lastSettleIndexKey )
280+ if len (settleValue ) == 0 {
281+ return ErrNoInvoiceIndexKnown
282+ }
283+
284+ return nil
285+ }, func () {
286+ addValue , settleValue = nil , nil
287+ })
288+ if err != nil {
289+ return 0 , 0 , err
290+ }
291+
292+ return byteOrder .Uint64 (addValue ), byteOrder .Uint64 (settleValue ), nil
293+ }
294+
214295// overrideAccountTimeZone overrides the time zone of the account to the local
215296// time zone and chops off the nanosecond part for comparison. This is needed
216297// because KV database stores times as-is which as an unwanted side effect would
0 commit comments