Skip to content

Commit a8b956a

Browse files
authored
Merge pull request #802 from Camillarhi/feat/tx-rebroadcast-fee-bumping-follow-up
Minor follow-ups to #628
2 parents 1cf1e6f + 6c0e4d4 commit a8b956a

File tree

2 files changed

+41
-43
lines changed

2 files changed

+41
-43
lines changed

src/wallet/mod.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,8 @@ impl Wallet {
388388
);
389389
let payment =
390390
self.payment_store.get(&payment_id).ok_or(Error::InvalidPaymentId)?;
391-
let pending_payment_details = self
392-
.create_pending_payment_from_tx(payment.clone(), conflict_txids.clone());
391+
let pending_payment_details =
392+
self.create_pending_payment_from_tx(payment, conflict_txids.clone());
393393

394394
self.pending_payment_store.insert_or_update(pending_payment_details)?;
395395
},
@@ -1200,7 +1200,10 @@ impl Wallet {
12001200

12011201
if let Some(replaced_details) = self
12021202
.pending_payment_store
1203-
.list_filter(|p| p.conflicting_txids.contains(&target_txid))
1203+
.list_filter(|p| {
1204+
matches!(p.details.kind, PaymentKind::Onchain { txid, .. } if txid == target_txid)
1205+
|| p.conflicting_txids.contains(&target_txid)
1206+
})
12041207
.first()
12051208
{
12061209
return Some(replaced_details.details.id);
@@ -1281,13 +1284,13 @@ impl Wallet {
12811284
old_fee_rate.to_sat_per_kwu() + INCREMENTAL_RELAY_FEE_SAT_PER_1000_WEIGHT as u64;
12821285

12831286
let confirmation_target = ConfirmationTarget::OnchainPayment;
1284-
let estimated_fee_rate =
1285-
fee_rate.unwrap_or_else(|| self.fee_estimator.estimate_fee_rate(confirmation_target));
1287+
let estimated_fee_rate = self.fee_estimator.estimate_fee_rate(confirmation_target);
12861288

12871289
// Use the higher of minimum RBF requirement or current network estimate
12881290
let final_fee_rate_sat_per_kwu =
12891291
min_required_fee_rate_sat_per_kwu.max(estimated_fee_rate.to_sat_per_kwu());
1290-
let final_fee_rate = FeeRate::from_sat_per_kwu(final_fee_rate_sat_per_kwu);
1292+
let final_fee_rate =
1293+
fee_rate.unwrap_or_else(|| FeeRate::from_sat_per_kwu(final_fee_rate_sat_per_kwu));
12911294

12921295
let mut psbt = {
12931296
let mut builder = locked_wallet.build_fee_bump(txid).map_err(|e| {
@@ -1312,6 +1315,17 @@ impl Wallet {
13121315
match builder.finish() {
13131316
Ok(psbt) => Ok(psbt),
13141317
Err(CreateTxError::FeeRateTooLow { required: required_fee_rate }) => {
1318+
if fee_rate.is_some() {
1319+
log_error!(
1320+
self.logger,
1321+
"Provided fee rate {} is too low for RBF fee bump of txid {}, required minimum fee rate: {}",
1322+
fee_rate.unwrap(),
1323+
txid,
1324+
required_fee_rate
1325+
);
1326+
return Err(Error::InvalidFeeRate);
1327+
}
1328+
13151329
log_info!(self.logger, "BDK requires higher fee rate: {}", required_fee_rate);
13161330

13171331
// BDK may require a higher fee rate than our estimate due to

tests/integration_tests_rust.rs

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2473,7 +2473,7 @@ async fn persistence_backwards_compatibility() {
24732473
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
24742474
async fn onchain_fee_bump_rbf() {
24752475
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
2476-
let chain_source = TestChainSource::Esplora(&electrsd);
2476+
let chain_source = random_chain_source(&bitcoind, &electrsd);
24772477
let (node_a, node_b) = setup_two_nodes(&chain_source, false, true, false);
24782478

24792479
// Fund both nodes
@@ -2497,6 +2497,10 @@ async fn onchain_fee_bump_rbf() {
24972497
let txid =
24982498
node_b.onchain_payment().send_to_address(&addr_a, amount_to_send_sats, None).unwrap();
24992499
wait_for_tx(&electrsd.client, txid).await;
2500+
// Give the chain source time to index the unconfirmed transaction before syncing.
2501+
// Without this, Esplora may not yet have the tx, causing sync to miss it and
2502+
// leaving the BDK wallet graph empty.
2503+
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
25002504
node_a.sync_wallets().unwrap();
25012505
node_b.sync_wallets().unwrap();
25022506

@@ -2522,10 +2526,10 @@ async fn onchain_fee_bump_rbf() {
25222526
// Successful fee bump
25232527
let new_txid = node_b.onchain_payment().bump_fee_rbf(payment_id, None).unwrap();
25242528
wait_for_tx(&electrsd.client, new_txid).await;
2525-
2526-
// Sleep to allow for transaction propagation
2529+
// Give the chain source time to index the unconfirmed transaction before syncing.
2530+
// Without this, Esplora may not yet have the tx, causing sync to miss it and
2531+
// leaving the BDK wallet graph empty.
25272532
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
2528-
25292533
node_a.sync_wallets().unwrap();
25302534
node_b.sync_wallets().unwrap();
25312535

@@ -2547,26 +2551,9 @@ async fn onchain_fee_bump_rbf() {
25472551
_ => panic!("Unexpected payment kind"),
25482552
}
25492553

2550-
// Verify node_a has the inbound payment txid updated to the replacement txid
2551-
let node_a_inbound_payment = node_a.payment(&payment_id).unwrap();
2552-
assert_eq!(node_a_inbound_payment.direction, PaymentDirection::Inbound);
2553-
match &node_a_inbound_payment.kind {
2554-
PaymentKind::Onchain { txid: inbound_txid, .. } => {
2555-
assert_eq!(
2556-
*inbound_txid, new_txid,
2557-
"node_a inbound payment txid should be updated to the replacement txid"
2558-
);
2559-
},
2560-
_ => panic!("Unexpected payment kind"),
2561-
}
2562-
25632554
// Multiple consecutive bumps
25642555
let second_bump_txid = node_b.onchain_payment().bump_fee_rbf(payment_id, None).unwrap();
25652556
wait_for_tx(&electrsd.client, second_bump_txid).await;
2566-
2567-
// Sleep to allow for transaction propagation
2568-
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
2569-
25702557
node_a.sync_wallets().unwrap();
25712558
node_b.sync_wallets().unwrap();
25722559

@@ -2586,19 +2573,6 @@ async fn onchain_fee_bump_rbf() {
25862573
_ => panic!("Unexpected payment kind"),
25872574
}
25882575

2589-
// Verify node_a has the inbound payment txid updated to the second replacement txid
2590-
let node_a_second_inbound_payment = node_a.payment(&payment_id).unwrap();
2591-
assert_eq!(node_a_second_inbound_payment.direction, PaymentDirection::Inbound);
2592-
match &node_a_second_inbound_payment.kind {
2593-
PaymentKind::Onchain { txid: inbound_txid, .. } => {
2594-
assert_eq!(
2595-
*inbound_txid, second_bump_txid,
2596-
"node_a inbound payment txid should be updated to the second replacement txid"
2597-
);
2598-
},
2599-
_ => panic!("Unexpected payment kind"),
2600-
}
2601-
26022576
// Confirm the transaction and try to bump again (should fail)
26032577
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6).await;
26042578
node_a.sync_wallets().unwrap();
@@ -2620,10 +2594,20 @@ async fn onchain_fee_bump_rbf() {
26202594
}
26212595

26222596
// Verify node A received the funds correctly
2623-
let node_a_received_payment = node_a.list_payments_with_filter(
2624-
|p| matches!(p.kind, PaymentKind::Onchain { txid, .. } if txid == second_bump_txid),
2625-
);
2597+
let node_a_received_payment = node_a.list_payments_with_filter(|p| {
2598+
p.id == payment_id && matches!(p.kind, PaymentKind::Onchain { .. })
2599+
});
2600+
26262601
assert_eq!(node_a_received_payment.len(), 1);
2602+
match &node_a_received_payment[0].kind {
2603+
PaymentKind::Onchain { txid: inbound_txid, .. } => {
2604+
assert_eq!(
2605+
*inbound_txid, second_bump_txid,
2606+
"node_a inbound payment txid should be updated to the second replacement txid"
2607+
);
2608+
},
2609+
_ => panic!("Unexpected payment kind"),
2610+
}
26272611
assert_eq!(node_a_received_payment[0].amount_msat, Some(amount_to_send_sats * 1000));
26282612
assert_eq!(node_a_received_payment[0].status, PaymentStatus::Succeeded);
26292613
}

0 commit comments

Comments
 (0)