Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
When a tx is broadcast but not yet mined, it lives in the mempool. Miners pick the highest fee-per-byte txs first. RBF (Replace-By-Fee) lets a sender bump the fee on a stuck tx. CPFP (Child-Pays-For-Parent) lets a receiver pull a stuck parent into a higher-fee block by spending its output with a high-fee child. Mastering these is essential for any payment app.
Fee bumping with RBF.
// BIP-125 (Replace-By-Fee) signaling: tx is replaceable if any input has sequence < 0xfffffffe.
pub fn is_rbf(tx: &Transaction) -> bool {
tx.inputs.iter().any(|i| i.sequence < 0xfffffffe)
}
// To replace a stuck tx, build a new tx that:
// 1. Spends the same inputs (at least one in common)
// 2. Pays a higher absolute fee AND higher fee rate than original
// 3. Replaces fewer than 100 descendants (default policy)
// 4. The replacement's fee rate >= original's fee rate + min_relay_fee
pub fn build_rbf_replacement(original: &Transaction, new_fee_rate: u64) -> Transaction {
let mut replacement = original.clone();
let total_in: u64 = original.inputs.iter().map(|i| get_utxo_value(&i.previous_outpoint)).sum();
let new_fee = new_fee_rate * tx_vsize(&replacement);
// Adjust change output (last output, typically)
let change_out = replacement.outputs.last_mut().unwrap();
let new_change = total_in - other_outputs_total(&replacement) - new_fee;
require!(new_change >= 546, RbfError::DustChange); // dust limit
change_out.value = new_change;
replacement
}
// CPFP alternative: when sender didn't enable RBF, recipient can spend the unconfirmed
// output in a new high-fee tx. Miners include both because the package fee rate is high.
pub fn build_cpfp_child(parent_tx: &Transaction, vout: u32, recipient_addr: &Address, fee_rate: u64) -> Transaction {
// Spends parent's output and pays high fee; miners pull both via package selection
todo!()
}