Add Wallet::cancel_tx

To allow you to re-use change addresses from transactions that get cancelled.
This commit is contained in:
LLFourn
2023-02-15 12:52:10 +11:00
committed by Daniela Brozzoni
parent 5985706c1a
commit b310a7afdd
3 changed files with 101 additions and 2 deletions

View File

@@ -5,8 +5,11 @@ use bitcoin::hashes::Hash;
use bitcoin::{BlockHash, Network, Transaction, TxOut};
/// Return a fake wallet that appears to be funded for testing.
pub fn get_funded_wallet(descriptor: &str) -> (Wallet, bitcoin::Txid) {
let mut wallet = Wallet::new_no_persist(descriptor, None, Network::Regtest).unwrap();
pub fn get_funded_wallet_with_change(
descriptor: &str,
change: Option<&str>,
) -> (Wallet, bitcoin::Txid) {
let mut wallet = Wallet::new_no_persist(descriptor, change, Network::Regtest).unwrap();
let address = wallet.get_address(AddressIndex::New).address;
let tx = Transaction {
@@ -38,6 +41,10 @@ pub fn get_funded_wallet(descriptor: &str) -> (Wallet, bitcoin::Txid) {
(wallet, tx.txid())
}
pub fn get_funded_wallet(descriptor: &str) -> (Wallet, bitcoin::Txid) {
get_funded_wallet_with_change(descriptor, None)
}
pub fn get_test_wpkh() -> &'static str {
"wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
}

View File

@@ -3240,3 +3240,72 @@ fn test_taproot_load_descriptor_duplicated_keys() {
"bcrt1pvysh4nmh85ysrkpwtrr8q8gdadhgdejpy6f9v424a8v9htjxjhyqw9c5s5"
);
}
#[test]
/// The wallet should re-use previously allocated change addresses when the tx using them is cancelled
fn test_tx_cancellation() {
macro_rules! new_tx {
($wallet:expr) => {{
let addr = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
let mut builder = $wallet.build_tx();
builder.add_recipient(addr.script_pubkey(), 10_000);
let (psbt, _) = builder.finish().unwrap();
psbt
}};
}
let (mut wallet, _) =
get_funded_wallet_with_change(get_test_wpkh(), Some(get_test_tr_single_sig_xprv()));
let psbt1 = new_tx!(wallet);
let change_derivation_1 = psbt1
.unsigned_tx
.output
.iter()
.find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
.unwrap();
assert_eq!(change_derivation_1, (KeychainKind::Internal, 0));
let psbt2 = new_tx!(wallet);
let change_derivation_2 = psbt2
.unsigned_tx
.output
.iter()
.find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
.unwrap();
assert_eq!(change_derivation_2, (KeychainKind::Internal, 1));
wallet.cancel_tx(&psbt1.extract_tx());
let psbt3 = new_tx!(wallet);
let change_derivation_3 = psbt3
.unsigned_tx
.output
.iter()
.find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
.unwrap();
assert_eq!(change_derivation_3, (KeychainKind::Internal, 0));
let psbt3 = new_tx!(wallet);
let change_derivation_3 = psbt3
.unsigned_tx
.output
.iter()
.find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
.unwrap();
assert_eq!(change_derivation_3, (KeychainKind::Internal, 2));
wallet.cancel_tx(&psbt3.extract_tx());
let psbt3 = new_tx!(wallet);
let change_derivation_4 = psbt3
.unsigned_tx
.output
.iter()
.find_map(|txout| wallet.derivation_of_spk(&txout.script_pubkey))
.unwrap();
assert_eq!(change_derivation_4, (KeychainKind::Internal, 2));
}