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 4, 2024
1 parent 213c270 commit 9a83b5b
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
75 changes: 75 additions & 0 deletions src/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3672,6 +3672,81 @@ 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(), 70_000)
.add_recipient(addr2.script_pubkey(), 4_400)
.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 75_000 sats from both utxos is sent
assert_eq!(original_details.sent, 75_000);
// 241 sats fee paid, 1 sat/vbyte
assert_eq!(original_details.fee, Some(241));
// 75_000-241-359 = full 74_400 sats outputs paid to recipient addresses
assert_eq!(original_details.received, 359);

// 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 75_000 sats from both utxos is sent
assert_eq!(rbf_details.sent, 75_000);
// 3150 sats fee paid, 15 sat/vbyte
assert_eq!(rbf_details.fee, Some(3150));
// 75_000-3150 = reduced 71_850 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, 1_850);
}

#[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 9a83b5b

Please sign in to comment.