pub struct TxSender<S, D, B>{
pub signer: S,
pub rpc: ExtendedBitcoinRpc,
pub db: D,
pub btc_syncer_consumer_id: String,
pub protocol_paramset: &'static ProtocolParamset,
pub tx_sender_limits: TxSenderLimits,
pub http_client: Client,
pub(crate) mempool_config: MempoolConfig,
pub(crate) _tx_builder: PhantomData<B>,
}Expand description
Manages the process of sending Bitcoin transactions, including handling fee bumping strategies like Replace-By-Fee (RBF) and Child-Pays-For-Parent (CPFP).
It interacts with a Bitcoin Core RPC endpoint (ExtendedBitcoinRpc) to query network state
(like fee rates) and submit transactions. It uses a Database to persist transaction
state, track confirmation status, and manage associated data like fee payer UTXOs.
The Actor provides signing capabilities for transactions controlled by this service.
The TxSenderTxBuilder type parameter provides static methods for transaction building
capabilities for CPFP child transactions, using SpendableTxIn and TxHandler.
Fields§
§signer: S§rpc: ExtendedBitcoinRpc§db: D§btc_syncer_consumer_id: String§protocol_paramset: &'static ProtocolParamset§tx_sender_limits: TxSenderLimits§http_client: Client§mempool_config: MempoolConfig§_tx_builder: PhantomData<B>Phantom data to track the TxBuilder type. B provides static methods for transaction building.
Implementations§
Source§impl<S, D, B> TxSender<S, D, B>
impl<S, D, B> TxSender<S, D, B>
Sourceasync fn create_fee_payer_utxo(
&self,
bumped_id: u32,
dbtx: Option<&mut D::Transaction>,
tx: &Transaction,
fee_rate: FeeRate,
total_fee_payer_amount: Amount,
fee_payer_utxos_len: usize,
) -> Result<()>
async fn create_fee_payer_utxo( &self, bumped_id: u32, dbtx: Option<&mut D::Transaction>, tx: &Transaction, fee_rate: FeeRate, total_fee_payer_amount: Amount, fee_payer_utxos_len: usize, ) -> Result<()>
Creates and broadcasts a new “fee payer” UTXO to be used for CPFP transactions.
This function is called when a CPFP attempt fails due to insufficient funds
in the existing confirmed fee payer UTXOs associated with a transaction (bumped_id).
It calculates the required fee based on the parent transaction (tx) and the current
fee_rate, adding a buffer (2x required fee + dust limit) to handle potential fee spikes.
It then sends funds to the TxSender’s own signer address using the RPC’s
send_to_address and saves the resulting UTXO information (outpoint, amount)
to the database, linking it to the bumped_id.
§Arguments
bumped_id- The database ID of the parent transaction requiring the fee bump.tx- The parent transaction itself.fee_rate- The target fee rate for the CPFP package.total_fee_payer_amount- The sum of amounts in currently available confirmed fee payer UTXOs.fee_payer_utxos_len- The number of currently available confirmed fee payer UTXOs.
Sourceasync fn create_child_tx(
&self,
p2a_anchor: OutPoint,
anchor_sat: Amount,
fee_payer_utxos: Vec<B::SpendableInput>,
parent_tx_size: Weight,
fee_rate: FeeRate,
) -> Result<Transaction>
async fn create_child_tx( &self, p2a_anchor: OutPoint, anchor_sat: Amount, fee_payer_utxos: Vec<B::SpendableInput>, parent_tx_size: Weight, fee_rate: FeeRate, ) -> Result<Transaction>
Creates a Child-Pays-For-Parent (CPFP) child transaction.
This transaction spends:
- The designated “P2A anchor” output of the parent transaction (
p2a_anchor). - One or more confirmed “fee payer” UTXOs (
fee_payer_utxos) controlled by thesigner.
It calculates the total fee required (required_fee) to make the combined parent + child
package attractive to miners at the target fee_rate. The required_fee is paid entirely
by this child transaction.
The remaining value (total input value - required_fee) is sent to the change_address.
§Signing
We sign the input spending the P2A anchor and all fee payer UTXOs.
§Returns
The constructed and partially signed child transaction.
Sourceasync fn create_package(
&self,
tx: Transaction,
fee_rate: FeeRate,
fee_payer_utxos: Vec<B::SpendableInput>,
) -> Result<Vec<Transaction>>
async fn create_package( &self, tx: Transaction, fee_rate: FeeRate, fee_payer_utxos: Vec<B::SpendableInput>, ) -> Result<Vec<Transaction>>
Creates a transaction package for CPFP submission.
Finds the P2A anchor output in the parent transaction (tx), then constructs
the child transaction using create_child_tx.
§Returns
Vec<Transaction>: Parent transaction followed by the child transaction ready for submission via thesubmitpackageRPC.
async fn get_confirmed_fee_payer_utxos( &self, try_to_send_id: u32, ) -> Result<Vec<B::SpendableInput>>
pub async fn bump_fees_of_unconfirmed_fee_payer_txs( &self, fee_rate: FeeRate, ) -> Result<()>
pub async fn send_cpfp_tx( &self, try_to_send_id: u32, tx: Transaction, _tx_metadata: Option<TxMetadata>, fee_rate: FeeRate, ) -> Result<()>
Source§impl<S, D, B> TxSender<S, D, B>
impl<S, D, B> TxSender<S, D, B>
Sourcepub fn is_bridge_tx_nonstandard(&self, tx: &Transaction) -> bool
pub fn is_bridge_tx_nonstandard(&self, tx: &Transaction) -> bool
Checks if a bridge transaction is nonstandard. Keep in mind that these are not all cases where a transaction is nonstandard. We only check non-standard types that clementine generates by default in non-standard mode. Currently checks these cases:
- The transaction contains 0 sat non-anchor (only checks our specific anchor address) and non-op return output.
- The transaction weight is bigger than 400k
Arguments:
tx- The transaction to check.
Returns:
trueif the transaction is nonstandard,falseotherwise.
Sourcepub async fn send_testnet4_nonstandard_tx(
&self,
tx: &Transaction,
try_to_send_id: u32,
) -> Result<(), SendTxError>
pub async fn send_testnet4_nonstandard_tx( &self, tx: &Transaction, try_to_send_id: u32, ) -> Result<(), SendTxError>
Sends a nonstandard transaction to testnet4 using the mempool.space accelerator.
Arguments:
tx- The transaction to send.
Returns:
Ok(())if the transaction is sent successfully to the accelerator.Err(SendTxError)if the transaction is not sent successfully to the accelerator.
Note: Mempool.space accelerator doesn’t accept transactions if: - At least one of the transaction’s inputs is signed with either the SIGHASH_NONE or SIGHASH_ANYONECANPAY flag, which may allow a third party to replace the transaction. - The number of signature operations multiplied by 20 exceeds the transaction’s weight. Mempool Space API docs Mempool Space Accelerator FAQ
Source§impl<S, D, B> TxSender<S, D, B>
impl<S, D, B> TxSender<S, D, B>
Sourcepub async fn calculate_bump_feerate_if_needed(
&self,
txid: &Txid,
new_feerate: FeeRate,
) -> Result<Option<FeeRate>>
pub async fn calculate_bump_feerate_if_needed( &self, txid: &Txid, new_feerate: FeeRate, ) -> Result<Option<FeeRate>>
Calculates the appropriate fee rate for a Replace-By-Fee (RBF) transaction.
This method determines the effective fee rate needed to successfully replace an existing transaction in the mempool. It follows Bitcoin’s RBF rules by:
- Retrieving the original transaction and calculating its current fee rate
- Ensuring the new fee rate is higher than the original by at least the minimum required incremental relay fee
- Comparing the calculated minimum bump fee rate with the requested target fee rate and selecting the higher of the two
§Arguments
txid- The transaction ID of the original transaction to be replacednew_feerate- The target fee rate requested for the replacement transaction
§Returns
Ok(Some(FeeRate))- The effective fee rate (in satoshis per kilo-wu) to use for the replacementOk(None)- If the original transaction already has a higher fee rate than requestedErr(...)- If there was an error retrieving or analyzing the original transaction
pub async fn fill_in_utxo_info(&self, psbt: &mut String) -> Result<()>
Sourcepub async fn copy_witnesses(
&self,
psbt: String,
initial_tx: &Transaction,
) -> Result<String>
pub async fn copy_witnesses( &self, psbt: String, initial_tx: &Transaction, ) -> Result<String>
Given a PSBT with inputs, fill in the existing witnesses from the original tx This allows us to create a finalized PSBT if the original tx had SinglePlusAnyoneCanPay signatures. If the original tx did not have S+AP, these signatures will be added. The expected behavior is for them to be replaced using RbfSigningInfo.
§Returns
The PSBT as a base64-encoded string.
pub async fn create_funded_psbt( &self, tx: &Transaction, fee_rate: FeeRate, ) -> Result<WalletCreateFundedPsbtResult>
Sourcepub async fn attempt_sign_psbt(
&self,
psbt: String,
rbf_signing_info: RbfSigningInfo,
) -> Result<String>
pub async fn attempt_sign_psbt( &self, psbt: String, rbf_signing_info: RbfSigningInfo, ) -> Result<String>
Given a PSBT with inputs that’ve been signed by the wallet except for our new input, we have to sign the first input with our self.signer actor.
Assumes that the first input is the input with our key.
§Returns
The signed PSBT as a base64-encoded string.
pub fn handle_err( &self, err_msg: impl AsRef<str>, err_state: impl Into<String>, try_to_send_id: u32, )
Sourcepub fn verify_new_inputs(&self, psbt: &str, original_tx: &Transaction) -> bool
pub fn verify_new_inputs(&self, psbt: &str, original_tx: &Transaction) -> bool
This function verifies that the wallet has added a funding input to the PSBT.
This is required for a transaction to be added to the wallet.
pub async fn get_tx_fee(&self, tx: &Transaction) -> Result<Amount>
Sourcepub async fn send_rbf_tx(
&self,
try_to_send_id: u32,
tx: Transaction,
tx_metadata: Option<TxMetadata>,
fee_rate: FeeRate,
rbf_signing_info: Option<RbfSigningInfo>,
) -> Result<()>
pub async fn send_rbf_tx( &self, try_to_send_id: u32, tx: Transaction, tx_metadata: Option<TxMetadata>, fee_rate: FeeRate, rbf_signing_info: Option<RbfSigningInfo>, ) -> Result<()>
Sends or bumps a transaction using the Replace-By-Fee (RBF) strategy.
It interacts with the database to track the latest RBF attempt (last_rbf_txid).
§Logic:
-
Check for Existing RBF Tx: Retrieves
last_rbf_txidfor thetry_to_send_id. -
Bump Existing Tx: If
psbt_bump_feeexists, it callsrpc.psbt_bump_fee.- This internally uses the Bitcoin Core
psbtbumpfeeRPC. - We then sign the inputs that we can using our Actor and have the wallet sign the rest.
- This internally uses the Bitcoin Core
-
Send Initial RBF Tx: If no
last_rbf_txidexists (first attempt):- It uses
fund_raw_transactionRPC to let the wallet add (potentially) inputs, outputs, set the fee according tofee_rate, and mark the transaction as replaceable. - Uses
sign_raw_transaction_with_walletRPC to sign the funded transaction. - Uses
send_raw_transactionRPC to broadcast the initial RBF transaction. - Saves the resulting
txidto the database as thelast_rbf_txid.
- It uses
§Arguments
try_to_send_id- The database ID tracking this send attempt.tx- The original transaction intended for RBF (used only on the first attempt).tx_metadata- Optional metadata associated with the transaction.fee_rate- The target fee rate for the RBF replacement.
Source§impl<S, D, B> TxSender<S, D, B>
impl<S, D, B> TxSender<S, D, B>
Sourcepub fn new(
signer: S,
rpc: ExtendedBitcoinRpc,
db: D,
btc_syncer_consumer_id: String,
protocol_paramset: &'static ProtocolParamset,
tx_sender_limits: TxSenderLimits,
mempool_config: MempoolConfig,
) -> Self
pub fn new( signer: S, rpc: ExtendedBitcoinRpc, db: D, btc_syncer_consumer_id: String, protocol_paramset: &'static ProtocolParamset, tx_sender_limits: TxSenderLimits, mempool_config: MempoolConfig, ) -> Self
Creates a new TxSender.
The type parameter B provides static methods for CPFP child transaction creation
using SpendableTxIn and TxHandler from the core builder module.
pub async fn get_fee_rate(&self) -> Result<FeeRate, BridgeError>
Sourcepub(crate) fn calculate_required_fee(
parent_tx_weight: Weight,
num_fee_payer_utxos: usize,
fee_rate: FeeRate,
fee_paying_type: FeePayingType,
) -> Result<Amount>
pub(crate) fn calculate_required_fee( parent_tx_weight: Weight, num_fee_payer_utxos: usize, fee_rate: FeeRate, fee_paying_type: FeePayingType, ) -> Result<Amount>
Calculates the total fee required for a transaction package based on the fee bumping strategy.
§Arguments
parent_tx_weight- The weight of the main transaction being bumped.num_fee_payer_utxos- The number of fee payer UTXOs used (relevant for child tx size in CPFP).fee_rate- The target fee rate (sat/kwu or similar).fee_paying_type- The strategy being used (CPFP or RBF).
§Calculation Logic
- CPFP: Calculates the weight of the hypothetical child transaction based on the number of fee payer inputs and standard P2TR output sizes. It then calculates the fee based on the combined virtual size (vbytes) of the parent and child transactions, as miners evaluate the package deal.
- RBF: Calculates the weight of the replacement transaction itself (assuming inputs and potentially outputs change slightly). The fee is calculated based on the weight of this single replacement transaction.
Reference for weight estimates: https://bitcoin.stackexchange.com/a/116959
pub fn is_p2a_anchor(&self, output: &TxOut) -> bool
pub fn find_p2a_vout(&self, tx: &Transaction) -> Result<usize, BridgeError>
Sourcepub(crate) async fn try_to_send_unconfirmed_txs(
&self,
new_fee_rate: FeeRate,
current_tip_height: u32,
is_tip_height_increased: bool,
) -> Result<()>
pub(crate) async fn try_to_send_unconfirmed_txs( &self, new_fee_rate: FeeRate, current_tip_height: u32, is_tip_height_increased: bool, ) -> Result<()>
Fetches transactions that are eligible to be sent or bumped from database based on the given fee rate and tip height. Then, places a send transaction request to the Bitcoin based on the fee strategy.
For each eligible transaction (id):
- Send/Bump Main Tx: Calls
send_txto either perform RBF or CPFP on the main transaction (id) using thenew_fee_rate. - Handle Errors:
SendTxError::UnconfirmedFeePayerUTXOsLeft: Skips the current tx, waiting for fee payers to confirm.SendTxError::InsufficientFeePayerAmount: Callscreate_fee_payer_utxoto provision more funds for a future CPFP attempt.- Other errors are logged.
§Arguments
new_fee_rate- The current target fee rate based on network conditions.current_tip_height- The current blockchain height, used for time-lock checks.is_tip_height_increased- True if the tip height has increased since the last time we sent unconfirmed transactions.
pub fn client(&self) -> TxSenderClient<D>
Sourcepub async fn send_no_funding_tx(
&self,
try_to_send_id: u32,
tx: Transaction,
tx_metadata: Option<TxMetadata>,
) -> Result<()>
pub async fn send_no_funding_tx( &self, try_to_send_id: u32, tx: Transaction, tx_metadata: Option<TxMetadata>, ) -> Result<()>
Sends a transaction that is already fully funded and signed.
This function is used for transactions that do not require fee bumping strategies like RBF or CPFP. The transaction is submitted directly to the Bitcoin network without any modifications.
§Arguments
try_to_send_id- The database ID tracking this send attempt.tx- The fully funded and signed transaction ready for broadcast.tx_metadata- Optional metadata associated with the transaction for debugging.
§Behavior
- Attempts to broadcast the transaction using
send_raw_transactionRPC. - Updates the database with success/failure state for debugging purposes.
- Logs appropriate messages for monitoring and troubleshooting.
§Returns
Ok(())- If the transaction was successfully broadcast.Err(SendTxError)- If the broadcast failed.
Trait Implementations§
Source§impl<S, D, B> Clone for TxSender<S, D, B>where
S: TxSenderSigner + 'static + Clone,
D: TxSenderDatabase + 'static + Clone,
B: TxSenderTxBuilder + 'static + Clone,
impl<S, D, B> Clone for TxSender<S, D, B>where
S: TxSenderSigner + 'static + Clone,
D: TxSenderDatabase + 'static + Clone,
B: TxSenderTxBuilder + 'static + Clone,
Source§impl<S, D, B> Debug for TxSender<S, D, B>where
S: TxSenderSigner + Debug + 'static,
D: TxSenderDatabase + Debug + 'static,
B: TxSenderTxBuilder + 'static,
impl<S, D, B> Debug for TxSender<S, D, B>where
S: TxSenderSigner + Debug + 'static,
D: TxSenderDatabase + Debug + 'static,
B: TxSenderTxBuilder + 'static,
Auto Trait Implementations§
impl<S, D, B> Freeze for TxSender<S, D, B>
impl<S, D, B> !RefUnwindSafe for TxSender<S, D, B>
impl<S, D, B> Send for TxSender<S, D, B>
impl<S, D, B> Sync for TxSender<S, D, B>
impl<S, D, B> Unpin for TxSender<S, D, B>
impl<S, D, B> !UnwindSafe for TxSender<S, D, B>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.