Skip to content

Commit cf78007

Browse files
jkczyzclaude
andcommitted
f - Keep a graduated funding payment terminal across wallet sync
Once ChannelReady graduates a funding payment to Succeeded (removing its pending record), a concurrent wallet-sync event for one of its candidates could re-stamp the old Pending status and revert the graduation. Treat a Succeeded on-chain payment as terminal during sync, refining only the confirmation status of the candidate that locked. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 88be9ce commit cf78007

1 file changed

Lines changed: 11 additions & 14 deletions

File tree

src/wallet/mod.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,24 +1433,21 @@ impl Wallet {
14331433
fn apply_funding_details_status_update(
14341434
&self, payment_id: PaymentId, event_txid: Txid, confirmation_status: ConfirmationStatus,
14351435
) -> Result<bool, Error> {
1436-
// `ChannelReady` may move the payment to the main store before wallet sync
1437-
// sees the tx confirm. In that case, update `kind` directly; recomputing from
1438-
// the wallet's view would overwrite the per-node fee set at broadcast time.
1436+
// A funding payment becomes `Succeeded` only once `handle_channel_ready` has graduated it
1437+
// on `ChannelReady`, which also removes the pending record. A wallet-sync event arriving
1438+
// during that removal (the two are awaited separately, so a sync can interleave) or after
1439+
// it must never downgrade the terminal status or adopt a replaced candidate's txid. At
1440+
// most it refines the confirmation status of the candidate that actually locked — and
1441+
// recomputing from the wallet's view would clobber the per-node fee set at broadcast time.
14391442
if let Some(mut existing) = self.payment_store.get(&payment_id) {
14401443
if existing.status == PaymentStatus::Succeeded
14411444
&& matches!(existing.kind, PaymentKind::Onchain { .. })
1442-
&& self.pending_payment_store.get(&payment_id).is_none()
14431445
{
1444-
let needs_update = match existing.kind {
1445-
PaymentKind::Onchain { txid, status } => {
1446-
txid != event_txid || status != confirmation_status
1447-
},
1448-
_ => false,
1449-
};
1450-
if needs_update {
1451-
existing.kind =
1452-
PaymentKind::Onchain { txid: event_txid, status: confirmation_status };
1453-
self.runtime.block_on(self.payment_store.insert_or_update(existing))?;
1446+
if let PaymentKind::Onchain { txid, status } = existing.kind {
1447+
if txid == event_txid && status != confirmation_status {
1448+
existing.kind = PaymentKind::Onchain { txid, status: confirmation_status };
1449+
self.runtime.block_on(self.payment_store.insert_or_update(existing))?;
1450+
}
14541451
}
14551452
return Ok(true);
14561453
}

0 commit comments

Comments
 (0)