multi: introduce interface for payment database
This commit is contained in:
5 files changed
+103
-14
No files matched your search
+3
-3
@@ -925,9 +925,9 @@ type DatabaseInstances struct {
|
|||||||
// InvoiceDB is the database that stores information about invoices.
|
// InvoiceDB is the database that stores information about invoices.
|
||||||
InvoiceDB invoices.InvoiceDB
|
InvoiceDB invoices.InvoiceDB
|
||||||
|
|
||||||
// KVPaymentsDB is the database that stores all payment related
|
// PaymentsDB is the database that stores all payment related
|
||||||
// information.
|
// information.
|
||||||
KVPaymentsDB *paymentsdb.KVPaymentsDB
|
PaymentsDB paymentsdb.DB
|
||||||
|
|
||||||
// MacaroonDB is the database that stores macaroon root keys.
|
// MacaroonDB is the database that stores macaroon root keys.
|
||||||
MacaroonDB kvdb.Backend
|
MacaroonDB kvdb.Backend
|
||||||
@@ -1237,7 +1237,7 @@ func (d *DefaultDatabaseBuilder) BuildDatabase(
|
|||||||
|
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
dbs.KVPaymentsDB = kvPaymentsDB
|
dbs.PaymentsDB = kvPaymentsDB
|
||||||
|
|
||||||
// Wrap the watchtower client DB and make sure we clean up.
|
// Wrap the watchtower client DB and make sure we clean up.
|
||||||
if cfg.WtClient.Active {
|
if cfg.WtClient.Active {
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package paymentsdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DB represents the interface to the underlying payments database.
|
||||||
|
type DB interface {
|
||||||
|
PaymentReader
|
||||||
|
PaymentWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
// PaymentReader represents the interface to read operations from the payments
|
||||||
|
// database.
|
||||||
|
type PaymentReader interface {
|
||||||
|
// QueryPayments queries the payments database and should support
|
||||||
|
// pagination.
|
||||||
|
QueryPayments(ctx context.Context, query Query) (Response, error)
|
||||||
|
|
||||||
|
// FetchPayment fetches the payment corresponding to the given payment
|
||||||
|
// hash.
|
||||||
|
FetchPayment(paymentHash lntypes.Hash) (*MPPayment, error)
|
||||||
|
|
||||||
|
// FetchInFlightPayments returns all payments with status InFlight.
|
||||||
|
FetchInFlightPayments() ([]*MPPayment, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PaymentWriter represents the interface to write operations to the payments
|
||||||
|
// database.
|
||||||
|
type PaymentWriter interface {
|
||||||
|
// DeletePayment deletes a payment from the DB given its payment hash.
|
||||||
|
DeletePayment(paymentHash lntypes.Hash, failedAttemptsOnly bool) error
|
||||||
|
|
||||||
|
// DeletePayments deletes all payments from the DB given the specified
|
||||||
|
// flags.
|
||||||
|
DeletePayments(failedOnly, failedAttemptsOnly bool) (int, error)
|
||||||
|
|
||||||
|
PaymentControl
|
||||||
|
}
|
||||||
|
|
||||||
|
// PaymentControl represents the interface to control the payment lifecycle and
|
||||||
|
// its database operations. This interface represents the control flow of how
|
||||||
|
// a payment should be handled in the database. They are not just writing
|
||||||
|
// operations but they inherently represent the flow of a payment. The methods
|
||||||
|
// are called in the following order:
|
||||||
|
//
|
||||||
|
// 1. InitPayment
|
||||||
|
// 2. RegisterAttempt (a payment can have multiple attempts)
|
||||||
|
// 3. SettleAttempt or FailAttempt (attempts can also fail as long as the
|
||||||
|
// sending amount will be eventually settled).
|
||||||
|
// 4. Payment succeeds or "Fail" is called.
|
||||||
|
// 5. DeleteFailedAttempts is called which will delete all failed attempts
|
||||||
|
// for a payment to clean up the database.
|
||||||
|
type PaymentControl interface {
|
||||||
|
// InitPayment checks that no other payment with the same payment hash
|
||||||
|
// exists in the database before creating a new payment. However, it
|
||||||
|
// should allow the user making a subsequent payment if the payment is
|
||||||
|
// in a Failed state.
|
||||||
|
InitPayment(lntypes.Hash, *PaymentCreationInfo) error
|
||||||
|
|
||||||
|
// RegisterAttempt atomically records the provided HTLCAttemptInfo.
|
||||||
|
RegisterAttempt(lntypes.Hash, *HTLCAttemptInfo) (*MPPayment, error)
|
||||||
|
|
||||||
|
// SettleAttempt marks the given attempt settled with the preimage. If
|
||||||
|
// this is a multi shard payment, this might implicitly mean the
|
||||||
|
// full payment succeeded.
|
||||||
|
//
|
||||||
|
// After invoking this method, InitPayment should always return an
|
||||||
|
// error to prevent us from making duplicate payments to the same
|
||||||
|
// payment hash. The provided preimage is atomically saved to the DB
|
||||||
|
// for record keeping.
|
||||||
|
SettleAttempt(lntypes.Hash, uint64, *HTLCSettleInfo) (*MPPayment, error)
|
||||||
|
|
||||||
|
// FailAttempt marks the given payment attempt failed.
|
||||||
|
FailAttempt(lntypes.Hash, uint64, *HTLCFailInfo) (*MPPayment, error)
|
||||||
|
|
||||||
|
// Fail transitions a payment into the Failed state, and records
|
||||||
|
// the ultimate reason the payment failed. Note that this should only
|
||||||
|
// be called when all active attempts are already failed. After
|
||||||
|
// invoking this method, InitPayment should return nil on its next call
|
||||||
|
// for this payment hash, allowing the user to make a subsequent
|
||||||
|
// payment.
|
||||||
|
Fail(lntypes.Hash, FailureReason) (*MPPayment, error)
|
||||||
|
|
||||||
|
// DeleteFailedAttempts removes all failed HTLCs from the db. It should
|
||||||
|
// be called for a given payment whenever all inflight htlcs are
|
||||||
|
// completed, and the payment has reached a final terminal state.
|
||||||
|
DeleteFailedAttempts(lntypes.Hash) error
|
||||||
|
}
|
||||||
@@ -151,7 +151,7 @@ func (s *controlTowerSubscriberImpl) Updates() <-chan interface{} {
|
|||||||
// controlTower is persistent implementation of ControlTower to restrict
|
// controlTower is persistent implementation of ControlTower to restrict
|
||||||
// double payment sending.
|
// double payment sending.
|
||||||
type controlTower struct {
|
type controlTower struct {
|
||||||
db *paymentsdb.KVPaymentsDB
|
db paymentsdb.DB
|
||||||
|
|
||||||
// subscriberIndex is used to provide a unique id for each subscriber
|
// subscriberIndex is used to provide a unique id for each subscriber
|
||||||
// to all payments. This is used to easily remove the subscriber when
|
// to all payments. This is used to easily remove the subscriber when
|
||||||
@@ -168,7 +168,7 @@ type controlTower struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewControlTower creates a new instance of the controlTower.
|
// NewControlTower creates a new instance of the controlTower.
|
||||||
func NewControlTower(db *paymentsdb.KVPaymentsDB) ControlTower {
|
func NewControlTower(db paymentsdb.DB) ControlTower {
|
||||||
return &controlTower{
|
return &controlTower{
|
||||||
db: db,
|
db: db,
|
||||||
subscribersAllPayments: make(
|
subscribersAllPayments: make(
|
||||||
|
|||||||
+3
-3
@@ -7529,7 +7529,7 @@ func (r *rpcServer) ListPayments(ctx context.Context,
|
|||||||
query.MaxPayments = math.MaxUint64
|
query.MaxPayments = math.MaxUint64
|
||||||
}
|
}
|
||||||
|
|
||||||
paymentsQuerySlice, err := r.server.kvPaymentsDB.QueryPayments(
|
paymentsQuerySlice, err := r.server.paymentsDB.QueryPayments(
|
||||||
ctx, query,
|
ctx, query,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -7612,7 +7612,7 @@ func (r *rpcServer) DeletePayment(ctx context.Context,
|
|||||||
rpcsLog.Infof("[DeletePayment] payment_identifier=%v, "+
|
rpcsLog.Infof("[DeletePayment] payment_identifier=%v, "+
|
||||||
"failed_htlcs_only=%v", hash, req.FailedHtlcsOnly)
|
"failed_htlcs_only=%v", hash, req.FailedHtlcsOnly)
|
||||||
|
|
||||||
err = r.server.kvPaymentsDB.DeletePayment(hash, req.FailedHtlcsOnly)
|
err = r.server.paymentsDB.DeletePayment(hash, req.FailedHtlcsOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -7652,7 +7652,7 @@ func (r *rpcServer) DeleteAllPayments(ctx context.Context,
|
|||||||
"failed_htlcs_only=%v", req.FailedPaymentsOnly,
|
"failed_htlcs_only=%v", req.FailedPaymentsOnly,
|
||||||
req.FailedHtlcsOnly)
|
req.FailedHtlcsOnly)
|
||||||
|
|
||||||
numDeletedPayments, err := r.server.kvPaymentsDB.DeletePayments(
|
numDeletedPayments, err := r.server.paymentsDB.DeletePayments(
|
||||||
req.FailedPaymentsOnly, req.FailedHtlcsOnly,
|
req.FailedPaymentsOnly, req.FailedHtlcsOnly,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -336,11 +336,9 @@ type server struct {
|
|||||||
|
|
||||||
invoicesDB invoices.InvoiceDB
|
invoicesDB invoices.InvoiceDB
|
||||||
|
|
||||||
// kvPaymentsDB is the DB that contains all functions for managing
|
// paymentsDB is the DB that contains all functions for managing
|
||||||
// payments.
|
// payments.
|
||||||
//
|
paymentsDB paymentsdb.DB
|
||||||
// TODO(ziggie): Replace with interface.
|
|
||||||
kvPaymentsDB *paymentsdb.KVPaymentsDB
|
|
||||||
|
|
||||||
aliasMgr *aliasmgr.Manager
|
aliasMgr *aliasmgr.Manager
|
||||||
|
|
||||||
@@ -683,7 +681,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr,
|
|||||||
addrSource: addrSource,
|
addrSource: addrSource,
|
||||||
miscDB: dbs.ChanStateDB,
|
miscDB: dbs.ChanStateDB,
|
||||||
invoicesDB: dbs.InvoiceDB,
|
invoicesDB: dbs.InvoiceDB,
|
||||||
kvPaymentsDB: dbs.KVPaymentsDB,
|
paymentsDB: dbs.PaymentsDB,
|
||||||
cc: cc,
|
cc: cc,
|
||||||
sigPool: lnwallet.NewSigPool(cfg.Workers.Sig, cc.Signer),
|
sigPool: lnwallet.NewSigPool(cfg.Workers.Sig, cc.Signer),
|
||||||
writePool: writePool,
|
writePool: writePool,
|
||||||
@@ -1007,7 +1005,7 @@ func newServer(ctx context.Context, cfg *Config, listenAddrs []net.Addr,
|
|||||||
PathFindingConfig: pathFindingConfig,
|
PathFindingConfig: pathFindingConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.controlTower = routing.NewControlTower(dbs.KVPaymentsDB)
|
s.controlTower = routing.NewControlTower(dbs.PaymentsDB)
|
||||||
|
|
||||||
strictPruning := cfg.Bitcoin.Node == "neutrino" ||
|
strictPruning := cfg.Bitcoin.Node == "neutrino" ||
|
||||||
cfg.Routing.StrictZombiePruning
|
cfg.Routing.StrictZombiePruning
|
||||||
|
|||||||
Reference in new issue
Block a user