clementine_core/tx_sender/
cpfp.rs

1//! # Child Pays For Parent (CPFP) Support For Transaction Sender
2//!
3//! This module implements the Child Pays For Parent (CPFP) strategy for sending
4//! Bitcoin transactions with transaction sender.
5//!
6//! ## Child Transaction Details
7//!
8//! A child transaction is created to pay for the fees of a parent transaction.
9//! They must be submitted together as a package for Bitcoin nodes to accept
10//! them.
11//!
12//! ### Fee Payer Transactions/UTXOs
13//!
14//! Child transaction needs to spend an UTXO for the fees. But because of the
15//! TRUC rules (https://github.com/bitcoin/bips/blob/master/bip-0431.mediawiki#specification),
16//! a third transaction can't be put into the package. So, a so called "fee
17//! payer" transaction must be send and confirmed before the CPFP package is
18//! send.
19
20use super::{Result, SendTxError, TxMetadata, TxSender};
21use crate::constants::NON_STANDARD_V3;
22use crate::errors::{ErrorExt, ResultExt};
23use crate::extended_bitcoin_rpc::BitcoinRPCError;
24use crate::utils::FeePayingType;
25use crate::{
26    builder::{
27        self,
28        script::SpendPath,
29        transaction::{
30            input::SpendableTxIn, output::UnspentTxOut, TransactionType, TxHandlerBuilder,
31            DEFAULT_SEQUENCE,
32        },
33    },
34    constants::MIN_TAPROOT_AMOUNT,
35    rpc::clementine::NormalSignatureKind,
36};
37use bitcoin::{Amount, FeeRate, OutPoint, Transaction, TxOut, Weight};
38use bitcoincore_rpc::PackageSubmissionResult;
39use bitcoincore_rpc::{PackageTransactionResult, RpcApi};
40use eyre::eyre;
41use eyre::Context;
42use std::collections::HashSet;
43use std::env;
44
45impl TxSender {
46    /// Creates and broadcasts a new "fee payer" UTXO to be used for CPFP
47    /// transactions.
48    ///
49    /// This function is called when a CPFP attempt fails due to insufficient funds
50    /// in the existing confirmed fee payer UTXOs associated with a transaction (`bumped_id`).
51    /// It calculates the required fee based on the parent transaction (`tx`) and the current
52    /// `fee_rate`, adding a buffer (2x required fee + dust limit) to handle potential fee spikes.
53    /// It then sends funds to the `TxSender`'s own signer address using the RPC's
54    /// `send_to_address` and saves the resulting UTXO information (`outpoint`, `amount`)
55    /// to the database, linking it to the `bumped_id`.
56    ///
57    /// # Arguments
58    /// * `bumped_id` - The database ID of the parent transaction requiring the fee bump.
59    /// * `tx` - The parent transaction itself.
60    /// * `fee_rate` - The target fee rate for the CPFP package.
61    /// * `total_fee_payer_amount` - The sum of amounts in currently available confirmed fee payer UTXOs.
62    /// * `fee_payer_utxos_len` - The number of currently available confirmed fee payer UTXOs.
63    async fn create_fee_payer_utxo(
64        &self,
65        bumped_id: u32,
66        tx: &Transaction,
67        fee_rate: FeeRate,
68        total_fee_payer_amount: Amount,
69        fee_payer_utxos_len: usize,
70    ) -> Result<()> {
71        tracing::debug!(
72            "Creating fee payer UTXO for txid {} with bump id {}",
73            &tx.compute_txid().to_string(),
74            bumped_id
75        );
76        let required_fee = Self::calculate_required_fee(
77            tx.weight(),
78            fee_payer_utxos_len + 1,
79            fee_rate,
80            FeePayingType::CPFP,
81        )?;
82
83        // Aggressively add 2x required fee to the total amount to account for sudden spikes
84        // We won't actually use 2x fees, but the fee payer utxo will hold that much amount so that while fee payer utxo gets mined
85        // if fees increase the utxo should still be sufficient to fund the tx with high probability
86        // leftover fees will get sent back to wallet with a change output in fn create_child_tx
87        let new_total_fee_needed = required_fee
88            .checked_mul(2)
89            .and_then(|fee| fee.checked_add(MIN_TAPROOT_AMOUNT));
90        if new_total_fee_needed.is_none() {
91            return Err(eyre!("Total fee needed is too large, required fee: {}, total fee payer amount: {}, fee rate: {}", required_fee, total_fee_payer_amount, fee_rate).into());
92        }
93        let new_fee_payer_amount =
94            new_total_fee_needed.and_then(|fee| fee.checked_sub(total_fee_payer_amount));
95
96        let new_fee_payer_amount = match new_fee_payer_amount {
97            Some(fee) => fee,
98            // if underflow, no new fee payer utxo is needed, log it anyway in case its a bug
99            None => {
100                tracing::debug!("create_fee_payer_utxo was called but no new fee payer utxo is needed for tx: {:?}, required fee: {}, total fee payer amount: {}, current fee rate: {}", tx, required_fee, total_fee_payer_amount, fee_rate);
101                return Ok(());
102            }
103        };
104
105        tracing::debug!(
106            "Creating fee payer UTXO with amount {} ({} sat/vb)",
107            new_fee_payer_amount,
108            fee_rate
109        );
110
111        let fee_payer_tx = Transaction {
112            version: bitcoin::transaction::Version::TWO,
113            lock_time: bitcoin::absolute::LockTime::ZERO,
114            input: vec![],
115            output: vec![TxOut {
116                value: new_fee_payer_amount,
117                script_pubkey: self.signer.address.script_pubkey(),
118            }],
119        };
120
121        // Manually serialize in legacy format for 0-input transactions
122        // Because fund_raw_transaction RPC gives deserialization error for 0-input transactions with segwit flag
123        // but in the end fund_raw_transaction returns a segwit transaction after adding inputs
124        let fee_payer_bytes = if fee_payer_tx.input.is_empty() {
125            use bitcoin::consensus::Encodable;
126            let mut buf = Vec::new();
127            // Serialize version
128            fee_payer_tx
129                .version
130                .consensus_encode(&mut buf)
131                .expect("Failed to serialize version");
132            fee_payer_tx
133                .input
134                .consensus_encode(&mut buf)
135                .expect("Failed to serialize inputs");
136            fee_payer_tx
137                .output
138                .consensus_encode(&mut buf)
139                .expect("Failed to serialize outputs");
140            // Serialize locktime
141            fee_payer_tx
142                .lock_time
143                .consensus_encode(&mut buf)
144                .expect("Failed to serialize locktime");
145
146            buf
147        } else {
148            bitcoin::consensus::encode::serialize(&fee_payer_tx)
149        };
150
151        let funded_fee_payer_tx = self
152            .rpc
153            .fund_raw_transaction(
154                &fee_payer_bytes,
155                Some(&bitcoincore_rpc::json::FundRawTransactionOptions {
156                    add_inputs: Some(true),
157                    change_address: None,
158                    change_position: None,
159                    change_type: None,
160                    include_watching: None,
161                    lock_unspents: None,
162                    fee_rate: Some(Amount::from_sat(fee_rate.to_sat_per_vb_ceil() * 1000)),
163                    subtract_fee_from_outputs: None,
164                    replaceable: Some(true),
165                    conf_target: None,
166                    estimate_mode: None,
167                }),
168                None,
169            )
170            .await
171            .wrap_err("Failed to fund cpfp fee payer tx")?
172            .hex;
173
174        let signed_fee_payer_tx: Transaction = bitcoin::consensus::deserialize(
175            &self
176                .rpc
177                .sign_raw_transaction_with_wallet(&funded_fee_payer_tx, None, None)
178                .await
179                .wrap_err("Failed to sign funded tx through bitcoin RPC")?
180                .hex,
181        )
182        .wrap_err("Failed to deserialize signed tx")?;
183
184        let outpoint_vout = signed_fee_payer_tx
185            .output
186            .iter()
187            .position(|o| {
188                o.value == new_fee_payer_amount
189                    && o.script_pubkey == self.signer.address.script_pubkey()
190            })
191            .ok_or(eyre!("Failed to find outpoint vout"))?;
192
193        self.rpc
194            .send_raw_transaction(&signed_fee_payer_tx)
195            .await
196            .wrap_err("Failed to send signed fee payer tx")?;
197
198        self.db
199            .save_fee_payer_tx(
200                None,
201                bumped_id,
202                signed_fee_payer_tx.compute_txid(),
203                outpoint_vout as u32,
204                new_fee_payer_amount,
205                None,
206            )
207            .await
208            .map_to_eyre()?;
209
210        Ok(())
211    }
212
213    /// Creates a Child-Pays-For-Parent (CPFP) child transaction.
214    ///
215    /// This transaction spends:
216    /// 1.  The designated "P2A anchor" output of the parent transaction (`p2a_anchor`).
217    /// 2.  One or more confirmed "fee payer" UTXOs (`fee_payer_utxos`) controlled by the `signer`.
218    ///
219    /// It calculates the total fee required (`required_fee`) to make the combined parent + child
220    /// package attractive to miners at the target `fee_rate`. The `required_fee` is paid entirely
221    /// by this child transaction.
222    ///
223    /// The remaining value (total input value - `required_fee`) is sent to the `change_address`.
224    ///
225    /// # Signing
226    /// We sign the input spending the P2A anchor and all fee payer UTXOs.
227    ///
228    /// # Returns
229    /// The constructed and partially signed child transaction.
230    async fn create_child_tx(
231        &self,
232        p2a_anchor: OutPoint,
233        anchor_sat: Amount,
234        fee_payer_utxos: Vec<SpendableTxIn>,
235        parent_tx_size: Weight,
236        fee_rate: FeeRate,
237    ) -> Result<Transaction> {
238        tracing::debug!(
239            "Creating child tx with {} fee payer utxos",
240            fee_payer_utxos.len()
241        );
242        let required_fee = Self::calculate_required_fee(
243            parent_tx_size,
244            fee_payer_utxos.len(),
245            fee_rate,
246            FeePayingType::CPFP,
247        )
248        .map_err(|e| eyre!(e))?;
249
250        let change_address = self
251            .rpc
252            .get_new_wallet_address()
253            .await
254            .wrap_err("Failed to get new wallet address")?;
255
256        let total_fee_payer_amount = fee_payer_utxos
257            .iter()
258            .map(|utxo| utxo.get_prevout().value)
259            .sum::<Amount>()
260            + anchor_sat; // We add the anchor output value to the total amount.
261        if change_address.script_pubkey().minimal_non_dust() + required_fee > total_fee_payer_amount
262        {
263            return Err(SendTxError::InsufficientFeePayerAmount);
264        }
265
266        let mut builder = TxHandlerBuilder::new(TransactionType::Dummy)
267            .with_version(NON_STANDARD_V3)
268            .add_input(
269                NormalSignatureKind::OperatorSighashDefault,
270                SpendableTxIn::new_partial(
271                    p2a_anchor,
272                    builder::transaction::anchor_output(anchor_sat),
273                ),
274                SpendPath::Unknown,
275                DEFAULT_SEQUENCE,
276            );
277
278        for fee_payer_utxo in fee_payer_utxos {
279            builder = builder.add_input(
280                NormalSignatureKind::OperatorSighashDefault,
281                fee_payer_utxo,
282                SpendPath::KeySpend,
283                DEFAULT_SEQUENCE,
284            );
285        }
286
287        builder = builder.add_output(UnspentTxOut::from_partial(TxOut {
288            value: total_fee_payer_amount - required_fee,
289            script_pubkey: change_address.script_pubkey(),
290        }));
291
292        let mut tx_handler = builder.finalize();
293
294        for fee_payer_input in 1..tx_handler.get_cached_tx().input.len() {
295            let sighash = tx_handler
296                .calculate_pubkey_spend_sighash(fee_payer_input, bitcoin::TapSighashType::Default)
297                .map_err(|e| eyre!(e))?;
298            let signature = self
299                .signer
300                .sign_with_tweak_data(sighash, builder::sighash::TapTweakData::KeyPath(None), None)
301                .map_err(|e| eyre!(e))?;
302            tx_handler
303                .set_p2tr_key_spend_witness(
304                    &bitcoin::taproot::Signature {
305                        signature,
306                        sighash_type: bitcoin::TapSighashType::Default,
307                    },
308                    fee_payer_input,
309                )
310                .map_err(|e| eyre!(e))?;
311        }
312        let child_tx = tx_handler.get_cached_tx().clone();
313
314        Ok(child_tx)
315    }
316
317    /// Creates a transaction package for CPFP submission.
318    ///
319    /// Finds the P2A anchor output in the parent transaction (`tx`), then constructs
320    /// the child transaction using `create_child_tx`.
321    ///
322    /// # Returns
323    ///
324    /// - [`Vec<Transaction>`]: Parent transaction followed by the child
325    ///   transaction ready for submission via the `submitpackage` RPC.
326    async fn create_package(
327        &self,
328        tx: Transaction,
329        fee_rate: FeeRate,
330        fee_payer_utxos: Vec<SpendableTxIn>,
331    ) -> Result<Vec<Transaction>> {
332        tracing::debug!(
333            "Creating package with {} fee payer utxos",
334            fee_payer_utxos.len()
335        );
336        let txid = tx.compute_txid();
337
338        let p2a_vout = self
339            .find_p2a_vout(&tx)
340            .wrap_err("Failed to find p2a vout")?;
341
342        // get sat amount of anchor output in the tx
343        let anchor_sat = tx.output[p2a_vout].value;
344
345        let child_tx = self
346            .create_child_tx(
347                OutPoint {
348                    txid,
349                    vout: p2a_vout as u32,
350                },
351                anchor_sat,
352                fee_payer_utxos,
353                tx.weight(),
354                fee_rate,
355            )
356            .await
357            .wrap_err("Failed to create child tx")?;
358
359        Ok(vec![tx, child_tx])
360    }
361
362    /// Retrieves confirmed fee payer UTXOs associated with a specific send attempt.
363    ///
364    /// Queries the database for UTXOs linked to `try_to_send_id` that are marked as confirmed.
365    /// These UTXOs are controlled by the `TxSender`'s `signer` and are intended to be
366    /// spent by a CPFP child transaction.
367    ///
368    /// # Returns
369    ///
370    /// - [`Vec<SpendableTxIn>`]: [`SpendableTxIn`]s of the confirmed fee payer
371    ///   UTXOs that are ready to be included as inputs in the CPFP child tx.
372    async fn get_confirmed_fee_payer_utxos(
373        &self,
374        try_to_send_id: u32,
375    ) -> Result<Vec<SpendableTxIn>> {
376        Ok(self
377            .db
378            .get_confirmed_fee_payer_utxos(None, try_to_send_id)
379            .await
380            .map_to_eyre()?
381            .iter()
382            .map(|(txid, vout, amount)| {
383                SpendableTxIn::new(
384                    OutPoint {
385                        txid: *txid,
386                        vout: *vout,
387                    },
388                    TxOut {
389                        value: *amount,
390                        script_pubkey: self.signer.address.script_pubkey(),
391                    },
392                    vec![],
393                    Some(self.cached_spendinfo.clone()),
394                )
395            })
396            .collect())
397    }
398
399    /// Attempts to bump the fees of unconfirmed "fee payer" UTXOs using RBF.
400    ///
401    /// Fee payer UTXOs are created to fund CPFP child transactions. However, these
402    /// fee payer creation transactions might themselves get stuck due to low fees.
403    /// This function identifies such unconfirmed fee payer transactions associated with
404    /// a parent transaction (`bumped_id`) and attempts to RBF them using the provided `fee_rate`.
405    ///
406    /// This ensures the fee payer UTXOs confirm quickly, making them available to be spent
407    /// by the actual CPFP child transaction.
408    ///
409    /// # Arguments
410    /// * `bumped_id` - The database ID of the parent transaction whose fee payer UTXOs need bumping.
411    /// * `fee_rate` - The target fee rate for bumping the fee payer transactions.
412    #[tracing::instrument(skip_all, fields(sender = self.btc_syncer_consumer_id, fee_rate))]
413    pub(crate) async fn bump_fees_of_unconfirmed_fee_payer_txs(
414        &self,
415        fee_rate: FeeRate,
416    ) -> Result<()> {
417        let bumpable_fee_payer_txs = self
418            .db
419            .get_all_unconfirmed_fee_payer_txs(None)
420            .await
421            .map_to_eyre()?;
422
423        let mut not_evicted_ids = HashSet::new();
424        let mut all_parent_ids = HashSet::new();
425
426        for (id, try_to_send_id, fee_payer_txid, vout, amount, replacement_of_id) in
427            bumpable_fee_payer_txs
428        {
429            tracing::debug!(
430                "Bumping fee for fee payer tx {} for try to send id {} for fee rate {}",
431                fee_payer_txid,
432                try_to_send_id,
433                fee_rate
434            );
435            // parent id is the id of the first created tx for all replacements
436            let parent_id = match replacement_of_id {
437                Some(replacement_of_id) => replacement_of_id,
438                None => id,
439            };
440            all_parent_ids.insert(parent_id);
441            let mempool_info = self.rpc.get_mempool_entry(&fee_payer_txid).await;
442            let mempool_info = match mempool_info {
443                Ok(mempool_info) => {
444                    not_evicted_ids.insert(parent_id);
445                    mempool_info
446                }
447                Err(e) => {
448                    // If not in mempool we should ignore
449                    // give an error if the error is not "Transaction not in mempool"
450                    if !e.to_string().contains("Transaction not in mempool") {
451                        return Err(eyre::eyre!(
452                            "Failed to get mempool entry for fee payer tx {}: {}",
453                            fee_payer_txid,
454                            e
455                        )
456                        .into());
457                    }
458                    // check here if the tx is already in block, if so do not mark it as evicted
459                    let tx_info = self.rpc.get_transaction(&fee_payer_txid, None).await;
460                    if let Ok(tx_info) = tx_info {
461                        if tx_info.info.blockhash.is_some() && tx_info.info.confirmations > 0 {
462                            not_evicted_ids.insert(parent_id);
463                        }
464                    }
465                    continue;
466                }
467            };
468            // only try to bump if tx has no descendants and some time has passed since tx was created
469            if mempool_info.descendant_count > 1
470                || std::time::SystemTime::now()
471                    .duration_since(std::time::UNIX_EPOCH)
472                    .wrap_err("Failed to get unix timestamp")?
473                    .as_secs()
474                    .saturating_sub(mempool_info.time)
475                    < self
476                        .config
477                        .tx_sender_limits
478                        .cpfp_fee_payer_bump_wait_time_seconds
479            {
480                continue;
481            }
482            let new_txid_result = self
483                .rpc
484                .bump_fee_with_fee_rate(fee_payer_txid, fee_rate)
485                .await;
486
487            match new_txid_result {
488                Ok(new_txid) => {
489                    if new_txid != fee_payer_txid {
490                        self.db
491                            .save_fee_payer_tx(
492                                None,
493                                try_to_send_id,
494                                new_txid,
495                                vout,
496                                amount,
497                                match replacement_of_id {
498                                    Some(replacement_of_id) => Some(replacement_of_id),
499                                    None => Some(id),
500                                },
501                            )
502                            .await
503                            .map_to_eyre()?;
504                    } else {
505                        tracing::trace!(
506                            "Fee payer tx {} has enough fee, no need to bump",
507                            fee_payer_txid
508                        );
509                    }
510                }
511                Err(e) => {
512                    let e = e.into_eyre();
513                    match e.root_cause().downcast_ref::<BitcoinRPCError>() {
514                        Some(BitcoinRPCError::TransactionAlreadyInBlock(block_hash)) => {
515                            tracing::debug!(
516                                "Fee payer tx {} is already in block {}, skipping",
517                                fee_payer_txid,
518                                block_hash
519                            );
520                            continue;
521                        }
522                        Some(BitcoinRPCError::BumpFeeUTXOSpent(outpoint)) => {
523                            tracing::debug!(
524                                "Fee payer tx {} is already onchain, skipping: {:?}",
525                                fee_payer_txid,
526                                outpoint
527                            );
528                            continue;
529                        }
530                        _ => {
531                            tracing::warn!(
532                                "Failed to bump fee the fee payer tx {} with error {e}, skipping",
533                                fee_payer_txid
534                            );
535                            continue;
536                        }
537                    }
538                }
539            }
540        }
541
542        // if all fee payer utxos are not in mempool
543        // in very rare cases, (if tx was mined, but before we called gettransaction it was reorged)
544        // it can be marked as evicted accidentally, but this is very rare and if it was mined once but reorged,
545        // it will likely enter the chain without any bumping anyway, but an extra fee payer utxo can be created by txsender
546        // because it is considered to be evicted
547        for parent_id in all_parent_ids {
548            if !not_evicted_ids.contains(&parent_id) {
549                self.db
550                    .mark_fee_payer_utxo_as_evicted(None, parent_id)
551                    .await
552                    .map_to_eyre()?;
553            }
554        }
555
556        Ok(())
557    }
558
559    /// Sends a transaction using the Child-Pays-For-Parent (CPFP) strategy.
560    ///
561    /// # Logic:
562    /// 1.  **Check Unconfirmed Fee Payers:** Ensures no unconfirmed fee payer UTXOs exist
563    ///     for this `try_to_send_id`. If they do, returns [`SendTxError::UnconfirmedFeePayerUTXOsLeft`]
564    ///     as they need to confirm before being spendable by the child.
565    /// 2.  **Get Confirmed Fee Payers:** Retrieves the available confirmed fee payer UTXOs.
566    /// 3.  **Create Package:** Calls `create_package` to build the `vec![parent_tx, child_tx]`.
567    ///     The `child_tx` spends the parent's anchor output and the fee payer UTXOs, paying
568    ///     a fee calculated for the whole package.
569    /// 4.  **Test Mempool Accept (Debug step):** Uses `testmempoolaccept` RPC
570    ///     to check if the package is likely to be accepted by the network before submitting.
571    /// 5.  **Submit Package:** Uses the `submitpackage` RPC to atomically submit the parent
572    ///     and child transactions. Bitcoin Core evaluates the fee rate of the package together.
573    /// 6.  **Handle Results:** Checks the `submitpackage` result. If successful or already in
574    ///     mempool, updates the effective fee rate in the database. If failed, logs an error.
575    ///
576    /// # Arguments
577    /// * `try_to_send_id` - The database ID tracking this send attempt.
578    /// * `tx` - The parent transaction requiring the fee bump.
579    /// * `tx_metadata` - Optional metadata associated with the transaction.
580    /// * `fee_rate` - The target fee rate for the CPFP package.
581    #[tracing::instrument(skip_all, fields(sender = self.btc_syncer_consumer_id, try_to_send_id, tx_meta=?tx_metadata))]
582    pub(super) async fn send_cpfp_tx(
583        &self,
584        try_to_send_id: u32,
585        tx: Transaction,
586        tx_metadata: Option<TxMetadata>,
587        fee_rate: FeeRate,
588    ) -> Result<()> {
589        let unconfirmed_fee_payer_utxos = self
590            .db
591            .get_unconfirmed_fee_payer_txs(None, try_to_send_id)
592            .await
593            .map_to_eyre()?;
594
595        if !unconfirmed_fee_payer_utxos.is_empty() {
596            // Log that we're waiting for unconfirmed UTXOs
597            tracing::debug!(
598                try_to_send_id,
599                "Waiting for {} UTXOs to confirm",
600                unconfirmed_fee_payer_utxos.len()
601            );
602
603            // Update the sending state
604            let _ = self
605                .db
606                .update_tx_debug_sending_state(
607                    try_to_send_id,
608                    "waiting_for_utxo_confirmation",
609                    true,
610                )
611                .await;
612
613            return Ok(());
614        }
615
616        tracing::debug!(try_to_send_id, "Attempting to send CPFP tx");
617
618        let confirmed_fee_payers = self.get_confirmed_fee_payer_utxos(try_to_send_id).await?;
619        let confirmed_fee_payer_len = confirmed_fee_payers.len();
620
621        let _ = self
622            .db
623            .update_tx_debug_sending_state(try_to_send_id, "creating_package", true)
624            .await;
625
626        // to be used below
627        let total_fee_payer_amount = confirmed_fee_payers
628            .iter()
629            .map(|txi| txi.get_prevout().value)
630            .sum::<Amount>();
631
632        let package = self
633            .create_package(tx.clone(), fee_rate, confirmed_fee_payers)
634            .await
635            .wrap_err("Failed to create CPFP package");
636
637        let package = match package {
638            Ok(package) => package,
639            Err(e) => match e.root_cause().downcast_ref::<SendTxError>() {
640                Some(SendTxError::InsufficientFeePayerAmount) => {
641                    tracing::debug!(
642                        try_to_send_id,
643                        "Insufficient fee payer amount, creating new fee payer utxo."
644                    );
645
646                    self.create_fee_payer_utxo(
647                        try_to_send_id,
648                        &tx,
649                        fee_rate,
650                        total_fee_payer_amount,
651                        confirmed_fee_payer_len,
652                    )
653                    .await?;
654
655                    let _ = self
656                        .db
657                        .update_tx_debug_sending_state(
658                            try_to_send_id,
659                            "waiting_for_fee_payer_utxos",
660                            true,
661                        )
662                        .await;
663
664                    return Ok(());
665                }
666                _ => {
667                    tracing::error!(try_to_send_id, "Failed to create CPFP package: {:?}", e);
668                    return Err(e.into());
669                }
670            },
671        };
672
673        let package_refs: Vec<&Transaction> = package.iter().collect();
674
675        tracing::debug!(
676            try_to_send_id,
677            "Submitting package\n Pkg tx hexs: {:?}",
678            if env::var("DBG_PACKAGE_HEX").is_ok() {
679                package
680                    .iter()
681                    .map(|tx| hex::encode(bitcoin::consensus::serialize(tx)))
682                    .collect::<Vec<_>>()
683            } else {
684                vec!["use DBG_PACKAGE_HEX=1 to print the package as hex".into()]
685            }
686        );
687
688        // Update sending state to submitting_package
689        let _ = self
690            .db
691            .update_tx_debug_sending_state(try_to_send_id, "submitting_package", true)
692            .await;
693
694        tracing::debug!(try_to_send_id, "Submitting package, size {}", package.len());
695
696        // let test_mempool_result = self
697        //     .rpc
698        //     .test_mempool_accept(&package_refs)
699        //     .await
700        //     .wrap_err("Failed to test mempool accept")?;
701
702        let submit_package_result: PackageSubmissionResult = self
703            .rpc
704            .submit_package(&package_refs, Some(Amount::from_sat(0)), None)
705            .await
706            .wrap_err("Failed to submit package")?;
707
708        tracing::debug!(
709            try_to_send_id,
710            "Submit package result: {submit_package_result:?}"
711        );
712
713        // If tx_results is empty, it means the txs were already accepted by the network.
714        if submit_package_result.tx_results.is_empty() {
715            return Ok(());
716        }
717
718        let mut early_exit = false;
719        for (_txid, result) in submit_package_result.tx_results {
720            if let PackageTransactionResult::Failure { error, .. } = result {
721                tracing::error!(
722                    try_to_send_id,
723                    "Error submitting package: {:?}, package: {:?}",
724                    error,
725                    package_refs
726                        .iter()
727                        .map(|tx| hex::encode(bitcoin::consensus::serialize(tx)))
728                        .collect::<Vec<_>>()
729                );
730
731                early_exit = true;
732            }
733        }
734        if early_exit {
735            return Ok(());
736        }
737
738        tracing::info!("Package submitted successfully.");
739
740        // // Get the effective fee rate from the first transaction result
741        // let effective_fee_rate_btc_per_kvb = submit_package_result
742        //     .tx_results
743        //     .iter()
744        //     .next()
745        //     .and_then(|(_, result)| match result {
746        //         PackageTransactionResult::Success { fees, .. } => Some(fees.effective_feerate),
747        //         PackageTransactionResult::SuccessAlreadyInMempool { txid, .. } => {
748        //             tracing::warn!(
749        //                 "{}: transaction {txid} is already in mempool, skipping",
750        //                 self.consumer_handle
751        //             );
752        //             None
753        //         }
754        //         PackageTransactionResult::Failure { txid, error } => {
755        //             tracing::warn!(
756        //                 "{}: failed to send the transaction {txid} with error {error}, skipping",
757        //                 self.consumer_handle
758        //             );
759        //             None
760        //         }
761        //     })
762        //     .expect("Effective fee rate should be present")
763        //     .expect("Effective fee rate should be present");
764
765        // let effective_fee_rate = Self::btc_per_kvb_to_fee_rate(effective_fee_rate_btc_per_kvb);
766        // Save the effective fee rate to the db
767        self.db
768            .update_effective_fee_rate(None, try_to_send_id, fee_rate)
769            .await
770            .wrap_err("Failed to update effective fee rate")?;
771
772        // Sanity check to make sure the fee rate is equal to the required fee rate
773        // assert_eq!(
774        //     effective_fee_rate, fee_rate,
775        //     "Effective fee rate is not equal to the required fee rate: {:?} to {:?} != {:?}",
776        //     effective_fee_rate_btc_per_kvb, effective_fee_rate, fee_rate
777        // );
778
779        Ok(())
780    }
781}