Skip to content

Commit 716c6dd

Browse files
authored
Merge pull request #8052 from bhandras/sql-invoices
sqldb: `InvoiceDB` implementation
2 parents d5138c1 + 6c09617 commit 716c6dd

39 files changed

+3105
-1100
lines changed

.github/workflows/main.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@ jobs:
252252
args: backend=bitcoind dbbackend=postgres
253253
- name: bitcoind-sqlite
254254
args: backend=bitcoind dbbackend=sqlite
255+
- name: bitcoind-postgres-nativesql
256+
args: backend=bitcoind dbbackend=postgres nativesql=true
257+
- name: bitcoind-sqlite-nativesql
258+
args: backend=bitcoind dbbackend=sqlite nativesql=true
255259
- name: neutrino
256260
args: backend=neutrino
257261
steps:

config_builder.go

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package lnd
33
import (
44
"bytes"
55
"context"
6+
"database/sql"
67
"errors"
78
"fmt"
89
"io/ioutil"
@@ -31,6 +32,7 @@ import (
3132
"github.com/lightningnetwork/lnd/chainntnfs"
3233
"github.com/lightningnetwork/lnd/chainreg"
3334
"github.com/lightningnetwork/lnd/channeldb"
35+
"github.com/lightningnetwork/lnd/clock"
3436
"github.com/lightningnetwork/lnd/invoices"
3537
"github.com/lightningnetwork/lnd/keychain"
3638
"github.com/lightningnetwork/lnd/kvdb"
@@ -42,6 +44,7 @@ import (
4244
"github.com/lightningnetwork/lnd/macaroons"
4345
"github.com/lightningnetwork/lnd/rpcperms"
4446
"github.com/lightningnetwork/lnd/signal"
47+
"github.com/lightningnetwork/lnd/sqldb"
4548
"github.com/lightningnetwork/lnd/walletunlocker"
4649
"github.com/lightningnetwork/lnd/watchtower"
4750
"github.com/lightningnetwork/lnd/watchtower/wtclient"
@@ -869,6 +872,11 @@ type DatabaseInstances struct {
869872
// WalletDB is the configuration for loading the wallet database using
870873
// the btcwallet's loader.
871874
WalletDB btcwallet.LoaderOption
875+
876+
// NativeSQLStore is a pointer to a native SQL store that can be used
877+
// for native SQL queries for tables that already support it. This may
878+
// be nil if the use-native-sql flag was not set.
879+
NativeSQLStore *sqldb.BaseDB
872880
}
873881

874882
// DefaultDatabaseBuilder is a type that builds the default database backends
@@ -923,10 +931,11 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
923931
// state DB point to the same local or remote DB and the same namespace
924932
// within that DB.
925933
dbs := &DatabaseInstances{
926-
HeightHintDB: databaseBackends.HeightHintDB,
927-
MacaroonDB: databaseBackends.MacaroonDB,
928-
DecayedLogDB: databaseBackends.DecayedLogDB,
929-
WalletDB: databaseBackends.WalletDB,
934+
HeightHintDB: databaseBackends.HeightHintDB,
935+
MacaroonDB: databaseBackends.MacaroonDB,
936+
DecayedLogDB: databaseBackends.DecayedLogDB,
937+
WalletDB: databaseBackends.WalletDB,
938+
NativeSQLStore: databaseBackends.NativeSQLStore,
930939
}
931940
cleanUp := func() {
932941
// We can just close the returned close functions directly. Even
@@ -1011,11 +1020,21 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
10111020
// using the same struct (and DB backend) instance.
10121021
dbs.ChanStateDB = dbs.GraphDB
10131022

1014-
// For now the only InvoiceDB implementation is the *channeldb.DB.
1015-
//
1016-
// TODO(positiveblue): use a sql first implementation for this
1017-
// interface.
1018-
dbs.InvoiceDB = dbs.GraphDB
1023+
// Instantiate a native SQL invoice store if the flag is set.
1024+
if d.cfg.DB.UseNativeSQL {
1025+
executor := sqldb.NewTransactionExecutor(
1026+
dbs.NativeSQLStore,
1027+
func(tx *sql.Tx) sqldb.InvoiceQueries {
1028+
return dbs.NativeSQLStore.WithTx(tx)
1029+
},
1030+
)
1031+
1032+
dbs.InvoiceDB = sqldb.NewInvoiceStore(
1033+
executor, clock.NewDefaultClock(),
1034+
)
1035+
} else {
1036+
dbs.InvoiceDB = dbs.GraphDB
1037+
}
10191038

10201039
// Wrap the watchtower client DB and make sure we clean up.
10211040
if cfg.WtClient.Active {
@@ -1298,8 +1317,9 @@ func initNeutrinoBackend(ctx context.Context, cfg *Config, chainDir string,
12981317
)
12991318
switch {
13001319
case cfg.DB.Backend == kvdb.SqliteBackendName:
1320+
sqliteConfig := lncfg.GetSqliteConfigKVDB(cfg.DB.Sqlite)
13011321
db, err = kvdb.Open(
1302-
kvdb.SqliteBackendName, ctx, cfg.DB.Sqlite, dbPath,
1322+
kvdb.SqliteBackendName, ctx, sqliteConfig, dbPath,
13031323
lncfg.SqliteNeutrinoDBName, lncfg.NSNeutrinoDB,
13041324
)
13051325

docs/release-notes/release-notes-0.18.0.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@
339339
* [Refactor UpdateInvoice](https://github.com/lightningnetwork/lnd/pull/8100) to
340340
make it simpler to adjust code to also support SQL InvoiceDB implementation.
341341

342+
* [InvoiceDB implementation](https://github.com/lightningnetwork/lnd/pull/8052)
343+
for SQL backends enabling new users to optionally use an experimental native
344+
SQL invoices database.
345+
342346
## Code Health
343347

344348
* [Remove database pointers](https://github.com/lightningnetwork/lnd/pull/8117)

invoices/invoiceregistry_test.go

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package invoices_test
33
import (
44
"context"
55
"crypto/rand"
6+
"database/sql"
67
"fmt"
78
"math"
89
"testing"
@@ -18,6 +19,7 @@ import (
1819
"github.com/lightningnetwork/lnd/lntypes"
1920
"github.com/lightningnetwork/lnd/lnwire"
2021
"github.com/lightningnetwork/lnd/record"
22+
"github.com/lightningnetwork/lnd/sqldb"
2123
"github.com/stretchr/testify/require"
2224
)
2325

@@ -114,12 +116,60 @@ func TestInvoiceRegistry(t *testing.T) {
114116
return db, testClock
115117
}
116118

119+
// First create a shared Postgres instance so we don't spawn a new
120+
// docker container for each test.
121+
pgFixture := sqldb.NewTestPgFixture(
122+
t, sqldb.DefaultPostgresFixtureLifetime,
123+
)
124+
t.Cleanup(func() {
125+
pgFixture.TearDown(t)
126+
})
127+
128+
makeSQLDB := func(t *testing.T, sqlite bool) (invpkg.InvoiceDB,
129+
*clock.TestClock) {
130+
131+
var db *sqldb.BaseDB
132+
if sqlite {
133+
db = sqldb.NewTestSqliteDB(t).BaseDB
134+
} else {
135+
db = sqldb.NewTestPostgresDB(t, pgFixture).BaseDB
136+
}
137+
138+
executor := sqldb.NewTransactionExecutor(
139+
db, func(tx *sql.Tx) sqldb.InvoiceQueries {
140+
return db.WithTx(tx)
141+
},
142+
)
143+
144+
testClock := clock.NewTestClock(testNow)
145+
146+
return sqldb.NewInvoiceStore(executor, testClock), testClock
147+
}
148+
117149
for _, test := range testList {
118150
test := test
119151

120-
t.Run(test.name, func(t *testing.T) {
152+
t.Run(test.name+"_KV", func(t *testing.T) {
121153
test.test(t, makeKeyValueDB)
122154
})
155+
156+
t.Run(test.name+"_SQLite", func(t *testing.T) {
157+
test.test(t,
158+
func(t *testing.T) (
159+
invpkg.InvoiceDB, *clock.TestClock) {
160+
161+
return makeSQLDB(t, true)
162+
})
163+
})
164+
165+
t.Run(test.name+"_Postgres", func(t *testing.T) {
166+
test.test(t,
167+
func(t *testing.T) (
168+
invpkg.InvoiceDB, *clock.TestClock) {
169+
170+
return makeSQLDB(t, false)
171+
})
172+
})
123173
}
124174
}
125175

0 commit comments

Comments
 (0)