Copy the core payments/db code into payments/db/migration1 and add the required sqlc-generated types/queries from sqldb/sqlc. This effectively freezes the migration code so it stays robust against future query or schema changes in the main payments package. Replace the delegation to channeldb.ReadElement/WriteElement with self-contained, frozen implementations that only handle the exact types required by this migration package. This removes the dependency on the live channeldb codec so that future changes to channeldb serialization cannot silently corrupt or break the migration. UnknownElementType is also defined locally for the same reason.
141 lines
5.3 KiB
Go
141 lines
5.3 KiB
Go
package migration1
|
|
|
|
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(ctx context.Context,
|
|
paymentHash lntypes.Hash) (*MPPayment, error)
|
|
|
|
// FetchInFlightPayments returns all payments with status InFlight.
|
|
FetchInFlightPayments(ctx context.Context) ([]*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(ctx context.Context, paymentHash lntypes.Hash,
|
|
failedAttemptsOnly bool) error
|
|
|
|
// DeletePayments deletes all payments from the DB given the specified
|
|
// flags.
|
|
DeletePayments(ctx context.Context, 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(context.Context, lntypes.Hash, *PaymentCreationInfo) error
|
|
|
|
// RegisterAttempt atomically records the provided HTLCAttemptInfo.
|
|
//
|
|
// IMPORTANT: Callers MUST serialize calls to RegisterAttempt for the
|
|
// same payment hash. Concurrent calls will result in race conditions
|
|
// where both calls read the same initial payment state, validate
|
|
// against stale data, and could cause overpayment. For example:
|
|
// - Both goroutines fetch payment with 400 sats sent
|
|
// - Both validate sending 650 sats won't overpay (within limit)
|
|
// - Both commit successfully
|
|
// - Result: 1700 sats sent, exceeding the payment amount
|
|
// The payment router/controller layer is responsible for ensuring
|
|
// serialized access per payment hash.
|
|
RegisterAttempt(context.Context, 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(context.Context, lntypes.Hash, uint64,
|
|
*HTLCSettleInfo) (*MPPayment, error)
|
|
|
|
// FailAttempt marks the given payment attempt failed.
|
|
FailAttempt(context.Context, 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(context.Context, 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(context.Context, lntypes.Hash) error
|
|
}
|
|
|
|
// DBMPPayment is an interface that represents the payment state during a
|
|
// payment lifecycle.
|
|
type DBMPPayment interface {
|
|
// GetState returns the current state of the payment.
|
|
GetState() *MPPaymentState
|
|
|
|
// Terminated returns true if the payment is in a final state.
|
|
Terminated() bool
|
|
|
|
// GetStatus returns the current status of the payment.
|
|
GetStatus() PaymentStatus
|
|
|
|
// NeedWaitAttempts specifies whether the payment needs to wait for the
|
|
// outcome of an attempt.
|
|
NeedWaitAttempts() (bool, error)
|
|
|
|
// GetHTLCs returns all HTLCs of this payment.
|
|
GetHTLCs() []HTLCAttempt
|
|
|
|
// InFlightHTLCs returns all HTLCs that are in flight.
|
|
InFlightHTLCs() []HTLCAttempt
|
|
|
|
// AllowMoreAttempts is used to decide whether we can safely attempt
|
|
// more HTLCs for a given payment state. Return an error if the payment
|
|
// is in an unexpected state.
|
|
AllowMoreAttempts() (bool, error)
|
|
|
|
// TerminalInfo returns the settled HTLC attempt or the payment's
|
|
// failure reason.
|
|
TerminalInfo() (*HTLCAttempt, *FailureReason)
|
|
}
|