1use crate::{log_error_for_tx, TxSender, TxSenderDatabase, TxSenderSigner, TxSenderTxBuilder};
2use bitcoin::script::Instruction;
3use bitcoin::sighash::{Prevouts, SighashCache};
4use bitcoin::taproot::{self};
5use bitcoin::{consensus, Address, Amount, FeeRate, Transaction};
6use bitcoin::{Psbt, TapSighashType, TxOut, Txid, Witness};
7use bitcoincore_rpc::json::{
8 BumpFeeOptions, BumpFeeResult, CreateRawTransactionInput, FinalizePsbtResult,
9 WalletCreateFundedPsbtOutput, WalletCreateFundedPsbtOutputs, WalletCreateFundedPsbtResult,
10};
11use bitcoincore_rpc::RpcApi;
12use clementine_errors::SendTxError;
13use clementine_utils::sign::TapTweakData;
14use clementine_utils::{RbfSigningInfo, TxMetadata};
15use eyre::Context;
16use eyre::{eyre, OptionExt};
17use std::str::FromStr;
18
19use super::Result;
20
21impl<S, D, B> TxSender<S, D, B>
22where
23 S: TxSenderSigner,
24 D: TxSenderDatabase,
25 B: TxSenderTxBuilder,
26{
27 pub async fn calculate_bump_feerate_if_needed(
47 &self,
48 txid: &Txid,
49 new_feerate: FeeRate,
50 ) -> Result<Option<FeeRate>> {
51 let original_tx = self.rpc.get_tx_of_txid(txid).await.map_err(|e| eyre!(e))?;
52
53 let original_tx_fee = self.get_tx_fee(&original_tx).await.map_err(|e| eyre!(e))?;
55
56 let original_tx_weight = original_tx.weight();
57
58 let original_feerate_sat_per_kwu = FeeRate::from_sat_per_kwu(
62 (original_tx_fee.to_sat() * 1000) / (original_tx_weight.to_vbytes_ceil() * 4),
63 );
64
65 if original_feerate_sat_per_kwu >= new_feerate {
67 return Ok(None);
68 }
69
70 let incremental_fee_rate = self
72 .rpc
73 .get_network_info()
74 .await
75 .map_err(|e| eyre!(e))?
76 .incremental_fee;
77 let incremental_fee_rate_sat_per_kvb = incremental_fee_rate.to_sat();
78 let incremental_fee_rate = FeeRate::from_sat_per_kwu(incremental_fee_rate_sat_per_kvb / 4);
79
80 let min_bump_feerate =
82 original_feerate_sat_per_kwu.to_sat_per_kwu() + incremental_fee_rate.to_sat_per_kwu();
83
84 let effective_feerate_sat_per_kwu =
85 std::cmp::max(new_feerate.to_sat_per_kwu(), min_bump_feerate);
86
87 Ok(Some(FeeRate::from_sat_per_kwu(
88 effective_feerate_sat_per_kwu,
89 )))
90 }
91
92 pub async fn fill_in_utxo_info(&self, psbt: &mut String) -> Result<()> {
93 let mut decoded_psbt = Psbt::from_str(psbt).map_err(|e| eyre!(e))?;
94 let tx = decoded_psbt.unsigned_tx.clone();
95
96 for (idx, input) in tx.input.iter().enumerate() {
97 let utxo = self
98 .rpc
99 .get_tx_out(
100 &input.previous_output.txid,
101 input.previous_output.vout,
102 Some(false),
103 )
104 .await
105 .wrap_err("Failed to get UTXO info")?;
106
107 if let Some(utxo) = utxo {
108 decoded_psbt.inputs[idx].witness_utxo = Some(TxOut {
109 value: utxo.value,
110 script_pubkey: utxo
111 .script_pub_key
112 .script()
113 .wrap_err("Failed to get script pubkey")?,
114 });
115 }
116 }
117
118 *psbt = decoded_psbt.to_string();
119
120 Ok(())
121 }
122
123 pub async fn copy_witnesses(&self, psbt: String, initial_tx: &Transaction) -> Result<String> {
131 let mut decoded_psbt = Psbt::from_str(&psbt).map_err(|e| eyre!(e))?;
132
133 for (idx, input) in initial_tx.input.iter().enumerate() {
134 if let Some(sig) = input.witness.nth(0) {
135 if sig.len() == 65 && sig[64] == 0x83 {
136 decoded_psbt.inputs[idx].final_script_witness = Some(input.witness.clone());
138 }
139 }
140 }
141
142 Ok(decoded_psbt.to_string())
143 }
144
145 pub async fn create_funded_psbt(
146 &self,
147 tx: &Transaction,
148 fee_rate: FeeRate,
149 ) -> Result<WalletCreateFundedPsbtResult> {
150 let witness_scaleup = tx.weight().to_wu() as f64 / (tx.base_size() * 4) as f64;
158
159 let adjusted_fee_rate = FeeRate::from_sat_per_kwu(
160 (fee_rate.to_sat_per_kwu() as f64 * witness_scaleup).ceil() as u64,
161 );
162
163 let create_psbt_opts = bitcoincore_rpc::json::WalletCreateFundedPsbtOptions {
165 add_inputs: Some(true), change_address: None,
167 change_position: Some(tx.output.len() as u16), change_type: None,
169 include_watching: None,
170 lock_unspent: None,
171 fee_rate: Some(
173 adjusted_fee_rate
174 .fee_vb(1000)
175 .ok_or_eyre("Failed to convert fee rate to BTC/kvbyte")?,
176 ),
177 subtract_fee_from_outputs: vec![],
178 replaceable: Some(true), conf_target: None,
180 estimate_mode: None,
181 };
182
183 let mut omitted = 0usize;
184 let filtered_outputs: Vec<WalletCreateFundedPsbtOutput> = tx
185 .output
186 .iter()
187 .filter_map(|out| {
188 if out.script_pubkey.is_op_return() {
189 if let Some(Ok(Instruction::PushBytes(data))) =
190 out.script_pubkey.instructions().last()
191 {
192 return Some(WalletCreateFundedPsbtOutput::OpReturn(
193 data.as_bytes().to_vec(),
194 ));
195 }
196 }
197 let address = Address::from_script(
198 &out.script_pubkey,
199 self.protocol_paramset.network,
200 )
201 .map_err(|e| eyre!(e));
202 match address {
203 Ok(address) => Some(WalletCreateFundedPsbtOutput::Spendable(
204 address.to_string(),
205 out.value,
206 )),
207 Err(err) => {
208 tracing::error!(
209 "Failed to get address from script for output of tx with txid {} for script: {}",
210 tx.compute_txid(),
211 err
212 );
213 omitted += 1;
214 None
215 }
216 }
217 })
218 .collect::<Vec<_>>();
219
220 if omitted > 0 {
221 return Err(eyre::eyre!("Failed to get address for outputs of tx with txid {} for {} outputs in create_funded_psbt", tx.compute_txid(), omitted).into());
222 }
223
224 let outputs = WalletCreateFundedPsbtOutputs(filtered_outputs);
225
226 self.rpc
227 .wallet_create_funded_psbt(
228 &tx.input
229 .iter()
230 .map(|inp| CreateRawTransactionInput {
231 txid: inp.previous_output.txid,
232 vout: inp.previous_output.vout,
233 sequence: Some(inp.sequence.to_consensus_u32()),
234 })
235 .collect::<Vec<_>>(),
236 outputs,
237 None,
238 Some(create_psbt_opts),
239 None,
240 )
241 .await
242 .map_err(|e| eyre!(e).into())
243 }
244 pub async fn attempt_sign_psbt(
252 &self,
253 psbt: String,
254 rbf_signing_info: RbfSigningInfo,
255 ) -> Result<String> {
256 let mut decoded_psbt = Psbt::from_str(&psbt).map_err(|e| eyre!(e))?;
258
259 if decoded_psbt.inputs.is_empty() {
261 return Err(eyre!("PSBT has no inputs to sign").into());
262 }
263
264 let input_index = rbf_signing_info.vout as usize;
265
266 let tx = decoded_psbt.unsigned_tx.clone();
268 let mut sighash_cache = SighashCache::new(&tx);
269
270 let sighash_type = decoded_psbt.inputs[input_index]
272 .sighash_type
273 .unwrap_or((TapSighashType::Default).into());
274
275 if let Ok(tap_sighash_type) = sighash_type.taproot_hash_ty() {
277 let prevouts: Vec<bitcoin::TxOut> = decoded_psbt
280 .inputs
281 .iter()
282 .zip(tx.input.iter())
283 .map(|(psbt_input, tx_input)| {
284 if let Some(witness_utxo) = psbt_input.witness_utxo.clone() {
286 Ok(witness_utxo)
287 } else if let Some(ref non_witness_tx) = psbt_input.non_witness_utxo {
288 let vout = tx_input.previous_output.vout as usize;
290 non_witness_tx
291 .output
292 .get(vout)
293 .cloned()
294 .ok_or_eyre(format!(
295 "Output index {vout} out of bounds in previous transaction",
296 ))
297 .map_err(SendTxError::Other)
298 } else {
299 Err(eyre!(
300 "Neither witness_utxo nor non_witness_utxo found for input"
301 ))
302 .map_err(SendTxError::Other)
303 }
304 })
305 .collect::<Result<Vec<_>>>()?;
306
307 let sighash = sighash_cache
308 .taproot_key_spend_signature_hash(
309 input_index,
310 &Prevouts::All(&prevouts),
311 tap_sighash_type,
312 )
313 .map_err(|e| eyre!("Failed to calculate sighash: {}", e))?;
314
315 let signature = self
317 .signer
318 .sign_with_tweak_data(
319 sighash,
320 TapTweakData::KeyPath(rbf_signing_info.tweak_merkle_root),
321 )
322 .map_err(|e| eyre!("Failed to sign input: {}", e))?;
323
324 decoded_psbt.inputs[input_index].tap_key_sig = Some(taproot::Signature {
326 signature,
327 sighash_type: tap_sighash_type,
328 });
329
330 decoded_psbt.inputs[input_index].final_script_witness =
331 Some(Witness::from_slice(&[signature.serialize()]));
332
333 Ok(decoded_psbt.to_string())
335 } else {
336 Err(eyre!("Only Taproot key path signing is currently supported").into())
337 }
338 }
339
340 #[track_caller]
341 pub fn handle_err(
342 &self,
343 err_msg: impl AsRef<str>,
344 err_state: impl Into<String>,
345 try_to_send_id: u32,
346 ) {
347 log_error_for_tx!(self.db, try_to_send_id, err_msg.as_ref());
348
349 let err_state = err_state.into();
350 let db = self.db.clone();
351
352 tokio::spawn(async move {
353 let _ = db
354 .update_tx_debug_sending_state(try_to_send_id, &err_state, true)
355 .await;
356 });
357 }
358
359 pub fn verify_new_inputs(&self, psbt: &str, original_tx: &Transaction) -> bool {
364 let Ok(psbt) = Psbt::from_str(psbt) else {
365 tracing::error!("Failed to parse PSBT");
366 return false;
367 };
368
369 psbt.inputs.len() > original_tx.input.len()
370 }
371
372 pub async fn get_tx_fee(&self, tx: &Transaction) -> Result<Amount> {
373 let inputs = {
374 let mut inputs = Amount::ZERO;
375 for inp in &tx.input {
376 inputs += self
377 .rpc
378 .get_txout_from_outpoint(&inp.previous_output)
379 .await
380 .map_err(|e| eyre!(e))?
381 .value;
382 }
383 inputs
384 };
385 let outputs = tx.output.iter().map(|o| o.value).sum::<Amount>();
386
387 let tx_fee = inputs - outputs;
388
389 Ok(tx_fee)
390 }
391
392 #[tracing::instrument(skip_all, fields(try_to_send_id, tx_meta=?tx_metadata))]
415 pub async fn send_rbf_tx(
416 &self,
417 try_to_send_id: u32,
418 tx: Transaction,
419 tx_metadata: Option<TxMetadata>,
420 fee_rate: FeeRate,
421 rbf_signing_info: Option<RbfSigningInfo>,
422 current_tip_height: u32,
423 ) -> Result<()> {
424 tracing::debug!(?tx_metadata, "Sending RBF tx",);
425
426 tracing::debug!(?try_to_send_id, "Attempting to send.");
427
428 let _ = self
429 .db
430 .update_tx_debug_sending_state(try_to_send_id, "preparing_rbf", true)
431 .await;
432
433 let mut dbtx = self
434 .db
435 .begin_transaction()
436 .await
437 .wrap_err("Failed to begin database transaction")?;
438
439 let last_rbf_txid = self
440 .db
441 .get_last_rbf_txid(Some(&mut dbtx), try_to_send_id)
442 .await
443 .wrap_err("Failed to get last RBF txid")?;
444
445 let effective_feerate = if let Some(last_rbf_txid) = last_rbf_txid {
446 tracing::debug!(
447 ?try_to_send_id,
448 "Attempting to bump fee for txid {last_rbf_txid} using psbt_bump_fee"
449 );
450
451 let effective_feerate = self
452 .calculate_bump_feerate_if_needed(&last_rbf_txid, fee_rate)
453 .await?;
454
455 let Some(effective_feerate) = effective_feerate else {
456 tracing::debug!(
457 ?try_to_send_id,
458 "Original tx feerate already higher than target ({} sat/vB), skipping bump",
459 fee_rate.to_sat_per_vb_ceil()
460 );
461 return Ok(());
462 };
463
464 let psbt_bump_opts = BumpFeeOptions {
465 conf_target: None, fee_rate: Some(bitcoincore_rpc::json::FeeRate::per_vbyte(Amount::from_sat(
467 effective_feerate.to_sat_per_vb_ceil(),
468 ))),
469 replaceable: Some(true), estimate_mode: None,
471 };
472
473 let bump_result = self
474 .rpc
475 .psbt_bump_fee(&last_rbf_txid, Some(&psbt_bump_opts))
476 .await;
477
478 let mut bumped_psbt = match bump_result {
479 Err(e) => {
480 let rpc_error_str = e.to_string();
482 if rpc_error_str.contains("Transaction already in block chain") {
483 tracing::debug!(
484 ?try_to_send_id,
485 "RBF bump failed for {last_rbf_txid}, likely confirmed or spent: {e}"
486 );
487 self.db.commit_transaction(dbtx).await.wrap_err(
489 "Failed to commit database transaction after failed bump check",
490 )?;
491 return Ok(());
492 } else {
493 let error_message = format!("psbt_bump_fee failed: {e}");
495 log_error_for_tx!(self.db, try_to_send_id, error_message);
496 let _ = self
497 .db
498 .update_tx_debug_sending_state(
499 try_to_send_id,
500 "rbf_psbt_bump_failed",
501 true,
502 )
503 .await;
504 tracing::warn!(?try_to_send_id, "psbt_bump_fee failed: {e:?}");
505 return Err(SendTxError::Other(eyre!(e)));
506 }
507 }
508 Ok(BumpFeeResult {
509 psbt: Some(psbt), ..
510 }) => psbt,
511 Ok(BumpFeeResult { errors, .. }) if !errors.is_empty() => {
512 self.handle_err(
513 format!("psbt_bump_fee failed: {errors:?}"),
514 "rbf_psbt_bump_failed",
515 try_to_send_id,
516 );
517 return Err(SendTxError::Other(eyre!(errors.join(", "))));
518 }
519 Ok(BumpFeeResult { psbt: None, .. }) => {
520 self.handle_err(
521 "psbt_bump_fee returned no psbt",
522 "rbf_psbt_bump_failed",
523 try_to_send_id,
524 );
525 return Err(SendTxError::Other(eyre!("psbt_bump_fee returned no psbt")));
526 }
527 };
528
529 self.fill_in_utxo_info(&mut bumped_psbt)
530 .await
531 .map_err(|err| {
532 let err = eyre!(err).wrap_err("Failed to fill in utxo info");
533 self.handle_err(
534 format!("{err:?}"),
535 "rbf_fill_in_utxo_info_failed",
536 try_to_send_id,
537 );
538
539 err
540 })?;
541
542 let bumped_psbt = self
543 .copy_witnesses(bumped_psbt, &tx)
544 .await
545 .wrap_err("Failed to fill SAP signatures")?;
546
547 let process_result = self
550 .rpc
551 .wallet_process_psbt(&bumped_psbt, Some(true), None, None) .await;
553
554 let processed_psbt = match process_result {
555 Ok(res) if res.complete => res.psbt,
556 Ok(res) => {
558 let Some(rbf_signing_info) = rbf_signing_info else {
559 return Err(eyre!(
560 "RBF signing info is required for non SighashSingle RBF txs"
561 )
562 .into());
563 };
564 self.attempt_sign_psbt(res.psbt, rbf_signing_info).await?
565 }
566 Err(e) => {
567 let err_msg = format!("wallet_process_psbt error: {e}");
568 tracing::warn!(?try_to_send_id, "{}", err_msg);
569 log_error_for_tx!(self.db, try_to_send_id, err_msg);
570 let _ = self
571 .db
572 .update_tx_debug_sending_state(try_to_send_id, "rbf_psbt_sign_failed", true)
573 .await;
574 return Err(SendTxError::Other(eyre!(e)));
575 }
576 };
577
578 let finalize_result = self
580 .rpc
581 .finalize_psbt(&processed_psbt, None) .await;
583
584 let final_tx_hex = match finalize_result {
585 Ok(FinalizePsbtResult {
586 hex: Some(hex),
587 complete: true,
588 ..
589 }) => hex,
590 Ok(res) => {
591 let err_msg = format!("Could not finalize PSBT: {res:?}");
592 log_error_for_tx!(self.db, try_to_send_id, err_msg);
593
594 let _ = self
595 .db
596 .update_tx_debug_sending_state(
597 try_to_send_id,
598 "rbf_psbt_finalize_incomplete",
599 true,
600 )
601 .await;
602 return Err(SendTxError::PsbtError(err_msg));
603 }
604 Err(e) => {
605 log_error_for_tx!(
606 self.db,
607 try_to_send_id,
608 format!("finalize_psbt error: {}", e)
609 );
610 let _ = self
611 .db
612 .update_tx_debug_sending_state(
613 try_to_send_id,
614 "rbf_psbt_finalize_failed",
615 true,
616 )
617 .await;
618 return Err(SendTxError::Other(eyre!(e)));
619 }
620 };
621
622 let final_tx: Transaction = match consensus::deserialize(&final_tx_hex) {
624 Ok(tx) => tx,
625 Err(e) => {
626 log_error_for_tx!(
627 self.db,
628 try_to_send_id,
629 format!("Failed to deserialize final RBF tx hex: {}", e)
630 );
631 return Err(SendTxError::Other(eyre!(e)));
632 }
633 };
634 let bumped_txid = final_tx.compute_txid();
635
636 let sent_txid = match self.rpc.send_raw_transaction(&final_tx).await {
638 Ok(sent_txid) if sent_txid == bumped_txid => sent_txid,
639 Ok(other_txid) => {
640 log_error_for_tx!(
641 self.db,
642 try_to_send_id,
643 format!(
644 "send_raw_transaction returned unexpected txid {} (expected {})",
645 other_txid, bumped_txid
646 )
647 );
648 let _ = self
649 .db
650 .update_tx_debug_sending_state(
651 try_to_send_id,
652 "rbf_send_txid_mismatch",
653 true,
654 )
655 .await;
656 return Err(SendTxError::Other(eyre!(
657 "send_raw_transaction returned unexpected txid"
658 )));
659 }
660 Err(e) => {
661 log_error_for_tx!(
662 self.db,
663 try_to_send_id,
664 format!("send_raw_transaction error for bumped RBF tx: {}", e)
665 );
666 let _ = self
667 .db
668 .update_tx_debug_sending_state(try_to_send_id, "rbf_bump_send_failed", true)
669 .await;
670 return Err(SendTxError::Other(eyre!(e)));
671 }
672 };
673
674 tracing::debug!(
675 ?try_to_send_id,
676 "RBF tx {last_rbf_txid} successfully bumped and sent as {sent_txid}"
677 );
678
679 let _ = self
680 .db
681 .update_tx_debug_sending_state(try_to_send_id, "rbf_bumped_sent", true)
682 .await;
683
684 self.db
685 .save_rbf_txid(Some(&mut dbtx), try_to_send_id, sent_txid)
686 .await
687 .wrap_err("Failed to save new RBF txid after bump")?;
688
689 effective_feerate
690 } else {
691 tracing::debug!(
692 ?try_to_send_id,
693 "Funding initial RBF tx using PSBT workflow"
694 );
695
696 let _ = self
697 .db
698 .update_tx_debug_sending_state(try_to_send_id, "creating_initial_rbf_psbt", true)
699 .await;
700
701 let create_result = self
702 .create_funded_psbt(&tx, fee_rate)
703 .await
704 .map_err(|err| {
705 let err = eyre!(err).wrap_err("Failed to create funded PSBT");
706 self.handle_err(format!("{err:?}"), "rbf_psbt_create_failed", try_to_send_id);
707
708 err
709 })?;
710
711 if !self.verify_new_inputs(&create_result.psbt, &tx) {
712 tracing::warn!(
713 ?try_to_send_id,
714 "Transaction has not been funded and is being sent as is. This transaction will have to be manually bumped as the wallet will not add it to itself."
715 );
716 }
717
718 let mut psbt = Psbt::from_str(&create_result.psbt).map_err(|e| eyre!(e))?;
720 psbt.unsigned_tx.lock_time = tx.lock_time;
721 psbt.unsigned_tx.version = tx.version;
722
723 tracing::debug!(
724 try_to_send_id,
725 "Successfully created initial RBF PSBT with fee {}",
726 create_result.fee
727 );
728
729 let mut psbt = psbt.to_string();
730
731 self.fill_in_utxo_info(&mut psbt).await.map_err(|err| {
732 let err = eyre!(err).wrap_err("Failed to fill in utxo info");
733 self.handle_err(
734 format!("{err:?}"),
735 "rbf_fill_in_utxo_info_failed",
736 try_to_send_id,
737 );
738
739 err
740 })?;
741
742 psbt = self.copy_witnesses(psbt, &tx).await.map_err(|err| {
743 let err = eyre!(err).wrap_err("Failed to copy witnesses");
744 self.handle_err(
745 format!("{err:?}"),
746 "rbf_copy_witnesses_failed",
747 try_to_send_id,
748 );
749
750 err
751 })?;
752
753 let process_result = self
755 .rpc
756 .wallet_process_psbt(&psbt, Some(true), None, None)
757 .await
758 .map_err(|err| {
759 let err = eyre!(err).wrap_err("Failed to process initial RBF PSBT");
760 self.handle_err(
761 format!("{err:?}"),
762 "rbf_psbt_process_failed",
763 try_to_send_id,
764 );
765
766 err
767 })?;
768
769 if let Some(rbf_signing_info) = rbf_signing_info {
770 psbt = self
771 .attempt_sign_psbt(process_result.psbt, rbf_signing_info)
772 .await
773 .map_err(|err| {
774 let err = eyre!(err).wrap_err("Failed to sign initial RBF PSBT");
775 self.handle_err(format!("{err:?}"), "rbf_psbt_sign_failed", try_to_send_id);
776
777 err
778 })?;
779 } else {
780 psbt = process_result.psbt;
781 }
782
783 tracing::debug!(try_to_send_id, "Successfully processed initial RBF PSBT");
784
785 let final_tx = {
786 let psbt = Psbt::from_str(&psbt).map_err(|e| eyre!(e)).map_err(|err| {
788 let err = eyre!(err).wrap_err("Failed to deserialize initial RBF PSBT");
789 self.handle_err(
790 format!("{err:?}"),
791 "rbf_psbt_deserialize_failed",
792 try_to_send_id,
793 );
794 err
795 })?;
796
797 let mut tx = psbt.unsigned_tx.clone();
798
799 for (idx, input) in tx.input.iter_mut().enumerate() {
800 if let Some(witness) = psbt.inputs[idx].final_script_witness.clone() {
801 input.witness = witness;
802 }
803 if let Some(sig) = psbt.inputs[idx].final_script_sig.clone() {
804 input.script_sig = sig;
805 }
806 }
807
808 tx
809 };
810
811 let initial_txid = final_tx.compute_txid();
812
813 let sent_txid = match self.rpc.send_raw_transaction(&final_tx).await {
815 Ok(sent_txid) => {
816 if sent_txid != initial_txid {
817 let err_msg = format!(
818 "send_raw_transaction returned unexpected txid {sent_txid} (expected {initial_txid}) for initial RBF",
819 );
820 log_error_for_tx!(self.db, try_to_send_id, err_msg);
821 let _ = self
822 .db
823 .update_tx_debug_sending_state(
824 try_to_send_id,
825 "rbf_initial_send_txid_mismatch",
826 true,
827 )
828 .await;
829 return Err(SendTxError::Other(eyre!(err_msg)));
830 }
831 tracing::debug!(
832 try_to_send_id,
833 "Successfully sent initial RBF tx with txid {sent_txid}"
834 );
835 sent_txid
836 }
837 Err(e) => {
838 tracing::error!("RBF failed for: {:?}", final_tx);
839 let err_msg = format!("send_raw_transaction error for initial RBF tx: {e}");
840 log_error_for_tx!(self.db, try_to_send_id, err_msg);
841 let _ = self
842 .db
843 .update_tx_debug_sending_state(
844 try_to_send_id,
845 "rbf_initial_send_failed",
846 true,
847 )
848 .await;
849 return Err(SendTxError::Other(eyre!(e)));
850 }
851 };
852
853 let _ = self
855 .db
856 .update_tx_debug_sending_state(try_to_send_id, "rbf_initial_sent", true)
857 .await;
858
859 self.db
860 .save_rbf_txid(Some(&mut dbtx), try_to_send_id, sent_txid)
861 .await
862 .wrap_err("Failed to save initial RBF txid")?;
863
864 fee_rate
865 };
866
867 self.db
868 .update_effective_fee_rate(
869 Some(&mut dbtx),
870 try_to_send_id,
871 effective_feerate,
872 current_tip_height,
873 )
874 .await
875 .wrap_err("Failed to update effective fee rate")?;
876
877 self.db
878 .commit_transaction(dbtx)
879 .await
880 .wrap_err("Failed to commit database transaction")?;
881
882 Ok(())
883 }
884}