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
2 changes: 2 additions & 0 deletions docs/release-notes/release-notes-0.21.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
database](https://github.com/lightningnetwork/lnd/pull/9147)
* Implement query methods (QueryPayments,FetchPayment) for the [payments db
SQL Backend](https://github.com/lightningnetwork/lnd/pull/10287)
* Implement insert methods for the [payments db
SQL Backend](https://github.com/lightningnetwork/lnd/pull/10291)

## Code Health

Expand Down
5 changes: 5 additions & 0 deletions payments/db/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ var (
// paths or vice versa.
ErrMixedBlindedAndNonBlindedPayments = errors.New("mixed blinded and " +
"non-blinded payments")
// ErrBlindedPaymentMissingTotalAmount is returned if we try to
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: new line above

// register a blinded payment attempt where the final hop doesn't set
// the total amount.
ErrBlindedPaymentMissingTotalAmount = errors.New("blinded payment " +
"final hop must set total amount")

// ErrMPPPaymentAddrMismatch is returned if we try to register an MPP
// shard where the payment address doesn't match existing shards.
Expand Down
11 changes: 11 additions & 0 deletions payments/db/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ type PaymentControl interface {
InitPayment(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(lntypes.Hash, *HTLCAttemptInfo) (*MPPayment, error)

// SettleAttempt marks the given attempt settled with the preimage. If
Expand Down
2 changes: 2 additions & 0 deletions payments/db/kv_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ func (p *KVStore) InitPayment(paymentHash lntypes.Hash,
// DeleteFailedAttempts deletes all failed htlcs for a payment if configured
// by the KVStore db.
func (p *KVStore) DeleteFailedAttempts(hash lntypes.Hash) error {
// TODO(ziggie): Refactor to not mix application logic with database
// logic. This decision should be made in the application layer.
if !p.keepFailedPaymentAttempts {
const failedHtlcsOnly = true
err := p.DeletePayment(hash, failedHtlcsOnly)
Expand Down
7 changes: 7 additions & 0 deletions payments/db/payment.go
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,13 @@ func verifyAttempt(payment *MPPayment, attempt *HTLCAttemptInfo) error {
// in the split payment is correct.
isBlinded := len(attempt.Route.FinalHop().EncryptedData) != 0

// For blinded payments, the last hop must set the total amount.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something we should cover in a unit test?

if isBlinded {
if attempt.Route.FinalHop().TotalAmtMsat == 0 {
return ErrBlindedPaymentMissingTotalAmount
}
}

// Make sure any existing shards match the new one with regards
// to MPP options.
mpp := attempt.Route.FinalHop().MPP
Expand Down
Loading
Loading