1
1
package accounts
2
2
3
3
import (
4
+ "bytes"
4
5
"context"
5
6
"database/sql"
6
7
"errors"
@@ -11,6 +12,7 @@ import (
11
12
12
13
"github.com/davecgh/go-spew/spew"
13
14
"github.com/lightninglabs/lightning-terminal/db/sqlc"
15
+ "github.com/lightningnetwork/lnd/kvdb"
14
16
"github.com/pmezard/go-difflib/difflib"
15
17
)
16
18
24
26
// MigrateAccountStoreToSQL runs the migration of all accounts and indices from
25
27
// the KV database to the SQL database. The migration is done in a single
26
28
// 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 ,
28
30
tx SQLQueries ) error {
29
31
30
32
log .Infof ("Starting migration of the KV accounts store to SQL" )
@@ -47,12 +49,12 @@ func MigrateAccountStoreToSQL(ctx context.Context, kvStore *BoltStore,
47
49
// migrateAccountsToSQL runs the migration of all accounts from the KV database
48
50
// to the SQL database. The migration is done in a single transaction to ensure
49
51
// 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 ,
51
53
tx SQLQueries ) error {
52
54
53
55
log .Infof ("Starting migration of accounts from KV to SQL" )
54
56
55
- kvAccounts , err := kvStore . Accounts ( ctx )
57
+ kvAccounts , err := getBBoltAccounts ( kvStore )
56
58
if err != nil {
57
59
return err
58
60
}
@@ -104,6 +106,51 @@ func migrateAccountsToSQL(ctx context.Context, kvStore *BoltStore,
104
106
return nil
105
107
}
106
108
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
+
107
154
// migrateSingleAccountToSQL runs the migration for a single account from the
108
155
// KV database to the SQL database.
109
156
func migrateSingleAccountToSQL (ctx context.Context ,
@@ -163,12 +210,12 @@ func migrateSingleAccountToSQL(ctx context.Context,
163
210
164
211
// migrateAccountsIndicesToSQL runs the migration for the account indices from
165
212
// the KV database to the SQL database.
166
- func migrateAccountsIndicesToSQL (ctx context.Context , kvStore * BoltStore ,
213
+ func migrateAccountsIndicesToSQL (ctx context.Context , kvStore kvdb. Backend ,
167
214
tx SQLQueries ) error {
168
215
169
216
log .Infof ("Starting migration of accounts indices from KV to SQL" )
170
217
171
- addIndex , settleIndex , err := kvStore . LastIndexes ( ctx )
218
+ addIndex , settleIndex , err := getBBoltIndices ( kvStore )
172
219
if errors .Is (err , ErrNoInvoiceIndexKnown ) {
173
220
log .Infof ("No indices found in KV store, skipping migration" )
174
221
return nil
@@ -211,6 +258,40 @@ func migrateAccountsIndicesToSQL(ctx context.Context, kvStore *BoltStore,
211
258
return nil
212
259
}
213
260
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
+
214
295
// overrideAccountTimeZone overrides the time zone of the account to the local
215
296
// time zone and chops off the nanosecond part for comparison. This is needed
216
297
// because KV database stores times as-is which as an unwanted side effect would
0 commit comments