-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
invoices: migrate KV invoices to native SQL for users of KV SQL backends #8831
base: master
Are you sure you want to change the base?
Changes from 1 commit
02565bf
0dc19ed
bdf2c68
8ed2cad
cd3be24
cd28406
a662470
2ea0af2
6ce0f8f
f502910
da850b1
1c2ee9e
7a60c30
7bb57be
a9351c7
c4d14b5
7a5bc73
51045c4
33b9112
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,6 +51,7 @@ import ( | |
"github.com/lightningnetwork/lnd/rpcperms" | ||
"github.com/lightningnetwork/lnd/signal" | ||
"github.com/lightningnetwork/lnd/sqldb" | ||
"github.com/lightningnetwork/lnd/sqldb/sqlc" | ||
"github.com/lightningnetwork/lnd/sweep" | ||
"github.com/lightningnetwork/lnd/walletunlocker" | ||
"github.com/lightningnetwork/lnd/watchtower" | ||
|
@@ -60,6 +61,16 @@ import ( | |
"gopkg.in/macaroon-bakery.v2/bakery" | ||
) | ||
|
||
const ( | ||
// invoiceMigrationBatchSize is the number of invoices that will be | ||
// migrated in a single batch. | ||
invoiceMigrationBatchSize = 1000 | ||
|
||
// invoiceMigration is the version of the migration that will be used to | ||
// migrate invoices from the kvdb to the sql database. | ||
invoiceMigration = 6 | ||
) | ||
|
||
// GrpcRegistrar is an interface that must be satisfied by an external subserver | ||
// that wants to be able to register its own gRPC server onto lnd's main | ||
// grpc.Server instance. | ||
|
@@ -1038,7 +1049,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase( | |
if err != nil { | ||
cleanUp() | ||
|
||
err := fmt.Errorf("unable to open graph DB: %w", err) | ||
err = fmt.Errorf("unable to open graph DB: %w", err) | ||
d.logger.Error(err) | ||
|
||
return nil, nil, err | ||
|
@@ -1072,65 +1083,69 @@ func (d *DefaultDatabaseBuilder) BuildDatabase( | |
case err != nil: | ||
cleanUp() | ||
|
||
err := fmt.Errorf("unable to open graph DB: %w", err) | ||
err = fmt.Errorf("unable to open graph DB: %w", err) | ||
d.logger.Error(err) | ||
return nil, nil, err | ||
} | ||
|
||
// Instantiate a native SQL invoice store if the flag is set. | ||
// Instantiate a native SQL store if the flag is set. | ||
if d.cfg.DB.UseNativeSQL { | ||
// We need to apply all migrations to the native SQL store | ||
// before we can use it. | ||
err := dbs.NativeSQLStore.ApplyAllMigrations( | ||
ctx, sqldb.GetMigrations(), | ||
) | ||
if err != nil { | ||
cleanUp() | ||
err := fmt.Errorf("unable to apply migrations: %w", err) | ||
d.logger.Error(err) | ||
|
||
return nil, nil, err | ||
} | ||
migrations := sqldb.GetMigrations() | ||
|
||
// If the user has not explicitly disabled the SQL invoice | ||
// migration, attach the custom migration function to invoice | ||
// migration (version 6). Even if this custom migration is | ||
// disabled, the regular native SQL store migrations will still | ||
// run. If the database version is already above this custom | ||
// migration's version (6), it will be skipped permanently, | ||
// regardless of the flag. | ||
if !d.cfg.DB.SkipSQLInvoiceMigration { | ||
migrationFn := func(tx *sqlc.Queries) error { | ||
return invoices.MigrateInvoicesToSQL( | ||
ctx, dbs.ChanStateDB.Backend, | ||
dbs.ChanStateDB, tx, | ||
invoiceMigrationBatchSize, | ||
) | ||
} | ||
|
||
// KV invoice db resides in the same database as the channel | ||
// state DB. Let's query the database to see if we have any | ||
// invoices there. If we do, we won't allow the user to start | ||
// lnd with native SQL enabled, as we don't currently migrate | ||
// the invoices to the new database schema. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dont we still want this check for anyone who has set There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and to protect against users who had a bbolt invoice store before? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don’t think it’s necessary, as this check was primarily intended to ensure that users with existing invoices in their database wouldn’t be able to start LND without the migration in place.
Since we don’t currently support mixed backends, the only scenario to consider is if the user is already using an SQL database but with the older KV schema. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah yes i see: if the user was pointing to a bbolt store and then changes config to sql store, there really isnt any way for us to know this so it is essentially a new node |
||
invoiceSlice, err := dbs.ChanStateDB.QueryInvoices( | ||
ctx, invoices.InvoiceQuery{ | ||
NumMaxInvoices: 1, | ||
}, | ||
) | ||
if err != nil { | ||
cleanUp() | ||
d.logger.Errorf("Unable to query KV invoice DB: %v", | ||
err) | ||
// Make sure we attach the custom migration function to | ||
// the correct migration version. | ||
for i := 0; i < len(migrations); i++ { | ||
if migrations[i].Version != invoiceMigration { | ||
continue | ||
} | ||
|
||
return nil, nil, err | ||
migrations[i].MigrationFn = migrationFn | ||
} | ||
} | ||
|
||
if len(invoiceSlice.Invoices) > 0 { | ||
// We need to apply all migrations to the native SQL store | ||
// before we can use it. | ||
err = dbs.NativeSQLStore.ApplyAllMigrations(ctx, migrations) | ||
if err != nil { | ||
cleanUp() | ||
err := fmt.Errorf("found invoices in the KV invoice " + | ||
"DB, migration to native SQL is not yet " + | ||
"supported") | ||
err = fmt.Errorf("faild to run migrations for the "+ | ||
"native SQL store: %w", err) | ||
d.logger.Error(err) | ||
|
||
return nil, nil, err | ||
} | ||
|
||
// With the DB ready and migrations applied, we can now create | ||
// the base DB and transaction executor for the native SQL | ||
// invoice store. | ||
baseDB := dbs.NativeSQLStore.GetBaseDB() | ||
executor := sqldb.NewTransactionExecutor( | ||
baseDB, | ||
func(tx *sql.Tx) invoices.SQLInvoiceQueries { | ||
baseDB, func(tx *sql.Tx) invoices.SQLInvoiceQueries { | ||
return baseDB.WithTx(tx) | ||
}, | ||
) | ||
|
||
dbs.InvoiceDB = invoices.NewSQLStore( | ||
sqlInvoiceDB := invoices.NewSQLStore( | ||
executor, clock.NewDefaultClock(), | ||
) | ||
|
||
dbs.InvoiceDB = sqlInvoiceDB | ||
} else { | ||
dbs.InvoiceDB = dbs.ChanStateDB | ||
} | ||
|
@@ -1143,7 +1158,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase( | |
if err != nil { | ||
cleanUp() | ||
|
||
err := fmt.Errorf("unable to open %s database: %w", | ||
err = fmt.Errorf("unable to open %s database: %w", | ||
lncfg.NSTowerClientDB, err) | ||
d.logger.Error(err) | ||
return nil, nil, err | ||
|
@@ -1158,7 +1173,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase( | |
if err != nil { | ||
cleanUp() | ||
|
||
err := fmt.Errorf("unable to open %s database: %w", | ||
err = fmt.Errorf("unable to open %s database: %w", | ||
lncfg.NSTowerServerDB, err) | ||
d.logger.Error(err) | ||
return nil, nil, err | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we sure we want to commit this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps it can be generated at runtime if we don't want to lug this blob around? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cc @bhandras - thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would it be difficult to inject in at runtime @bhandras |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm so if the user disables this, and we add a new migration in the future (version 7) he will not be able to migrate the invoice ?