@@ -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."`
51
63
}
52
64
53
- func (d * DB ) isRemote () bool {
54
- return d .Backend == lncfg .EtcdBackend ||
55
- d .Backend == lncfg .PostgresBackend
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
56
79
}
57
80
58
- func (d * DB ) isEtcd () bool {
59
- return d .Backend == lncfg .EtcdBackend
81
+ // isBoltDB returns true if the db is a type bolt db.
82
+ func (db * DB ) isBoltDB () bool {
83
+ return db .Backend == lncfg .BoltBackend
84
+ }
85
+
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
@@ -286,7 +333,9 @@ func (x *migrateDBCommand) migrateKvdb(srcTx walletdb.ReadWriteTx,
286
333
}
287
334
288
335
// Migrate wallet created marker.
289
- if prefix == lncfg .NSWalletDB && x .Dest .isRemote () {
336
+ //
337
+ // TODO(ziggie): Why not for bbolt backends ?
338
+ if prefix == lncfg .NSWalletDB && ! x .Dest .isBoltDB () {
290
339
const (
291
340
walletMetaBucket = "lnwallet"
292
341
walletReadyKey = "ready"
@@ -382,21 +431,27 @@ func (x *migrateDBCommand) migrateEtcd(srcTx walletdb.ReadWriteTx,
382
431
return nil
383
432
}
384
433
385
- func openDb (cfg * DB , prefix string ) (walletdb.DB , error ) {
434
+ func openDb (cfg * DB , prefix , network string ) (walletdb.DB , error ) {
386
435
backend := cfg .Backend
387
436
388
- var args []interface {}
437
+ // Init the db connections for sql backends.
438
+ cfg .Init ()
389
439
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
- )
440
+ // Settings to open a particular db backend.
441
+ var args []interface {}
397
442
398
443
switch backend {
399
444
case lncfg .BoltBackend :
445
+ // Directories where the db files are located.
446
+ graphDir := filepath .Join (cfg .Bolt .DataDir , "graph" , network )
447
+ walletDir := filepath .Join (
448
+ cfg .Bolt .DataDir , "chain" , "bitcoin" , network ,
449
+ )
450
+ towerServerDir := filepath .Join (
451
+ cfg .Bolt .TowerDir , "bitcoin" , network ,
452
+ )
453
+
454
+ // Path to the db file.
400
455
var path string
401
456
switch prefix {
402
457
case lncfg .NSChannelDB :
@@ -443,13 +498,68 @@ func openDb(cfg *DB, prefix string) (walletdb.DB, error) {
443
498
args = []interface {}{
444
499
context .Background (),
445
500
& postgres.Config {
446
- Dsn : cfg .Postgres .Dsn ,
501
+ Dsn : cfg .Postgres .Dsn ,
502
+ Timeout : time .Minute ,
503
+ MaxConnections : 10 ,
447
504
},
448
505
prefix ,
449
506
}
507
+
450
508
log ("Opening postgres backend at %s with prefix '%s'" ,
451
509
cfg .Postgres .Dsn , prefix )
452
510
511
+ case kvdb .SqliteBackendName :
512
+ // Directories where the db files are located.
513
+ graphDir := filepath .Join (cfg .Sqlite .DataDir , "graph" , network )
514
+ walletDir := filepath .Join (
515
+ cfg .Sqlite .DataDir , "chain" , "bitcoin" , network ,
516
+ )
517
+ towerServerDir := filepath .Join (
518
+ cfg .Sqlite .TowerDir , "bitcoin" , network ,
519
+ )
520
+
521
+ var dbName string
522
+ var path string
523
+ switch prefix {
524
+ case lncfg .NSChannelDB :
525
+ path = graphDir
526
+ dbName = lncfg .SqliteChannelDBName
527
+ case lncfg .NSMacaroonDB :
528
+ path = walletDir
529
+ dbName = lncfg .SqliteChainDBName
530
+
531
+ case lncfg .NSDecayedLogDB :
532
+ path = graphDir
533
+ dbName = lncfg .SqliteChannelDBName
534
+
535
+ case lncfg .NSTowerClientDB :
536
+ path = graphDir
537
+ dbName = lncfg .SqliteChannelDBName
538
+
539
+ case lncfg .NSTowerServerDB :
540
+ path = towerServerDir
541
+ dbName = lncfg .SqliteChannelDBName
542
+
543
+ case lncfg .NSWalletDB :
544
+ path = walletDir
545
+ dbName = lncfg .SqliteChainDBName
546
+
547
+ case lncfg .NSNeutrinoDB :
548
+ dbName = lncfg .SqliteNeutrinoDBName
549
+ }
550
+
551
+ args = []interface {}{
552
+ context .Background (),
553
+ & sqlite.Config {
554
+ Timeout : time .Minute ,
555
+ },
556
+ path ,
557
+ dbName ,
558
+ prefix ,
559
+ }
560
+
561
+ log ("Opening sqlite backend with prefix '%s'" , prefix )
562
+
453
563
default :
454
564
return nil , fmt .Errorf ("unknown backend: %v" , backend )
455
565
}
@@ -548,7 +658,7 @@ func addMarker(db walletdb.DB, markerKey []byte) error {
548
658
return rwtx .Commit ()
549
659
}
550
660
551
- func checkMigrationsApplied (db walletdb.DB ) error {
661
+ func checkChannelDBMigrationsApplied (db walletdb.DB ) error {
552
662
var meta channeldb.Meta
553
663
err := kvdb .View (db , func (tx kvdb.RTx ) error {
554
664
return channeldb .FetchMeta (& meta , tx )
0 commit comments