• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 13157733617

05 Feb 2025 12:49PM UTC coverage: 57.712% (-1.1%) from 58.82%
13157733617

Pull #9447

github

yyforyongyu
sweep: rename methods for clarity

We now rename "third party" to "unknown" as the inputs can be spent via
an older sweeping tx, a third party (anchor), or a remote party (pin).
In fee bumper we don't have the info to distinguish the above cases, and
leave them to be further handled by the sweeper as it has more context.
Pull Request #9447: sweep: start tracking input spending status in the fee bumper

83 of 87 new or added lines in 2 files covered. (95.4%)

19472 existing lines in 252 files now uncovered.

103634 of 179570 relevant lines covered (57.71%)

24840.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

4.62
/lncfg/db.go
1
package lncfg
2

3
import (
4
        "context"
5
        "fmt"
6
        "path"
7
        "path/filepath"
8
        "time"
9

10
        "github.com/btcsuite/btclog/v2"
11
        "github.com/lightningnetwork/lnd/kvdb"
12
        "github.com/lightningnetwork/lnd/kvdb/etcd"
13
        "github.com/lightningnetwork/lnd/kvdb/postgres"
14
        "github.com/lightningnetwork/lnd/kvdb/sqlbase"
15
        "github.com/lightningnetwork/lnd/kvdb/sqlite"
16
        "github.com/lightningnetwork/lnd/lnrpc"
17
        "github.com/lightningnetwork/lnd/lnwallet/btcwallet"
18
        "github.com/lightningnetwork/lnd/sqldb"
19
)
20

21
const (
22
        ChannelDBName     = "channel.db"
23
        MacaroonDBName    = "macaroons.db"
24
        DecayedLogDbName  = "sphinxreplay.db"
25
        TowerClientDBName = "wtclient.db"
26
        TowerServerDBName = "watchtower.db"
27
        WalletDBName      = "wallet.db"
28

29
        SqliteChannelDBName  = "channel.sqlite"
30
        SqliteChainDBName    = "chain.sqlite"
31
        SqliteNeutrinoDBName = "neutrino.sqlite"
32
        SqliteTowerDBName    = "watchtower.sqlite"
33
        SqliteNativeDBName   = "lnd.sqlite"
34

35
        BoltBackend                = "bolt"
36
        EtcdBackend                = "etcd"
37
        PostgresBackend            = "postgres"
38
        SqliteBackend              = "sqlite"
39
        DefaultBatchCommitInterval = 500 * time.Millisecond
40

41
        defaultPostgresMaxConnections = 50
42
        defaultSqliteMaxConnections   = 2
43

44
        defaultSqliteBusyTimeout = 5 * time.Second
45

46
        // NSChannelDB is the namespace name that we use for the combined graph
47
        // and channel state DB.
48
        NSChannelDB = "channeldb"
49

50
        // NSMacaroonDB is the namespace name that we use for the macaroon DB.
51
        NSMacaroonDB = "macaroondb"
52

53
        // NSDecayedLogDB is the namespace name that we use for the sphinx
54
        // replay a.k.a. decayed log DB.
55
        NSDecayedLogDB = "decayedlogdb"
56

57
        // NSTowerClientDB is the namespace name that we use for the watchtower
58
        // client DB.
59
        NSTowerClientDB = "towerclientdb"
60

61
        // NSTowerServerDB is the namespace name that we use for the watchtower
62
        // server DB.
63
        NSTowerServerDB = "towerserverdb"
64

65
        // NSWalletDB is the namespace name that we use for the wallet DB.
66
        NSWalletDB = "walletdb"
67

68
        // NSNeutrinoDB is the namespace name that we use for the neutrino DB.
69
        NSNeutrinoDB = "neutrinodb"
70
)
71

72
// DB holds database configuration for LND.
73
//
74
//nolint:ll
75
type DB struct {
76
        Backend string `long:"backend" description:"The selected database backend."`
77

78
        BatchCommitInterval time.Duration `long:"batch-commit-interval" description:"The maximum duration the channel graph batch schedulers will wait before attempting to commit a batch of pending updates. This can be tradeoff database contenion for commit latency."`
79

80
        Etcd *etcd.Config `group:"etcd" namespace:"etcd" description:"Etcd settings."`
81

82
        Bolt *kvdb.BoltConfig `group:"bolt" namespace:"bolt" description:"Bolt settings."`
83

84
        Postgres *sqldb.PostgresConfig `group:"postgres" namespace:"postgres" description:"Postgres settings."`
85

86
        Sqlite *sqldb.SqliteConfig `group:"sqlite" namespace:"sqlite" description:"Sqlite settings."`
87

88
        UseNativeSQL bool `long:"use-native-sql" description:"Use native SQL for tables that already support it."`
89

90
        SkipSQLInvoiceMigration bool `long:"skip-sql-invoice-migration" description:"Do not migrate invoices stored in our key-value database to native SQL."`
91

92
        NoGraphCache bool `long:"no-graph-cache" description:"Don't use the in-memory graph cache for path finding. Much slower but uses less RAM. Can only be used with a bolt database backend."`
93

94
        PruneRevocation bool `long:"prune-revocation" description:"Run the optional migration that prunes the revocation logs to save disk space."`
95

96
        NoRevLogAmtData bool `long:"no-rev-log-amt-data" description:"If set, the to-local and to-remote output amounts of revoked commitment transactions will not be stored in the revocation log. Note that once this data is lost, a watchtower client will not be able to back up the revoked state."`
97
}
98

99
// DefaultDB creates and returns a new default DB config.
100
func DefaultDB() *DB {
2✔
101
        return &DB{
2✔
102
                Backend:             BoltBackend,
2✔
103
                BatchCommitInterval: DefaultBatchCommitInterval,
2✔
104
                Bolt: &kvdb.BoltConfig{
2✔
105
                        NoFreelistSync:    true,
2✔
106
                        AutoCompactMinAge: kvdb.DefaultBoltAutoCompactMinAge,
2✔
107
                        DBTimeout:         kvdb.DefaultDBTimeout,
2✔
108
                },
2✔
109
                Etcd: &etcd.Config{
2✔
110
                        // Allow at most 32 MiB messages by default.
2✔
111
                        MaxMsgSize: 32768 * 1024,
2✔
112
                },
2✔
113
                Postgres: &sqldb.PostgresConfig{
2✔
114
                        MaxConnections: defaultPostgresMaxConnections,
2✔
115
                },
2✔
116
                Sqlite: &sqldb.SqliteConfig{
2✔
117
                        MaxConnections: defaultSqliteMaxConnections,
2✔
118
                        BusyTimeout:    defaultSqliteBusyTimeout,
2✔
119
                },
2✔
120
                UseNativeSQL:            false,
2✔
121
                SkipSQLInvoiceMigration: false,
2✔
122
        }
2✔
123
}
2✔
124

125
// Validate validates the DB config.
UNCOV
126
func (db *DB) Validate() error {
×
UNCOV
127
        switch db.Backend {
×
UNCOV
128
        case BoltBackend:
×
UNCOV
129
                if db.UseNativeSQL {
×
130
                        return fmt.Errorf("cannot use native SQL with bolt " +
×
131
                                "backend")
×
132
                }
×
133

134
        case SqliteBackend:
×
135
        case PostgresBackend:
×
136
                if err := db.Postgres.Validate(); err != nil {
×
137
                        return err
×
138
                }
×
139

140
        case EtcdBackend:
×
141
                if db.UseNativeSQL {
×
142
                        return fmt.Errorf("cannot use native SQL with etcd " +
×
143
                                "backend")
×
144
                }
×
145

146
                if !db.Etcd.Embedded && db.Etcd.Host == "" {
×
147
                        return fmt.Errorf("etcd host must be set")
×
148
                }
×
149

150
        default:
×
151
                return fmt.Errorf("unknown backend, must be either '%v', "+
×
152
                        "'%v', '%v' or '%v'", BoltBackend, EtcdBackend,
×
153
                        PostgresBackend, SqliteBackend)
×
154
        }
155

156
        // The path finding uses a manual read transaction that's open for a
157
        // potentially long time. That works fine with the locking model of
158
        // bbolt but can lead to locks or rolled back transactions with etcd or
159
        // postgres. And since we already have a smaller memory footprint for
160
        // remote database setups (due to not needing to memory-map the bbolt DB
161
        // files), we can keep the graph in memory instead. But for mobile
162
        // devices the tradeoff between a smaller memory footprint and the
163
        // longer time needed for path finding might be a desirable one.
UNCOV
164
        if db.NoGraphCache && db.Backend != BoltBackend {
×
165
                return fmt.Errorf("cannot use no-graph-cache with database "+
×
166
                        "backend '%v'", db.Backend)
×
167
        }
×
168

UNCOV
169
        return nil
×
170
}
171

172
// Init should be called upon start to pre-initialize database access dependent
173
// on configuration.
UNCOV
174
func (db *DB) Init(ctx context.Context, dbPath string) error {
×
UNCOV
175
        // Start embedded etcd server if requested.
×
UNCOV
176
        switch {
×
177
        case db.Backend == EtcdBackend && db.Etcd.Embedded:
×
178
                cfg, _, err := kvdb.StartEtcdTestBackend(
×
179
                        dbPath, db.Etcd.EmbeddedClientPort,
×
180
                        db.Etcd.EmbeddedPeerPort, db.Etcd.EmbeddedLogFile,
×
181
                )
×
182
                if err != nil {
×
183
                        return err
×
184
                }
×
185

186
                // Override the original config with the config for
187
                // the embedded instance.
188
                db.Etcd = cfg
×
189

190
        case db.Backend == PostgresBackend:
×
191
                sqlbase.Init(db.Postgres.MaxConnections)
×
192

193
        case db.Backend == SqliteBackend:
×
194
                sqlbase.Init(db.Sqlite.MaxConnections)
×
195
        }
196

UNCOV
197
        return nil
×
198
}
199

200
// DatabaseBackends is a two-tuple that holds the set of active database
201
// backends for the daemon. The two backends we expose are the graph database
202
// backend, and the channel state backend.
203
type DatabaseBackends struct {
204
        // GraphDB points to the database backend that contains the less
205
        // critical data that is accessed often, such as the channel graph and
206
        // chain height hints.
207
        GraphDB kvdb.Backend
208

209
        // ChanStateDB points to a possibly networked replicated backend that
210
        // contains the critical channel state related data.
211
        ChanStateDB kvdb.Backend
212

213
        // HeightHintDB points to a possibly networked replicated backend that
214
        // contains the chain height hint related data.
215
        HeightHintDB kvdb.Backend
216

217
        // MacaroonDB points to a database backend that stores the macaroon root
218
        // keys.
219
        MacaroonDB kvdb.Backend
220

221
        // DecayedLogDB points to a database backend that stores the decayed log
222
        // data.
223
        DecayedLogDB kvdb.Backend
224

225
        // TowerClientDB points to a database backend that stores the watchtower
226
        // client data. This might be nil if the watchtower client is disabled.
227
        TowerClientDB kvdb.Backend
228

229
        // TowerServerDB points to a database backend that stores the watchtower
230
        // server data. This might be nil if the watchtower server is disabled.
231
        TowerServerDB kvdb.Backend
232

233
        // WalletDB is an option that instructs the wallet loader where to load
234
        // the underlying wallet database from.
235
        WalletDB btcwallet.LoaderOption
236

237
        // NativeSQLStore holds a reference to the native SQL store that can
238
        // be used for native SQL queries for tables that already support it.
239
        // This may be nil if the use-native-sql flag was not set.
240
        NativeSQLStore sqldb.DB
241

242
        // Remote indicates whether the database backends are remote, possibly
243
        // replicated instances or local bbolt or sqlite backed databases.
244
        Remote bool
245

246
        // CloseFuncs is a map of close functions for each of the initialized
247
        // DB backends keyed by their namespace name.
248
        CloseFuncs map[string]func() error
249
}
250

251
// GetPostgresConfigKVDB converts a sqldb.PostgresConfig to a kvdb
252
// postgres.Config.
253
func GetPostgresConfigKVDB(cfg *sqldb.PostgresConfig) *postgres.Config {
×
254
        return &postgres.Config{
×
255
                Dsn:            cfg.Dsn,
×
256
                Timeout:        cfg.Timeout,
×
257
                MaxConnections: cfg.MaxConnections,
×
258
        }
×
259
}
×
260

261
// GetSqliteConfigKVDB converts a sqldb.SqliteConfig to a kvdb sqlite.Config.
262
func GetSqliteConfigKVDB(cfg *sqldb.SqliteConfig) *sqlite.Config {
×
263
        return &sqlite.Config{
×
264
                Timeout:        cfg.Timeout,
×
265
                BusyTimeout:    cfg.BusyTimeout,
×
266
                MaxConnections: cfg.MaxConnections,
×
267
                PragmaOptions:  cfg.PragmaOptions,
×
268
        }
×
269
}
×
270

271
// GetBackends returns a set of kvdb.Backends as set in the DB config.
272
func (db *DB) GetBackends(ctx context.Context, chanDBPath,
273
        walletDBPath, towerServerDBPath string, towerClientEnabled,
274
        towerServerEnabled bool, logger btclog.Logger) (*DatabaseBackends,
UNCOV
275
        error) {
×
UNCOV
276

×
UNCOV
277
        // We keep track of all the kvdb backends we actually open and return a
×
UNCOV
278
        // reference to their close function so they can be cleaned up properly
×
UNCOV
279
        // on error or shutdown.
×
UNCOV
280
        closeFuncs := make(map[string]func() error)
×
UNCOV
281

×
UNCOV
282
        // If we need to return early because of an error, we invoke any close
×
UNCOV
283
        // function that has been initialized so far.
×
UNCOV
284
        returnEarly := true
×
UNCOV
285
        defer func() {
×
UNCOV
286
                if !returnEarly {
×
UNCOV
287
                        return
×
UNCOV
288
                }
×
289

290
                for _, closeFunc := range closeFuncs {
×
291
                        _ = closeFunc()
×
292
                }
×
293
        }()
294

UNCOV
295
        switch db.Backend {
×
296
        case EtcdBackend:
×
297
                // As long as the graph data, channel state and height hint
×
298
                // cache are all still in the channel.db file in bolt, we
×
299
                // replicate the same behavior here and use the same etcd
×
300
                // backend for those three sub DBs. But we namespace it properly
×
301
                // to make such a split even easier in the future. This will
×
302
                // break lnd for users that ran on etcd with 0.13.x since that
×
303
                // code used the root namespace. We assume that nobody used etcd
×
304
                // for mainnet just yet since that feature was clearly marked as
×
305
                // experimental in 0.13.x.
×
306
                etcdBackend, err := kvdb.Open(
×
307
                        kvdb.EtcdBackendName, ctx,
×
308
                        db.Etcd.CloneWithSubNamespace(NSChannelDB),
×
309
                )
×
310
                if err != nil {
×
311
                        return nil, fmt.Errorf("error opening etcd DB: %w", err)
×
312
                }
×
313
                closeFuncs[NSChannelDB] = etcdBackend.Close
×
314

×
315
                etcdMacaroonBackend, err := kvdb.Open(
×
316
                        kvdb.EtcdBackendName, ctx,
×
317
                        db.Etcd.CloneWithSubNamespace(NSMacaroonDB),
×
318
                )
×
319
                if err != nil {
×
320
                        return nil, fmt.Errorf("error opening etcd macaroon "+
×
321
                                "DB: %v", err)
×
322
                }
×
323
                closeFuncs[NSMacaroonDB] = etcdMacaroonBackend.Close
×
324

×
325
                etcdDecayedLogBackend, err := kvdb.Open(
×
326
                        kvdb.EtcdBackendName, ctx,
×
327
                        db.Etcd.CloneWithSubNamespace(NSDecayedLogDB),
×
328
                )
×
329
                if err != nil {
×
330
                        return nil, fmt.Errorf("error opening etcd decayed "+
×
331
                                "log DB: %v", err)
×
332
                }
×
333
                closeFuncs[NSDecayedLogDB] = etcdDecayedLogBackend.Close
×
334

×
335
                etcdTowerClientBackend, err := kvdb.Open(
×
336
                        kvdb.EtcdBackendName, ctx,
×
337
                        db.Etcd.CloneWithSubNamespace(NSTowerClientDB),
×
338
                )
×
339
                if err != nil {
×
340
                        return nil, fmt.Errorf("error opening etcd tower "+
×
341
                                "client DB: %v", err)
×
342
                }
×
343
                closeFuncs[NSTowerClientDB] = etcdTowerClientBackend.Close
×
344

×
345
                etcdTowerServerBackend, err := kvdb.Open(
×
346
                        kvdb.EtcdBackendName, ctx,
×
347
                        db.Etcd.CloneWithSubNamespace(NSTowerServerDB),
×
348
                )
×
349
                if err != nil {
×
350
                        return nil, fmt.Errorf("error opening etcd tower "+
×
351
                                "server DB: %v", err)
×
352
                }
×
353
                closeFuncs[NSTowerServerDB] = etcdTowerServerBackend.Close
×
354

×
355
                etcdWalletBackend, err := kvdb.Open(
×
356
                        kvdb.EtcdBackendName, ctx,
×
357
                        db.Etcd.
×
358
                                CloneWithSubNamespace(NSWalletDB).
×
359
                                CloneWithSingleWriter(),
×
360
                )
×
361
                if err != nil {
×
362
                        return nil, fmt.Errorf("error opening etcd macaroon "+
×
363
                                "DB: %v", err)
×
364
                }
×
365
                closeFuncs[NSWalletDB] = etcdWalletBackend.Close
×
366

×
367
                returnEarly = false
×
368

×
369
                return &DatabaseBackends{
×
370
                        GraphDB:       etcdBackend,
×
371
                        ChanStateDB:   etcdBackend,
×
372
                        HeightHintDB:  etcdBackend,
×
373
                        MacaroonDB:    etcdMacaroonBackend,
×
374
                        DecayedLogDB:  etcdDecayedLogBackend,
×
375
                        TowerClientDB: etcdTowerClientBackend,
×
376
                        TowerServerDB: etcdTowerServerBackend,
×
377
                        // The wallet loader will attempt to use/create the
×
378
                        // wallet in the replicated remote DB if we're running
×
379
                        // in a clustered environment. This will ensure that all
×
380
                        // members of the cluster have access to the same wallet
×
381
                        // state.
×
382
                        WalletDB: btcwallet.LoaderWithExternalWalletDB(
×
383
                                etcdWalletBackend,
×
384
                        ),
×
385
                        Remote:     true,
×
386
                        CloseFuncs: closeFuncs,
×
387
                }, nil
×
388

389
        case PostgresBackend:
×
390
                // Convert the sqldb PostgresConfig to a kvdb postgres.Config.
×
391
                // This is a temporary measure until we migrate all kvdb SQL
×
392
                // users to native SQL.
×
393
                postgresConfig := GetPostgresConfigKVDB(db.Postgres)
×
394

×
395
                postgresBackend, err := kvdb.Open(
×
396
                        kvdb.PostgresBackendName, ctx,
×
397
                        postgresConfig, NSChannelDB,
×
398
                )
×
399
                if err != nil {
×
400
                        return nil, fmt.Errorf("error opening postgres graph "+
×
401
                                "DB: %v", err)
×
402
                }
×
403
                closeFuncs[NSChannelDB] = postgresBackend.Close
×
404

×
405
                postgresMacaroonBackend, err := kvdb.Open(
×
406
                        kvdb.PostgresBackendName, ctx,
×
407
                        postgresConfig, NSMacaroonDB,
×
408
                )
×
409
                if err != nil {
×
410
                        return nil, fmt.Errorf("error opening postgres "+
×
411
                                "macaroon DB: %v", err)
×
412
                }
×
413
                closeFuncs[NSMacaroonDB] = postgresMacaroonBackend.Close
×
414

×
415
                postgresDecayedLogBackend, err := kvdb.Open(
×
416
                        kvdb.PostgresBackendName, ctx,
×
417
                        postgresConfig, NSDecayedLogDB,
×
418
                )
×
419
                if err != nil {
×
420
                        return nil, fmt.Errorf("error opening postgres "+
×
421
                                "decayed log DB: %v", err)
×
422
                }
×
423
                closeFuncs[NSDecayedLogDB] = postgresDecayedLogBackend.Close
×
424

×
425
                postgresTowerClientBackend, err := kvdb.Open(
×
426
                        kvdb.PostgresBackendName, ctx,
×
427
                        postgresConfig, NSTowerClientDB,
×
428
                )
×
429
                if err != nil {
×
430
                        return nil, fmt.Errorf("error opening postgres tower "+
×
431
                                "client DB: %v", err)
×
432
                }
×
433
                closeFuncs[NSTowerClientDB] = postgresTowerClientBackend.Close
×
434

×
435
                postgresTowerServerBackend, err := kvdb.Open(
×
436
                        kvdb.PostgresBackendName, ctx,
×
437
                        postgresConfig, NSTowerServerDB,
×
438
                )
×
439
                if err != nil {
×
440
                        return nil, fmt.Errorf("error opening postgres tower "+
×
441
                                "server DB: %v", err)
×
442
                }
×
443
                closeFuncs[NSTowerServerDB] = postgresTowerServerBackend.Close
×
444

×
445
                postgresWalletBackend, err := kvdb.Open(
×
446
                        kvdb.PostgresBackendName, ctx,
×
447
                        postgresConfig, NSWalletDB,
×
448
                )
×
449
                if err != nil {
×
450
                        return nil, fmt.Errorf("error opening postgres macaroon "+
×
451
                                "DB: %v", err)
×
452
                }
×
453
                closeFuncs[NSWalletDB] = postgresWalletBackend.Close
×
454

×
455
                var nativeSQLStore sqldb.DB
×
456
                if db.UseNativeSQL {
×
457
                        nativePostgresStore, err := sqldb.NewPostgresStore(
×
458
                                db.Postgres,
×
459
                        )
×
460
                        if err != nil {
×
461
                                return nil, fmt.Errorf("error opening "+
×
462
                                        "native postgres store: %v", err)
×
463
                        }
×
464

465
                        nativeSQLStore = nativePostgresStore
×
466
                        closeFuncs[PostgresBackend] = nativePostgresStore.Close
×
467
                }
468

469
                // Warn if the user is trying to switch over to a Postgres DB
470
                // while there is a wallet or channel bbolt DB still present.
471
                warnExistingBoltDBs(
×
472
                        logger, "postgres", walletDBPath, WalletDBName,
×
473
                )
×
474
                warnExistingBoltDBs(
×
475
                        logger, "postgres", chanDBPath, ChannelDBName,
×
476
                )
×
477

×
478
                returnEarly = false
×
479

×
480
                return &DatabaseBackends{
×
481
                        GraphDB:       postgresBackend,
×
482
                        ChanStateDB:   postgresBackend,
×
483
                        HeightHintDB:  postgresBackend,
×
484
                        MacaroonDB:    postgresMacaroonBackend,
×
485
                        DecayedLogDB:  postgresDecayedLogBackend,
×
486
                        TowerClientDB: postgresTowerClientBackend,
×
487
                        TowerServerDB: postgresTowerServerBackend,
×
488
                        // The wallet loader will attempt to use/create the
×
489
                        // wallet in the replicated remote DB if we're running
×
490
                        // in a clustered environment. This will ensure that all
×
491
                        // members of the cluster have access to the same wallet
×
492
                        // state.
×
493
                        WalletDB: btcwallet.LoaderWithExternalWalletDB(
×
494
                                postgresWalletBackend,
×
495
                        ),
×
496
                        NativeSQLStore: nativeSQLStore,
×
497
                        Remote:         true,
×
498
                        CloseFuncs:     closeFuncs,
×
499
                }, nil
×
500

501
        case SqliteBackend:
×
502
                // Convert the sqldb SqliteConfig to a kvdb sqlite.Config.
×
503
                // This is a temporary measure until we migrate all kvdb SQL
×
504
                // users to native SQL.
×
505
                sqliteConfig := GetSqliteConfigKVDB(db.Sqlite)
×
506

×
507
                // Note that for sqlite, we put kv tables for the channel.db,
×
508
                // wtclient.db and sphinxreplay.db all in the channel.sqlite db.
×
509
                // The tables for wallet.db and macaroon.db are in the
×
510
                // chain.sqlite db and watchtower.db tables are in the
×
511
                // watchtower.sqlite db. The reason for the multiple sqlite dbs
×
512
                // is twofold. The first reason is that it maintains the file
×
513
                // structure that users are used to. The second reason is the
×
514
                // fact that sqlite only supports one writer at a time which
×
515
                // would cause deadlocks in the code due to the wallet db often
×
516
                // being accessed during a write to another db.
×
517
                sqliteBackend, err := kvdb.Open(
×
518
                        kvdb.SqliteBackendName, ctx, sqliteConfig, chanDBPath,
×
519
                        SqliteChannelDBName, NSChannelDB,
×
520
                )
×
521
                if err != nil {
×
522
                        return nil, fmt.Errorf("error opening sqlite graph "+
×
523
                                "DB: %v", err)
×
524
                }
×
525
                closeFuncs[NSChannelDB] = sqliteBackend.Close
×
526

×
527
                sqliteMacaroonBackend, err := kvdb.Open(
×
528
                        kvdb.SqliteBackendName, ctx, sqliteConfig, walletDBPath,
×
529
                        SqliteChainDBName, NSMacaroonDB,
×
530
                )
×
531
                if err != nil {
×
532
                        return nil, fmt.Errorf("error opening sqlite "+
×
533
                                "macaroon DB: %v", err)
×
534
                }
×
535
                closeFuncs[NSMacaroonDB] = sqliteMacaroonBackend.Close
×
536

×
537
                sqliteDecayedLogBackend, err := kvdb.Open(
×
538
                        kvdb.SqliteBackendName, ctx, sqliteConfig, chanDBPath,
×
539
                        SqliteChannelDBName, NSDecayedLogDB,
×
540
                )
×
541
                if err != nil {
×
542
                        return nil, fmt.Errorf("error opening sqlite decayed "+
×
543
                                "log DB: %v", err)
×
544
                }
×
545
                closeFuncs[NSDecayedLogDB] = sqliteDecayedLogBackend.Close
×
546

×
547
                sqliteTowerClientBackend, err := kvdb.Open(
×
548
                        kvdb.SqliteBackendName, ctx, sqliteConfig, chanDBPath,
×
549
                        SqliteChannelDBName, NSTowerClientDB,
×
550
                )
×
551
                if err != nil {
×
552
                        return nil, fmt.Errorf("error opening sqlite tower "+
×
553
                                "client DB: %v", err)
×
554
                }
×
555
                closeFuncs[NSTowerClientDB] = sqliteTowerClientBackend.Close
×
556

×
557
                sqliteTowerServerBackend, err := kvdb.Open(
×
558
                        kvdb.SqliteBackendName, ctx, sqliteConfig,
×
559
                        towerServerDBPath, SqliteTowerDBName, NSTowerServerDB,
×
560
                )
×
561
                if err != nil {
×
562
                        return nil, fmt.Errorf("error opening sqlite tower "+
×
563
                                "server DB: %v", err)
×
564
                }
×
565
                closeFuncs[NSTowerServerDB] = sqliteTowerServerBackend.Close
×
566

×
567
                sqliteWalletBackend, err := kvdb.Open(
×
568
                        kvdb.SqliteBackendName, ctx, sqliteConfig, walletDBPath,
×
569
                        SqliteChainDBName, NSWalletDB,
×
570
                )
×
571
                if err != nil {
×
572
                        return nil, fmt.Errorf("error opening sqlite macaroon "+
×
573
                                "DB: %v", err)
×
574
                }
×
575
                closeFuncs[NSWalletDB] = sqliteWalletBackend.Close
×
576

×
577
                var nativeSQLStore sqldb.DB
×
578
                if db.UseNativeSQL {
×
579
                        nativeSQLiteStore, err := sqldb.NewSqliteStore(
×
580
                                db.Sqlite,
×
581
                                path.Join(chanDBPath, SqliteNativeDBName),
×
582
                        )
×
583
                        if err != nil {
×
584
                                return nil, fmt.Errorf("error opening "+
×
585
                                        "native SQLite store: %v", err)
×
586
                        }
×
587

588
                        nativeSQLStore = nativeSQLiteStore
×
589
                        closeFuncs[SqliteBackend] = nativeSQLiteStore.Close
×
590
                }
591

592
                // Warn if the user is trying to switch over to a sqlite DB
593
                // while there is a wallet or channel bbolt DB still present.
594
                warnExistingBoltDBs(
×
595
                        logger, "sqlite", walletDBPath, WalletDBName,
×
596
                )
×
597
                warnExistingBoltDBs(
×
598
                        logger, "sqlite", chanDBPath, ChannelDBName,
×
599
                )
×
600

×
601
                returnEarly = false
×
602

×
603
                return &DatabaseBackends{
×
604
                        GraphDB:       sqliteBackend,
×
605
                        ChanStateDB:   sqliteBackend,
×
606
                        HeightHintDB:  sqliteBackend,
×
607
                        MacaroonDB:    sqliteMacaroonBackend,
×
608
                        DecayedLogDB:  sqliteDecayedLogBackend,
×
609
                        TowerClientDB: sqliteTowerClientBackend,
×
610
                        TowerServerDB: sqliteTowerServerBackend,
×
611
                        // The wallet loader will attempt to use/create the
×
612
                        // wallet in the replicated remote DB if we're running
×
613
                        // in a clustered environment. This will ensure that all
×
614
                        // members of the cluster have access to the same wallet
×
615
                        // state.
×
616
                        WalletDB: btcwallet.LoaderWithExternalWalletDB(
×
617
                                sqliteWalletBackend,
×
618
                        ),
×
619
                        NativeSQLStore: nativeSQLStore,
×
620
                        CloseFuncs:     closeFuncs,
×
621
                }, nil
×
622
        }
623

624
        // We're using all bbolt based databases by default.
UNCOV
625
        boltBackend, err := kvdb.GetBoltBackend(&kvdb.BoltBackendConfig{
×
UNCOV
626
                DBPath:            chanDBPath,
×
UNCOV
627
                DBFileName:        ChannelDBName,
×
UNCOV
628
                DBTimeout:         db.Bolt.DBTimeout,
×
UNCOV
629
                NoFreelistSync:    db.Bolt.NoFreelistSync,
×
UNCOV
630
                AutoCompact:       db.Bolt.AutoCompact,
×
UNCOV
631
                AutoCompactMinAge: db.Bolt.AutoCompactMinAge,
×
UNCOV
632
        })
×
UNCOV
633
        if err != nil {
×
634
                return nil, fmt.Errorf("error opening bolt DB: %w", err)
×
635
        }
×
UNCOV
636
        closeFuncs[NSChannelDB] = boltBackend.Close
×
UNCOV
637

×
UNCOV
638
        macaroonBackend, err := kvdb.GetBoltBackend(&kvdb.BoltBackendConfig{
×
UNCOV
639
                DBPath:            walletDBPath,
×
UNCOV
640
                DBFileName:        MacaroonDBName,
×
UNCOV
641
                DBTimeout:         db.Bolt.DBTimeout,
×
UNCOV
642
                NoFreelistSync:    db.Bolt.NoFreelistSync,
×
UNCOV
643
                AutoCompact:       db.Bolt.AutoCompact,
×
UNCOV
644
                AutoCompactMinAge: db.Bolt.AutoCompactMinAge,
×
UNCOV
645
        })
×
UNCOV
646
        if err != nil {
×
647
                return nil, fmt.Errorf("error opening macaroon DB: %w", err)
×
648
        }
×
UNCOV
649
        closeFuncs[NSMacaroonDB] = macaroonBackend.Close
×
UNCOV
650

×
UNCOV
651
        decayedLogBackend, err := kvdb.GetBoltBackend(&kvdb.BoltBackendConfig{
×
UNCOV
652
                DBPath:            chanDBPath,
×
UNCOV
653
                DBFileName:        DecayedLogDbName,
×
UNCOV
654
                DBTimeout:         db.Bolt.DBTimeout,
×
UNCOV
655
                NoFreelistSync:    db.Bolt.NoFreelistSync,
×
UNCOV
656
                AutoCompact:       db.Bolt.AutoCompact,
×
UNCOV
657
                AutoCompactMinAge: db.Bolt.AutoCompactMinAge,
×
UNCOV
658
        })
×
UNCOV
659
        if err != nil {
×
660
                return nil, fmt.Errorf("error opening decayed log DB: %w", err)
×
661
        }
×
UNCOV
662
        closeFuncs[NSDecayedLogDB] = decayedLogBackend.Close
×
UNCOV
663

×
UNCOV
664
        // The tower client is optional and might not be enabled by the user. We
×
UNCOV
665
        // handle it being nil properly in the main server.
×
UNCOV
666
        var towerClientBackend kvdb.Backend
×
UNCOV
667
        if towerClientEnabled {
×
UNCOV
668
                towerClientBackend, err = kvdb.GetBoltBackend(
×
UNCOV
669
                        &kvdb.BoltBackendConfig{
×
UNCOV
670
                                DBPath:            chanDBPath,
×
UNCOV
671
                                DBFileName:        TowerClientDBName,
×
UNCOV
672
                                DBTimeout:         db.Bolt.DBTimeout,
×
UNCOV
673
                                NoFreelistSync:    db.Bolt.NoFreelistSync,
×
UNCOV
674
                                AutoCompact:       db.Bolt.AutoCompact,
×
UNCOV
675
                                AutoCompactMinAge: db.Bolt.AutoCompactMinAge,
×
UNCOV
676
                        },
×
UNCOV
677
                )
×
UNCOV
678
                if err != nil {
×
679
                        return nil, fmt.Errorf("error opening tower client "+
×
680
                                "DB: %v", err)
×
681
                }
×
UNCOV
682
                closeFuncs[NSTowerClientDB] = towerClientBackend.Close
×
683
        }
684

685
        // The tower server is optional and might not be enabled by the user. We
686
        // handle it being nil properly in the main server.
UNCOV
687
        var towerServerBackend kvdb.Backend
×
UNCOV
688
        if towerServerEnabled {
×
UNCOV
689
                towerServerBackend, err = kvdb.GetBoltBackend(
×
UNCOV
690
                        &kvdb.BoltBackendConfig{
×
UNCOV
691
                                DBPath:            towerServerDBPath,
×
UNCOV
692
                                DBFileName:        TowerServerDBName,
×
UNCOV
693
                                DBTimeout:         db.Bolt.DBTimeout,
×
UNCOV
694
                                NoFreelistSync:    db.Bolt.NoFreelistSync,
×
UNCOV
695
                                AutoCompact:       db.Bolt.AutoCompact,
×
UNCOV
696
                                AutoCompactMinAge: db.Bolt.AutoCompactMinAge,
×
UNCOV
697
                        },
×
UNCOV
698
                )
×
UNCOV
699
                if err != nil {
×
700
                        return nil, fmt.Errorf("error opening tower server "+
×
701
                                "DB: %v", err)
×
702
                }
×
UNCOV
703
                closeFuncs[NSTowerServerDB] = towerServerBackend.Close
×
704
        }
705

UNCOV
706
        returnEarly = false
×
UNCOV
707

×
UNCOV
708
        return &DatabaseBackends{
×
UNCOV
709
                GraphDB:       boltBackend,
×
UNCOV
710
                ChanStateDB:   boltBackend,
×
UNCOV
711
                HeightHintDB:  boltBackend,
×
UNCOV
712
                MacaroonDB:    macaroonBackend,
×
UNCOV
713
                DecayedLogDB:  decayedLogBackend,
×
UNCOV
714
                TowerClientDB: towerClientBackend,
×
UNCOV
715
                TowerServerDB: towerServerBackend,
×
UNCOV
716
                // When "running locally", LND will use the bbolt wallet.db to
×
UNCOV
717
                // store the wallet located in the chain data dir, parametrized
×
UNCOV
718
                // by the active network. The wallet loader has its own cleanup
×
UNCOV
719
                // method so we don't need to add anything to our map (in fact
×
UNCOV
720
                // nothing is opened just yet).
×
UNCOV
721
                WalletDB: btcwallet.LoaderWithLocalWalletDB(
×
UNCOV
722
                        walletDBPath, db.Bolt.NoFreelistSync, db.Bolt.DBTimeout,
×
UNCOV
723
                ),
×
UNCOV
724
                CloseFuncs: closeFuncs,
×
UNCOV
725
        }, nil
×
726
}
727

728
// warnExistingBoltDBs checks if there is an existing bbolt database in the
729
// given location and logs a warning if so.
730
func warnExistingBoltDBs(log btclog.Logger, dbType, dir, fileName string) {
×
731
        if lnrpc.FileExists(filepath.Join(dir, fileName)) {
×
732
                log.Warnf("Found existing bbolt database file in %s/%s while "+
×
733
                        "using database type %s. Existing data will NOT be "+
×
734
                        "migrated to %s automatically!", dir, fileName, dbType,
×
735
                        dbType)
×
736
        }
×
737
}
738

739
// Compile-time constraint to ensure Workers implements the Validator interface.
740
var _ Validator = (*DB)(nil)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc