diff --git a/payments/db/migration1/migration_validation.go b/payments/db/migration1/migration_validation.go index e97c3db40..e6f8bdd48 100644 --- a/payments/db/migration1/migration_validation.go +++ b/payments/db/migration1/migration_validation.go @@ -299,6 +299,17 @@ func normalizePaymentForCompare(payment *MPPayment) { htlc.circuit = nil htlc.cachedSessionKey = nil + // For legacy payments, the HTLC Hash field may be nil in the + // bbolt backend. During migration, the SQL code uses the + // parent payment hash as fallback. To ensure the comparison + // between bbolt and SQL data succeeds, we apply the same + // fallback here. + // + // See also: patchLegacyPaymentHash in payment_lifecycle.go. + if htlc.Hash == nil && payment.Info != nil { + htlc.Hash = &payment.Info.PaymentIdentifier + } + if len(htlc.Route.FirstHopWireCustomRecords) == 0 { htlc.Route.FirstHopWireCustomRecords = lnwire.CustomRecords{} diff --git a/payments/db/migration1/sql_migration.go b/payments/db/migration1/sql_migration.go index a7a02af5b..626b25a61 100644 --- a/payments/db/migration1/sql_migration.go +++ b/payments/db/migration1/sql_migration.go @@ -364,20 +364,23 @@ func migrateHTLCAttempt(ctx context.Context, paymentID int64, parentPaymentHash lntypes.Hash, htlc *HTLCAttempt, sqlDB SQLQueries, stats *MigrationStats) error { - // Validate that we have a payment hash for the attempt. + // Determine the payment hash for this HTLC attempt. // - // NOTE: We always require an attempt payment hash. A missing hash is an - // unrecoverable inconsistency. All payments should have a payment hash - // (AMP,MPP,Legacy) + // For AMP payments, each HTLC has its own unique hash. For non-AMP + // payments (MPP, Legacy), all HTLCs use the same hash as the parent + // payment. Older payment attempts may not have the hash stored + // explicitly, in which case we fall back to the parent payment hash + // which is ok since non-AMP payments have a single hash for all HTLCs. var paymentHash []byte switch { case htlc.Hash != nil: paymentHash = (*htlc.Hash)[:] default: - return fmt.Errorf("HTLC attempt %d missing payment hash "+ - "(parent payment hash=%x)", htlc.AttemptID, - parentPaymentHash[:]) + // For older payments where Hash is nil, use the parent payment + // hash. This is consistent with how the router handles these + // legacy payments. + paymentHash = parentPaymentHash[:] } firstHopAmountMsat := int64(htlc.Route.FirstHopAmount.Val.Int())