Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions config_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ import (
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/msgmux"
paymentsdb "github.com/lightningnetwork/lnd/payments/db"
paymentsmig1 "github.com/lightningnetwork/lnd/payments/db/migration1"
paymentsmig1sqlc "github.com/lightningnetwork/lnd/payments/db/migration1/sqlc"
"github.com/lightningnetwork/lnd/rpcperms"
"github.com/lightningnetwork/lnd/signal"
"github.com/lightningnetwork/lnd/sqldb"
Expand All @@ -76,6 +78,10 @@ const (
// graphMigration is the version number for the graph migration
// that migrates the KV graph to the native SQL schema.
graphMigration = 10

// paymentMigration is the version number for the payments migration
// that migrates KV payments to the native SQL schema.
paymentMigration = 12
)

// GrpcRegistrar is an interface that must be satisfied by an external subserver
Expand Down Expand Up @@ -1153,6 +1159,34 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
return nil
}

//nolint:ll
paymentMig := func(tx *sqlc.Queries) error {
err := paymentsmig1.MigratePaymentsKVToSQL(
ctx,
dbs.ChanStateDB.Backend,
paymentsmig1sqlc.New(tx.GetTx()),
&paymentsmig1.SQLStoreConfig{
QueryCfg: queryCfg,
SkipMigrationValidation: cfg.DB.
SkipPaymentsMigrationValidation,
},
)
if err != nil {
return fmt.Errorf("failed to migrate "+
"payments to SQL: %w", err)
}

// Set the payments bucket tombstone to
// indicate that the migration has been
// completed.
d.logger.Debugf("Setting payments bucket " +
"tombstone")

return paymentsdb.SetPaymentsBucketTombstone(
dbs.ChanStateDB.Backend,
)
}

// Make sure we attach the custom migration function to
// the correct migration version.
for i := 0; i < len(migrations); i++ {
Expand All @@ -1162,11 +1196,17 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
migrations[i].MigrationFn = invoiceMig

continue

case graphMigration:
migrations[i].MigrationFn = graphMig

continue

case paymentMigration:
migrations[i].MigrationFn = paymentMig

continue

default:
}

Expand Down Expand Up @@ -1265,6 +1305,27 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
return nil, nil, err
}

// Check if the payments bucket tombstone is set. If it is, we
// need to return and ask the user switch back to using the
// native SQL store.
ripPayments, err := paymentsdb.GetPaymentsBucketTombstone(
dbs.ChanStateDB.Backend,
)
if err != nil {
err = fmt.Errorf("unable to check payments bucket "+
"tombstone: %w", err)
d.logger.Error(err)

return nil, nil, err
}
if ripPayments {
err = fmt.Errorf("payments bucket tombstoned, please " +
"switch back to native SQL")
d.logger.Error(err)

return nil, nil, err
}

dbs.InvoiceDB = dbs.ChanStateDB

graphStore, err = graphdb.NewKVStore(
Expand Down
15 changes: 15 additions & 0 deletions docs/release-notes/release-notes-0.21.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@

## Deprecations

### ⚠️ **Warning:** Deprecated fields in `lnrpc.Hop` will be removed in release version **0.22**

The following deprecated fields in the [`lnrpc.Hop`](https://lightning.engineering/api-docs/api/lnd/lightning/send-to-route-sync/#lnrpchop)
message will be removed:

| Field | Deprecated Since | Replacement |
|-------|------------------|-------------|
| `chan_capacity` | 0.7.1 | None |
| `amt_to_forward` | 0.7.1 | `amt_to_forward_msat` |
| `fee` | 0.7.1 | `fee_msat` |

### ⚠️ **Warning:** The deprecated fee rate option `--sat_per_byte` will be removed in release version **0.22**

The deprecated `--sat_per_byte` option will be fully removed. This flag was
Expand Down Expand Up @@ -184,6 +195,10 @@
db functions Part 2](https://github.com/lightningnetwork/lnd/pull/10308)
* [Finalize SQL implementation for
payments db](https://github.com/lightningnetwork/lnd/pull/10373)
* [Add the KV-to-SQL payment
migration](https://github.com/lightningnetwork/lnd/pull/10485) with
comprehensive tests and build tag "test_native_sql" gated wiring into the
payment flow.


## Code Health
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ require (
github.com/opencontainers/runc v1.1.14 // indirect
github.com/ory/dockertest/v3 v3.10.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.26.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
Expand Down
7 changes: 5 additions & 2 deletions lncfg/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ type DB struct {

SkipNativeSQLMigration bool `long:"skip-native-sql-migration" description:"If set to true, the KV to native SQL migration will be skipped. Note that this option is intended for users who experience non-resolvable migration errors. Enabling after there is a non-resolvable migration error that resulted in an incomplete migration will cause that partial migration to be abandoned and ignored and an empty database will be used instead. Since invoices are currently the only native SQL database used, our channels will still work but the invoice history will be forgotten. This option has no effect if native SQL is not in use (db.use-native-sql=false)."`

SkipPaymentsMigrationValidation bool `long:"skip-payments-migration-validation" description:"If set to true, the KV to native SQL payments migration will skip its in-migration validation step. This can be used if validation is too slow for large databases."`

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."`

PruneRevocation bool `long:"prune-revocation" description:"Run the optional migration that prunes the revocation logs to save disk space."`
Expand Down Expand Up @@ -130,8 +132,9 @@ func DefaultDB() *DB {
BusyTimeout: defaultSqliteBusyTimeout,
QueryConfig: *sqldb.DefaultSQLiteConfig(),
},
UseNativeSQL: false,
SkipNativeSQLMigration: false,
UseNativeSQL: false,
SkipNativeSQLMigration: false,
SkipPaymentsMigrationValidation: false,
}
}

Expand Down
14 changes: 2 additions & 12 deletions lnrpc/routerrpc/router_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -651,20 +651,11 @@ func (r *RouterBackend) MarshallRoute(route *route.Route) (*lnrpc.Route, error)
}
}

incomingAmt := route.TotalAmount
for i, hop := range route.Hops {
fee := route.HopFee(i)

// Channel capacity is not a defining property of a route. For
// backwards RPC compatibility, we retrieve it here from the
// graph.
chanCapacity, err := r.FetchChannelCapacity(hop.ChannelID)
if err != nil {
// If capacity cannot be retrieved, this may be a
// not-yet-received or private channel. Then report
// amount that is sent through the channel as capacity.
chanCapacity = incomingAmt.ToSatoshis()
}
// Leave capacity unset (zero) to avoid per-hop graph lookups.
var chanCapacity btcutil.Amount

// Extract the MPP fields if present on this hop.
var mpp *lnrpc.MPPRecord
Expand Down Expand Up @@ -713,7 +704,6 @@ func (r *RouterBackend) MarshallRoute(route *route.Route) (*lnrpc.Route, error)
blinding := hop.BlindingPoint.SerializeCompressed()
resp.Hops[i].BlindingPoint = blinding
}
incomingAmt = hop.AmtToForward
}

return resp, nil
Expand Down
71 changes: 71 additions & 0 deletions payments/db/kv_tombstone.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package paymentsdb

import (
"fmt"

"github.com/lightningnetwork/lnd/kvdb"
)

var (
// paymentsBucketTombstone is the key used to mark the payments bucket
// as permanently closed after a successful migration.
paymentsBucketTombstone = []byte("payments-tombstone")
)

// SetPaymentsBucketTombstone sets the tombstone key in the payments bucket to
// mark the bucket as permanently closed. This prevents it from being reopened
// in the future.
func SetPaymentsBucketTombstone(db kvdb.Backend) error {
return kvdb.Update(db, func(tx kvdb.RwTx) error {
// Access the top-level payments bucket.
payments := tx.ReadWriteBucket(paymentsRootBucket)

// In case the bucket doesn't exist, because we start
// immediately with the native SQL schema, we create it as well
// to make sure the user cannot switch back to the KV store.
if payments == nil {
var err error
payments, err = tx.CreateTopLevelBucket(
paymentsRootBucket,
)
if err != nil {
return fmt.Errorf("failed to create payments "+
"bucket: %w", err)
}
}

// Add the tombstone key to the payments bucket.
err := payments.Put(paymentsBucketTombstone, []byte("1"))
if err != nil {
return fmt.Errorf("failed to set tombstone: %w", err)
}

return nil
}, func() {})
}

// GetPaymentsBucketTombstone checks if the tombstone key exists in the payments
// bucket. It returns true if the tombstone is present and false otherwise.
func GetPaymentsBucketTombstone(db kvdb.Backend) (bool, error) {
var tombstoneExists bool

err := kvdb.View(db, func(tx kvdb.RTx) error {
// Access the top-level payments bucket.
payments := tx.ReadBucket(paymentsRootBucket)
if payments == nil {
tombstoneExists = false
return nil
}

// Check if the tombstone key exists.
tombstone := payments.Get(paymentsBucketTombstone)
tombstoneExists = tombstone != nil

return nil
}, func() {})
if err != nil {
return false, err
}

return tombstoneExists, nil
}
2 changes: 2 additions & 0 deletions payments/db/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package paymentsdb
import (
"github.com/btcsuite/btclog/v2"
"github.com/lightningnetwork/lnd/build"
paymentsmig1 "github.com/lightningnetwork/lnd/payments/db/migration1"
)

// log is a logger that is initialized with no output filters. This
Expand All @@ -29,4 +30,5 @@ func DisableLog() {
// using btclog.
func UseLogger(logger btclog.Logger) {
log = logger
paymentsmig1.UseLogger(logger)
}
Loading
Loading