1
2use anyhow::Context;
3use bitcoin::FeeRate;
4use log::warn;
5
6use crate::Wallet;
7use crate::exit::{Exit, ExitProgressStatus};
8use crate::onchain::{CpfpError, MakeCpfpFees};
9
10impl Exit {
11 pub async fn progress_exits_with_cpfp(
28 &self,
29 wallet: &Wallet,
30 fee_rate_override: Option<FeeRate>,
31 ) -> anyhow::Result<Option<Vec<ExitProgressStatus>>> {
32 let onchain_arc = wallet.inner.onchain.as_ref()
33 .context("no onchain wallet configured; cannot progress exits")?;
34
35 self.progress_exits(wallet).await?;
36
37 let fee_rate = fee_rate_override.unwrap_or(wallet.chain().fee_rates().await.fast);
38 for req in self.exits_needing_cpfp().await {
39 let fees = match req.rbf_requirement {
40 None => MakeCpfpFees::Effective(fee_rate),
41 Some(rbf) => {
42 if fee_rate <= rbf.min_fee_rate {
45 warn!(
46 "Skipping exit CPFP RBF: requested fee rate {} is not above current package rate {}",
47 fee_rate, rbf.min_fee_rate,
48 );
49 continue;
50 }
51 MakeCpfpFees::Rbf {
52 min_effective_fee_rate: fee_rate,
53 current_package_fee: rbf.current_package_fee,
54 }
55 },
56 };
57 let child_tx = {
58 let mut onchain = onchain_arc.write().await;
59 let tx = match onchain.make_signed_p2a_cpfp(&req.exit_tx, fees).await {
60 Ok(tx) => tx,
61 Err(CpfpError::InsufficientConfirmedFunds { needed, available }) => {
62 warn!("Insufficient funds for exit CPFP: needed {} available {}", needed, available);
63 continue;
64 },
65 Err(e) => return Err(e.into()),
66 };
67 onchain.store_signed_p2a_cpfp(&tx).await?;
68 tx
69 };
70 let exit_txid = req.exit_tx.compute_txid();
71 self.provide_cpfp_tx(wallet, exit_txid, child_tx).await?;
72 }
73
74 self.progress_exits(wallet).await
75 }
76}