fix: LND payments made externally from the hub are not visible#2183
fix: LND payments made externally from the hub are not visible#2183
Conversation
(cherry picked from commit bd0d660)
📝 WalkthroughWalkthroughTests and service logic updated to handle externally-made LND payments by creating transaction records instead of returning errors. Enables visibility of such payments in the hub's transaction list. Adds idempotency validation for repeated event processing. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@transactions/transactions_service.go`:
- Around line 857-889: The Find→Create race when inserting an outgoing
db.Transaction for lnClientTransaction.PaymentHash must be serialized: before
calling tx.Limit(1).Find(...) acquire a DB-level lock (e.g. Postgres advisory
lock via pg_advisory_xact_lock using a hash of lnClientTransaction.PaymentHash)
or otherwise ensure a unique constraint exists on outgoing payment_hash, then
perform the lookup and conditional tx.Create(&dbTransaction) while the lock is
held; reference the existing use of tx.Limit(1).Find(&dbTransaction,
&db.Transaction{Type: constants.TRANSACTION_TYPE_OUTGOING, PaymentHash:
lnClientTransaction.PaymentHash}) and tx.Create(&dbTransaction) to add the lock
acquisition and release (or add the DB migration to create a uniqueness
constraint on payment_hash for outgoing transactions) so concurrent workers
cannot both insert duplicates.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f5da7bf9-82b5-40ea-b511-16a7016d38a5
📒 Files selected for processing (2)
transactions/notifications_test.gotransactions/transactions_service.go
| result := tx.Limit(1).Find(&dbTransaction, &db.Transaction{ | ||
| Type: constants.TRANSACTION_TYPE_OUTGOING, | ||
| PaymentHash: lnClientTransaction.PaymentHash, | ||
| }) | ||
|
|
||
| if result.Error != nil { | ||
| return result.Error | ||
| } | ||
|
|
||
| if result.RowsAffected == 0 { | ||
| dbTransaction = db.Transaction{ | ||
| Type: constants.TRANSACTION_TYPE_OUTGOING, | ||
| State: constants.TRANSACTION_STATE_PENDING, | ||
| AmountMsat: uint64(lnClientTransaction.Amount), | ||
| FeeReserveMsat: 0, | ||
| PaymentRequest: lnClientTransaction.Invoice, | ||
| PaymentHash: lnClientTransaction.PaymentHash, | ||
| Description: lnClientTransaction.Description, | ||
| DescriptionHash: lnClientTransaction.DescriptionHash, | ||
| } | ||
|
|
||
| if lnClientTransaction.ExpiresAt != nil { | ||
| expiresAtValue := time.Unix(*lnClientTransaction.ExpiresAt, 0) | ||
| dbTransaction.ExpiresAt = &expiresAtValue | ||
| } | ||
|
|
||
| err := tx.Create(&dbTransaction).Error | ||
| if err != nil { | ||
| logger.Logger.WithFields(logrus.Fields{ | ||
| "payment_hash": lnClientTransaction.PaymentHash, | ||
| }).WithError(err).Error("Failed to create outgoing transaction") | ||
| return err | ||
| } |
There was a problem hiding this comment.
Serialize this fallback before inserting a new outgoing record.
This Find → Create path is still non-idempotent under concurrent nwc_lnclient_payment_sent delivery. Two workers can both observe “no rows”, both insert, and then either settle duplicate rows or leave one duplicate pending row behind. The schema in db/migrations/202407012100_transactions.go does not enforce uniqueness on outgoing payment_hash, so this is a real data-integrity gap.
Please guard the lookup/create sequence with a DB-level lock/advisory lock on the hash, or add a constraint that guarantees only one settled outgoing record per payment hash.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@transactions/transactions_service.go` around lines 857 - 889, The Find→Create
race when inserting an outgoing db.Transaction for
lnClientTransaction.PaymentHash must be serialized: before calling
tx.Limit(1).Find(...) acquire a DB-level lock (e.g. Postgres advisory lock via
pg_advisory_xact_lock using a hash of lnClientTransaction.PaymentHash) or
otherwise ensure a unique constraint exists on outgoing payment_hash, then
perform the lookup and conditional tx.Create(&dbTransaction) while the lock is
held; reference the existing use of tx.Limit(1).Find(&dbTransaction,
&db.Transaction{Type: constants.TRANSACTION_TYPE_OUTGOING, PaymentHash:
lnClientTransaction.PaymentHash}) and tx.Create(&dbTransaction) to add the lock
acquisition and release (or add the DB migration to create a uniqueness
constraint on payment_hash for outgoing transactions) so concurrent workers
cannot both insert duplicates.
fixes #2044
Summary by CodeRabbit