Apply RBF replacements to the wallet before sync - #1124
ram0verflow wants to merge 1 commit into
Conversation
bump_fee_rbf updated the payment store but not the BDK wallet, so a second bump before sync failed with InvalidPaymentId (or panicked on debug). Apply the replacement to the wallet immediately, with a seen-at after the replaced round, and carry conflicting_txids across rounds. Fixes lightningdevkit#1117. AI assistance: OpenAI Codex, Claude Code.
|
👋 Thanks for assigning @jkczyz as a reviewer! |
| if let Some(previous) = self.pending_payment_store.get(&payment_id).await? { | ||
| conflict_txids.extend(previous.conflicting_txids); | ||
| } | ||
|
|
||
| conflict_txids.push(txid); | ||
| conflict_txids.sort_unstable(); | ||
| conflict_txids.dedup(); |
| .get(&payment_id) | ||
| .await? | ||
| .map(|p| p.conflicting_txids) | ||
| .unwrap_or_default(); |
There was a problem hiding this comment.
This is independent of #1117. A session of mine found this a little while ago, so I took the opportunity to clean it up. Could you base your PR on https://github.com/jkczyz/ldk-node/commits/2026-09-rbf-middle-round-conflict-list? Then you can drop this and the push/sort/dedup below.
Worth updating your commit's message to include something like:
Once the bump applies the replacement to the wallet, sync no longer emits TxReplaced for the replaced transaction (BDK derives events from a before/after diff of the canonical set), so nothing else populates conflicting_txids after a bump until a later eviction or confirmation flips the canonical set.
| locked_wallet.apply_unconfirmed_txs([( | ||
| fee_bumped_tx.clone(), | ||
| seen_at.max(previous_seen_at.saturating_add(1)), | ||
| )]); |
There was a problem hiding this comment.
Worth adding a one-line comment on why + 1 is needed.
Fixes #1117.
bump_fee_rbfwrote the replacement to the payment store but never applied it to the BDK wallet. A second bump before the next sync returnedInvalidPaymentId(release) or panicked on thedebug_assert!(debug).apply_unconfirmed_txsbeforetake_staged(), seen-atmax(now, previous_last_seen + 1).conflicting_txidsacross rounds inbump_fee_rbfand theTxReplacedhandler. The pending record is read before the persister/wallet locks.Testing:
onchain_fee_bump_rbf_twice_before_sync: fails onmain, passes with this change.onchain_fee_bump_rbfandonchain_fee_bump_rbf_respects_anchor_reservepass.cargo fmt --checkclean; no new clippy warnings.AI assistance: OpenAI Codex, Claude Code.