1use super::Result;
21use crate::{SpendableInputInfo, TxSender, TxSenderDatabase, TxSenderSigner, TxSenderTxBuilder};
22use bitcoin::absolute::LockTime;
23use bitcoin::transaction::Version;
24use bitcoin::{Amount, FeeRate, OutPoint, Transaction, TxOut, Weight};
25use bitcoincore_rpc::json::FundRawTransactionOptions;
26use bitcoincore_rpc::{PackageTransactionResult, RpcApi};
27use clementine_errors::{BridgeError, ResultExt as _, SendTxError};
28use clementine_primitives::MIN_TAPROOT_AMOUNT;
29use clementine_utils::{FeePayingType, TxMetadata};
30use eyre::{eyre, Context};
31use std::collections::HashSet;
32
33impl<S, D, B> TxSender<S, D, B>
34where
35 S: TxSenderSigner,
36 D: TxSenderDatabase,
37 B: TxSenderTxBuilder,
38{
39 async fn create_fee_payer_utxo(
57 &self,
58 bumped_id: u32,
59 dbtx: Option<&mut D::Transaction>,
60 tx: &Transaction,
61 fee_rate: FeeRate,
62 total_fee_payer_amount: Amount,
63 fee_payer_utxos_len: usize,
64 ) -> Result<()> {
65 tracing::debug!(
66 "Creating fee payer UTXO for txid {} with bump id {}",
67 &tx.compute_txid().to_string(),
68 bumped_id
69 );
70 let required_fee = Self::calculate_required_fee(
71 tx.weight(),
72 fee_payer_utxos_len + 1,
73 fee_rate,
74 FeePayingType::CPFP,
75 )?;
76
77 let new_total_fee_needed = required_fee
82 .checked_mul(2)
83 .and_then(|fee| fee.checked_add(MIN_TAPROOT_AMOUNT));
84 if new_total_fee_needed.is_none() {
85 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());
86 }
87 let new_fee_payer_amount =
88 new_total_fee_needed.and_then(|fee| fee.checked_sub(total_fee_payer_amount));
89
90 let new_fee_payer_amount = match new_fee_payer_amount {
91 Some(fee) => fee,
92 None => {
94 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);
95 return Ok(());
96 }
97 };
98
99 tracing::debug!(
100 "Creating fee payer UTXO with amount {} ({} sat/vb)",
101 new_fee_payer_amount,
102 fee_rate
103 );
104
105 let fee_payer_tx = Transaction {
106 version: Version::TWO,
107 lock_time: LockTime::ZERO,
108 input: vec![],
109 output: vec![TxOut {
110 value: new_fee_payer_amount,
111 script_pubkey: self.signer.address().script_pubkey(),
112 }],
113 };
114
115 let fee_payer_bytes = if fee_payer_tx.input.is_empty() {
119 use bitcoin::consensus::Encodable;
120 let mut buf = Vec::new();
121 fee_payer_tx
123 .version
124 .consensus_encode(&mut buf)
125 .expect("Failed to serialize version");
126 fee_payer_tx
127 .input
128 .consensus_encode(&mut buf)
129 .expect("Failed to serialize inputs");
130 fee_payer_tx
131 .output
132 .consensus_encode(&mut buf)
133 .expect("Failed to serialize outputs");
134 fee_payer_tx
136 .lock_time
137 .consensus_encode(&mut buf)
138 .expect("Failed to serialize locktime");
139
140 buf
141 } else {
142 bitcoin::consensus::encode::serialize(&fee_payer_tx)
143 };
144
145 let funded_fee_payer_tx = self
146 .rpc
147 .fund_raw_transaction(
148 &fee_payer_bytes,
149 Some(&FundRawTransactionOptions {
150 add_inputs: Some(true),
151 change_address: None,
152 change_position: None,
153 change_type: None,
154 include_watching: None,
155 lock_unspents: None,
156 fee_rate: Some(Amount::from_sat(fee_rate.to_sat_per_vb_ceil() * 1000)),
157 subtract_fee_from_outputs: None,
158 replaceable: Some(true),
159 conf_target: None,
160 estimate_mode: None,
161 }),
162 None,
163 )
164 .await
165 .wrap_err("Failed to fund cpfp fee payer tx")?
166 .hex;
167
168 let signed_fee_payer_tx: Transaction = bitcoin::consensus::deserialize(
169 &self
170 .rpc
171 .sign_raw_transaction_with_wallet(&funded_fee_payer_tx, None, None)
172 .await
173 .wrap_err("Failed to sign funded tx through bitcoin RPC")?
174 .hex,
175 )
176 .wrap_err("Failed to deserialize signed tx")?;
177
178 let outpoint_vout = signed_fee_payer_tx
179 .output
180 .iter()
181 .position(|o| {
182 o.value == new_fee_payer_amount
183 && o.script_pubkey == self.signer.address().script_pubkey()
184 })
185 .ok_or(eyre!("Failed to find outpoint vout"))?;
186
187 self.rpc
188 .send_raw_transaction(&signed_fee_payer_tx)
189 .await
190 .wrap_err("Failed to send signed fee payer tx")?;
191
192 self.db
193 .save_fee_payer_tx(
194 dbtx,
195 None,
196 bumped_id,
197 signed_fee_payer_tx.compute_txid(),
198 outpoint_vout as u32,
199 new_fee_payer_amount,
200 None,
201 )
202 .await
203 .map_to_eyre()?;
204
205 Ok(())
206 }
207
208 async fn create_child_tx(
226 &self,
227 p2a_anchor: OutPoint,
228 anchor_sat: Amount,
229 fee_payer_utxos: Vec<B::SpendableInput>,
230 parent_tx_size: Weight,
231 fee_rate: FeeRate,
232 ) -> Result<Transaction> {
233 let required_fee = Self::calculate_required_fee(
234 parent_tx_size,
235 fee_payer_utxos.len(),
236 fee_rate,
237 FeePayingType::CPFP,
238 )?;
239
240 let change_address = self
241 .rpc
242 .get_new_address(None, None)
243 .await
244 .wrap_err("Failed to get new wallet address")?
245 .assume_checked();
246
247 let total_fee_payer_amount = fee_payer_utxos
248 .iter()
249 .map(|utxo| utxo.get_prevout().value)
250 .sum::<Amount>()
251 + anchor_sat;
252
253 if change_address.script_pubkey().minimal_non_dust() + required_fee > total_fee_payer_amount
254 {
255 return Err(SendTxError::InsufficientFeePayerAmount);
256 }
257
258 B::build_child_tx(
260 p2a_anchor,
261 anchor_sat,
262 fee_payer_utxos,
263 change_address,
264 required_fee,
265 &self.signer,
266 )
267 .map_err(|e| SendTxError::Other(e.into()))
268 }
269
270 async fn create_package(
280 &self,
281 tx: Transaction,
282 fee_rate: FeeRate,
283 fee_payer_utxos: Vec<B::SpendableInput>,
284 ) -> Result<Vec<Transaction>> {
285 let txid = tx.compute_txid();
286 let p2a_vout = self
287 .find_p2a_vout(&tx)
288 .map_err(|e: BridgeError| SendTxError::Other(e.into()))?;
289 let anchor_sat = tx.output[p2a_vout].value;
290
291 let child_tx = self
292 .create_child_tx(
293 OutPoint {
294 txid,
295 vout: p2a_vout as u32,
296 },
297 anchor_sat,
298 fee_payer_utxos,
299 tx.weight(),
300 fee_rate,
301 )
302 .await?;
303
304 Ok(vec![tx, child_tx])
305 }
306
307 async fn get_confirmed_fee_payer_utxos(
308 &self,
309 try_to_send_id: u32,
310 ) -> Result<Vec<B::SpendableInput>> {
311 let utxos = self
312 .db
313 .get_confirmed_fee_payer_utxos(None, try_to_send_id)
314 .await
315 .map_err(|e: BridgeError| SendTxError::Other(e.into()))?;
316 Ok(B::utxos_to_spendable_inputs(utxos, self.signer.address()))
317 }
318
319 pub async fn bump_fees_of_unconfirmed_fee_payer_txs(&self, fee_rate: FeeRate) -> Result<()> {
320 let bumpable_txs = self
321 .db
322 .get_all_unconfirmed_fee_payer_txs(None)
323 .await
324 .map_err(|e: BridgeError| SendTxError::Other(e.into()))?;
325 let mut not_evicted_ids = HashSet::new();
326 let mut all_parent_ids = HashSet::new();
327
328 for (id, try_to_send_id, txid, vout, amount, replacement_of_id) in bumpable_txs {
329 let parent_id = replacement_of_id.unwrap_or(id);
330 all_parent_ids.insert(parent_id);
331
332 match self.rpc.get_mempool_entry(&txid).await {
333 Ok(info) => {
334 not_evicted_ids.insert(parent_id);
335 if info.descendant_count > 1
336 || std::time::SystemTime::now()
337 .duration_since(std::time::UNIX_EPOCH)
338 .unwrap()
339 .as_secs()
340 .saturating_sub(info.time)
341 < self.tx_sender_limits.cpfp_fee_payer_bump_wait_time_seconds
342 {
343 continue;
344 }
345 }
346 Err(e) => {
347 if !e.to_string().contains("Transaction not in mempool") {
348 return Err(eyre!("Failed to get mempool entry for {txid}: {e}").into());
349 }
350 if let Ok(tx_info) = self.rpc.get_transaction(&txid, None).await {
351 if tx_info.info.blockhash.is_some() && tx_info.info.confirmations > 0 {
352 not_evicted_ids.insert(parent_id);
353 }
354 }
355 continue;
356 }
357 }
358
359 if let Ok(new_txid) = self.rpc.bump_fee_with_fee_rate(txid, fee_rate).await {
360 if new_txid != txid {
361 self.db
362 .save_fee_payer_tx(
363 None,
364 Some(try_to_send_id),
365 0, new_txid,
367 vout,
368 amount,
369 Some(parent_id),
370 )
371 .await
372 .map_err(|e: BridgeError| SendTxError::Other(e.into()))?;
373 }
374 }
375 }
376
377 for parent_id in all_parent_ids {
378 if !not_evicted_ids.contains(&parent_id) {
379 self.db
380 .mark_fee_payer_utxo_as_evicted(None, parent_id)
381 .await
382 .map_err(|e: BridgeError| SendTxError::Other(e.into()))?;
383 }
384 }
385 Ok(())
386 }
387
388 pub async fn send_cpfp_tx(
389 &self,
390 try_to_send_id: u32,
391 tx: Transaction,
392 _tx_metadata: Option<TxMetadata>,
393 fee_rate: FeeRate,
394 ) -> Result<()> {
395 let unconfirmed = self
396 .db
397 .get_unconfirmed_fee_payer_txs(None, try_to_send_id)
398 .await
399 .map_err(|e: BridgeError| SendTxError::Other(e.into()))?;
400 if !unconfirmed.is_empty() {
401 let _ = self
402 .db
403 .update_tx_debug_sending_state(
404 try_to_send_id,
405 "waiting_for_utxo_confirmation",
406 true,
407 )
408 .await;
409 return Ok(());
410 }
411
412 let confirmed = self.get_confirmed_fee_payer_utxos(try_to_send_id).await?;
413 let total_amount: Amount = confirmed.iter().map(|u| u.get_prevout().value).sum();
414
415 let package = match self
416 .create_package(tx.clone(), fee_rate, confirmed.clone())
417 .await
418 {
419 Ok(p) => p,
420 Err(SendTxError::InsufficientFeePayerAmount) => {
421 self.create_fee_payer_utxo(
422 try_to_send_id,
423 None,
424 &tx,
425 fee_rate,
426 total_amount,
427 confirmed.len(),
428 )
429 .await?;
430 let _ = self
431 .db
432 .update_tx_debug_sending_state(
433 try_to_send_id,
434 "waiting_for_fee_payer_utxos",
435 true,
436 )
437 .await;
438 return Ok(());
439 }
440 Err(e) => return Err(e),
441 };
442
443 let package_refs: Vec<&Transaction> = package.iter().collect();
444 let submit_result = self
445 .rpc
446 .submit_package(&package_refs, Some(Amount::ZERO), None)
447 .await
448 .wrap_err("Failed to submit package")?;
449
450 if submit_result.tx_results.is_empty() {
451 return Ok(());
452 }
453
454 for (_txid, result) in submit_result.tx_results {
455 if let PackageTransactionResult::Failure { error, .. } = result {
456 tracing::error!(try_to_send_id, "Error submitting package: {:?}", error);
457 return Ok(());
458 }
459 }
460
461 self.db
462 .update_effective_fee_rate(None, try_to_send_id, fee_rate)
463 .await
464 .map_err(|e: BridgeError| SendTxError::Other(e.into()))?;
465 Ok(())
466 }
467}