@@ -8,12 +8,15 @@ import (
8
8
"strconv"
9
9
"time"
10
10
11
+ "github.com/btcsuite/btcd/btcutil"
11
12
"github.com/btcsuite/btcwallet/walletdb"
12
13
"github.com/jessevdk/go-flags"
13
14
"github.com/lightningnetwork/lnd/channeldb"
14
15
"github.com/lightningnetwork/lnd/kvdb"
15
16
"github.com/lightningnetwork/lnd/kvdb/etcd"
16
17
"github.com/lightningnetwork/lnd/kvdb/postgres"
18
+ "github.com/lightningnetwork/lnd/kvdb/sqlbase"
19
+ "github.com/lightningnetwork/lnd/kvdb/sqlite"
17
20
"github.com/lightningnetwork/lnd/lncfg"
18
21
"github.com/lightningnetwork/lnd/signal"
19
22
clientv3 "go.etcd.io/etcd/client/v3"
27
30
28
31
// etcdTimeout is the time we allow a single etcd transaction to take.
29
32
etcdTimeout = time .Second * 5
33
+
34
+ // defaultDataDir is the default data directory for lnd.
35
+ defaultDataDir = btcutil .AppDataDir ("lnd" , false )
30
36
)
31
37
32
38
const (
@@ -40,28 +46,51 @@ type Bolt struct {
40
46
DBTimeout time.Duration `long:"dbtimeout" description:"Specify the timeout value used when opening the database."`
41
47
DataDir string `long:"data-dir" description:"Lnd data dir where bolt dbs are located."`
42
48
TowerDir string `long:"tower-dir" description:"Lnd watchtower dir where bolt dbs for the watchtower server are located."`
43
- Network string `long:"network" description:"Network within data dir where bolt dbs are located."`
49
+ }
50
+
51
+ type Sqlite struct {
52
+ DataDir string `long:"data-dir" description:"Lnd data dir where sqlite dbs are located."`
53
+ TowerDir string `long:"tower-dir" description:"Lnd watchtower dir where sqlite dbs for the watchtower server are located."`
54
+ Config * sqlite.Config `group:"sqlite-config" namespace:"sqlite-config" description:"Sqlite config."`
44
55
}
45
56
46
57
type DB struct {
47
58
Backend string `long:"backend" description:"The selected database backend."`
48
59
Etcd * etcd.Config `group:"etcd" namespace:"etcd" description:"Etcd settings."`
49
60
Bolt * Bolt `group:"bolt" namespace:"bolt" description:"Bolt settings."`
50
61
Postgres * postgres.Config `group:"postgres" namespace:"postgres" description:"Postgres settings."`
62
+ Sqlite * Sqlite `group:"sqlite" namespace:"sqlite" description:"Sqlite settings."`
63
+ }
64
+
65
+ // Init should be called upon start to pre-initialize database for sql
66
+ // backends. If max connections are not set, the amount of connections will be
67
+ // unlimited however we only use one connection during the migration.
68
+ func (db * DB ) Init () error {
69
+ // Start embedded etcd server if requested.
70
+ switch {
71
+ case db .Backend == lncfg .PostgresBackend :
72
+ sqlbase .Init (db .Postgres .MaxConnections )
73
+
74
+ case db .Backend == lncfg .SqliteBackend :
75
+ sqlbase .Init (db .Sqlite .Config .MaxConnections )
76
+ }
77
+
78
+ return nil
51
79
}
52
80
53
- func ( d * DB ) isRemote () bool {
54
- return d . Backend == lncfg . EtcdBackend ||
55
- d .Backend == lncfg .PostgresBackend
81
+ // isBoltDB returns true if the db is a type bolt db.
82
+ func ( db * DB ) isBoltDB () bool {
83
+ return db .Backend == lncfg .BoltBackend
56
84
}
57
85
58
- func (d * DB ) isEtcd () bool {
59
- return d .Backend == lncfg .EtcdBackend
86
+ func (db * DB ) isEtcd () bool {
87
+ return db .Backend == lncfg .EtcdBackend
60
88
}
61
89
62
90
type migrateDBCommand struct {
63
- Source * DB `group:"source" namespace:"source" long:"source" short:"s" description:"The source database where the data is read from"`
64
- Dest * DB `group:"dest" namespace:"dest" long:"dest" short:"d" description:"The destination database where the data is written to"`
91
+ Source * DB `group:"source" namespace:"source" long:"source" short:"s" description:"The source database where the data is read from"`
92
+ Dest * DB `group:"dest" namespace:"dest" long:"dest" short:"d" description:"The destination database where the data is written to"`
93
+ Network string `long:"network" short:"n" description:"Network of the db files to migrate (used to navigate into the right directory)"`
65
94
}
66
95
67
96
func newMigrateDBCommand () * migrateDBCommand {
@@ -71,9 +100,15 @@ func newMigrateDBCommand() *migrateDBCommand {
71
100
Etcd : & etcd.Config {},
72
101
Bolt : & Bolt {
73
102
DBTimeout : kvdb .DefaultDBTimeout ,
74
- Network : "mainnet" ,
103
+ TowerDir : defaultDataDir ,
104
+ DataDir : defaultDataDir ,
75
105
},
76
106
Postgres : & postgres.Config {},
107
+ Sqlite : & Sqlite {
108
+ Config : & sqlite.Config {},
109
+ TowerDir : defaultDataDir ,
110
+ DataDir : defaultDataDir ,
111
+ },
77
112
},
78
113
Dest : & DB {
79
114
Backend : lncfg .EtcdBackend ,
@@ -82,10 +117,17 @@ func newMigrateDBCommand() *migrateDBCommand {
82
117
},
83
118
Bolt : & Bolt {
84
119
DBTimeout : kvdb .DefaultDBTimeout ,
85
- Network : "mainnet" ,
120
+ TowerDir : defaultDataDir ,
121
+ DataDir : defaultDataDir ,
86
122
},
87
123
Postgres : & postgres.Config {},
124
+ Sqlite : & Sqlite {
125
+ Config : & sqlite.Config {},
126
+ TowerDir : defaultDataDir ,
127
+ DataDir : defaultDataDir ,
128
+ },
88
129
},
130
+ Network : "regtest" ,
89
131
}
90
132
}
91
133
@@ -141,20 +183,21 @@ func (x *migrateDBCommand) Execute(_ []string) error {
141
183
for _ , prefix := range prefixes {
142
184
log ("Migrating DB with prefix %s" , prefix )
143
185
144
- srcDb , err := openDb (x .Source , prefix )
145
- if err != nil {
146
- if err == walletdb .ErrDbDoesNotExist &&
147
- x .Source .Backend == lncfg .BoltBackend {
186
+ srcDb , err := openDb (x .Source , prefix , x .Network )
148
187
149
- log ("Skipping DB with prefix %s because " +
150
- "source does not exist" , prefix )
151
- continue
152
- }
153
- return err
188
+ // This is only for now done for bolt dbs because other backends
189
+ // do not special case this error for now. For example if
190
+ // we do not run the watcher tower functionaliy we might not
191
+ // have a towerclient.db so we skip this error.
192
+ if err == walletdb .ErrDbDoesNotExist &&
193
+ x .Source .Backend == lncfg .BoltBackend {
194
+
195
+ log ("Skipping DB with prefix %s because " +
196
+ "source does not exist" , prefix )
197
+ continue
154
198
}
155
- log ("Opened source DB" )
156
199
157
- destDb , err := openDb (x .Dest , prefix )
200
+ destDb , err := openDb (x .Dest , prefix , x . Network )
158
201
if err != nil {
159
202
return err
160
203
}
@@ -183,11 +226,15 @@ func (x *migrateDBCommand) Execute(_ []string) error {
183
226
// to the channel DB as that is the only DB that has migrations.
184
227
log ("Checking DB version of source DB" )
185
228
if prefix == lncfg .NSChannelDB {
186
- if err := checkMigrationsApplied (srcDb ); err != nil {
229
+ err := checkChannelDBMigrationsApplied (srcDb )
230
+ if err != nil {
187
231
return err
188
232
}
189
233
}
190
234
235
+ // TODO(ziggie): Also check other DBs for migrations like the
236
+ // wtclient.db as soon as LND 19 is tagged.
237
+
191
238
// Also make sure that the destination DB hasn't been marked as
192
239
// successfully having been the target of a migration. We only
193
240
// mark a destination DB as successfully migrated at the end of
@@ -242,6 +289,9 @@ func (x *migrateDBCommand) Execute(_ []string) error {
242
289
if err := addMarker (destDb , alreadyMigratedKey ); err != nil {
243
290
return err
244
291
}
292
+
293
+ log ("Migration of DB with prefix %s completed successfully" ,
294
+ prefix )
245
295
}
246
296
247
297
return nil
@@ -286,7 +336,9 @@ func (x *migrateDBCommand) migrateKvdb(srcTx walletdb.ReadWriteTx,
286
336
}
287
337
288
338
// Migrate wallet created marker.
289
- if prefix == lncfg .NSWalletDB && x .Dest .isRemote () {
339
+ //
340
+ // TODO(ziggie): Why not for bbolt backends ?
341
+ if prefix == lncfg .NSWalletDB && ! x .Dest .isBoltDB () {
290
342
const (
291
343
walletMetaBucket = "lnwallet"
292
344
walletReadyKey = "ready"
@@ -382,21 +434,30 @@ func (x *migrateDBCommand) migrateEtcd(srcTx walletdb.ReadWriteTx,
382
434
return nil
383
435
}
384
436
385
- func openDb (cfg * DB , prefix string ) (walletdb.DB , error ) {
437
+ func openDb (cfg * DB , prefix , network string ) (walletdb.DB , error ) {
386
438
backend := cfg .Backend
387
439
388
- var args []interface {}
440
+ // Init the db connections for sql backends.
441
+ err := cfg .Init ()
442
+ if err != nil {
443
+ return nil , err
444
+ }
389
445
390
- graphDir := filepath .Join (cfg .Bolt .DataDir , "graph" , cfg .Bolt .Network )
391
- walletDir := filepath .Join (
392
- cfg .Bolt .DataDir , "chain" , "bitcoin" , cfg .Bolt .Network ,
393
- )
394
- towerServerDir := filepath .Join (
395
- cfg .Bolt .TowerDir , "bitcoin" , cfg .Bolt .Network ,
396
- )
446
+ // Settings to open a particular db backend.
447
+ var args []interface {}
397
448
398
449
switch backend {
399
450
case lncfg .BoltBackend :
451
+ // Directories where the db files are located.
452
+ graphDir := filepath .Join (cfg .Bolt .DataDir , "graph" , network )
453
+ walletDir := filepath .Join (
454
+ cfg .Bolt .DataDir , "chain" , "bitcoin" , network ,
455
+ )
456
+ towerServerDir := filepath .Join (
457
+ cfg .Bolt .TowerDir , "bitcoin" , network ,
458
+ )
459
+
460
+ // Path to the db file.
400
461
var path string
401
462
switch prefix {
402
463
case lncfg .NSChannelDB :
@@ -443,13 +504,68 @@ func openDb(cfg *DB, prefix string) (walletdb.DB, error) {
443
504
args = []interface {}{
444
505
context .Background (),
445
506
& postgres.Config {
446
- Dsn : cfg .Postgres .Dsn ,
507
+ Dsn : cfg .Postgres .Dsn ,
508
+ Timeout : time .Minute ,
509
+ MaxConnections : 10 ,
447
510
},
448
511
prefix ,
449
512
}
513
+
450
514
log ("Opening postgres backend at %s with prefix '%s'" ,
451
515
cfg .Postgres .Dsn , prefix )
452
516
517
+ case kvdb .SqliteBackendName :
518
+ // Directories where the db files are located.
519
+ graphDir := filepath .Join (cfg .Sqlite .DataDir , "graph" , network )
520
+ walletDir := filepath .Join (
521
+ cfg .Sqlite .DataDir , "chain" , "bitcoin" , network ,
522
+ )
523
+ towerServerDir := filepath .Join (
524
+ cfg .Sqlite .TowerDir , "bitcoin" , network ,
525
+ )
526
+
527
+ var dbName string
528
+ var path string
529
+ switch prefix {
530
+ case lncfg .NSChannelDB :
531
+ path = graphDir
532
+ dbName = lncfg .SqliteChannelDBName
533
+ case lncfg .NSMacaroonDB :
534
+ path = walletDir
535
+ dbName = lncfg .SqliteChainDBName
536
+
537
+ case lncfg .NSDecayedLogDB :
538
+ path = graphDir
539
+ dbName = lncfg .SqliteChannelDBName
540
+
541
+ case lncfg .NSTowerClientDB :
542
+ path = graphDir
543
+ dbName = lncfg .SqliteChannelDBName
544
+
545
+ case lncfg .NSTowerServerDB :
546
+ path = towerServerDir
547
+ dbName = lncfg .SqliteChannelDBName
548
+
549
+ case lncfg .NSWalletDB :
550
+ path = walletDir
551
+ dbName = lncfg .SqliteChainDBName
552
+
553
+ case lncfg .NSNeutrinoDB :
554
+ dbName = lncfg .SqliteNeutrinoDBName
555
+ }
556
+
557
+ args = []interface {}{
558
+ context .Background (),
559
+ & sqlite.Config {
560
+ Timeout : time .Minute ,
561
+ },
562
+ path ,
563
+ dbName ,
564
+ prefix ,
565
+ }
566
+
567
+ log ("Opening sqlite backend with prefix '%s'" , prefix )
568
+
453
569
default :
454
570
return nil , fmt .Errorf ("unknown backend: %v" , backend )
455
571
}
@@ -548,7 +664,7 @@ func addMarker(db walletdb.DB, markerKey []byte) error {
548
664
return rwtx .Commit ()
549
665
}
550
666
551
- func checkMigrationsApplied (db walletdb.DB ) error {
667
+ func checkChannelDBMigrationsApplied (db walletdb.DB ) error {
552
668
var meta channeldb.Meta
553
669
err := kvdb .View (db , func (tx kvdb.RTx ) error {
554
670
return channeldb .FetchMeta (& meta , tx )
0 commit comments