Skip to content

Commit

Permalink
docs(wallet): add warning on TxBuilder::allow_shrinking()
Browse files Browse the repository at this point in the history
test(wallet): add test_bump_fee_allow_shrinking test
  • Loading branch information
notmandatory committed Mar 15, 2024
1 parent 3e9f08a commit 21f9d69
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
80 changes: 80 additions & 0 deletions src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3672,6 +3672,86 @@ pub(crate) mod test {
assert_eq!(details.sent, 75_000);
}

#[test]
fn test_bump_fee_allow_shrinking() {
// wallet with one 50_000 sat utxo
let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
// receive an extra 25_000 sat utxo so that our wallet has two utxos
let _incoming_txid = crate::populate_test_db!(
wallet.database.borrow_mut(),
testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
Some(100),
);

let addr1 = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX")
.unwrap()
.assume_checked();
let addr2 = Address::from_str("bcrt1q6m7tyf45hd5swf7ug5f3r35y6htga0m2tlxhfh")
.unwrap()
.assume_checked();
let mut builder = wallet.build_tx();
builder
.add_recipient(addr1.script_pubkey(), 40_000)
.add_recipient(addr2.script_pubkey(), 8_000)
.fee_rate(FeeRate::default_min_relay_fee())
.enable_rbf();
let (psbt, mut original_details) = builder.finish().unwrap();
let mut tx = psbt.extract_tx();
let txid = tx.txid();

// fake tx inputs
for txin in &mut tx.input {
txin.witness.push([0x00; P2WPKH_FAKE_WITNESS_SIZE]); // fake signature
wallet
.database
.borrow_mut()
.del_utxo(&txin.previous_output)
.unwrap();
}
original_details.transaction = Some(tx);
wallet
.database
.borrow_mut()
.set_tx(&original_details)
.unwrap();

// all 50_000 sats from one utxo is sent
assert_eq!(original_details.sent, 50_000);
// 173 sats fee paid, 1 sat/vbyte
assert_eq!(original_details.fee, Some(173));
// 50_000 - 173 - 1827 = full 48_000 sats outputs paid to recipient addresses
assert_eq!(original_details.received, 1827);

// for the new fee rate, it should be enough to reduce the addr2 output
let mut builder = wallet.build_fee_bump(txid).unwrap();
builder
.allow_shrinking(addr2.script_pubkey())
.unwrap()
.fee_rate(FeeRate::from_sat_per_vb(15.0));
let (psbt, rbf_details) = builder.finish().unwrap();
let tx = psbt.extract_tx();

// all 40_000 sats from both utxos is sent
assert_eq!(rbf_details.sent, 50_000);
// 3150 sats fee paid, 15 sat/vbyte
assert_eq!(rbf_details.fee, Some(2130));
// 50_000-2130 = 47_870 instead of 48_000 outputs paid to recipient addresses
assert_eq!(rbf_details.received, 0);
// addr2 was reduced from 4_400 to 1_850 sats
let addr2_output = tx
.output
.into_iter()
.filter(|o| o.script_pubkey.eq(&addr2.script_pubkey()))
.next();
assert!(addr2_output.is_some());
assert_eq!(addr2_output.unwrap().value, 7_870);

// confirm extra 25_000 sat UTXO not included in the original RBF is not spent
let utxos = wallet.list_unspent().unwrap();
assert_eq!(utxos.len(), 1);
assert_eq!(utxos[0].txout.value, 25_000);
}

#[test]
#[should_panic(expected = "InsufficientFunds")]
fn test_bump_fee_remove_output_manually_selected_only() {
Expand Down
4 changes: 4 additions & 0 deletions src/wallet/tx_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,10 @@ impl<'a, D: BatchDatabase> TxBuilder<'a, D, DefaultCoinSelectionAlgorithm, BumpF
/// `script_pubkey` in order to bump the transaction fee. Without specifying this the wallet
/// will attempt to find a change output to shrink instead.
///
/// **Warning**, use with extreme caution. The specified `script_pubkey` will be used _instead_
/// of a change address and if the total transaction input amounts are greater than the required
/// outputs + transaction fee the remaining change sats will also be sent to this address.
///
/// **Note** that the output may shrink to below the dust limit and therefore be removed. If it is
/// preserved then it is currently not guaranteed to be in the same position as it was
/// originally.
Expand Down

0 comments on commit 21f9d69

Please sign in to comment.