From 75989d8cde3902f226bfa89aae05803b93a7cf1d Mon Sep 17 00:00:00 2001 From: valued mammal Date: Tue, 27 Aug 2024 12:24:41 -0400 Subject: [PATCH] test(wallet): Add `test_create_tx_increment_change_index` --- crates/wallet/tests/wallet.rs | 121 ++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/crates/wallet/tests/wallet.rs b/crates/wallet/tests/wallet.rs index 21f391ca6..2a2a68fa6 100644 --- a/crates/wallet/tests/wallet.rs +++ b/crates/wallet/tests/wallet.rs @@ -1392,6 +1392,127 @@ fn test_create_tx_global_xpubs_with_origin() { assert_eq!(psbt.xpub.get(&key), Some(&(fingerprint, path))); } +#[test] +fn test_create_tx_increment_change_index() { + // Test derivation index and unused index of change keychain when creating a transaction + // Cases include wildcard and non-wildcard descriptors with and without an internal keychain + // note the test assumes that the first external address is revealed since we're using + // `receive_output` + struct TestCase { + name: &'static str, + descriptor: &'static str, + change_descriptor: Option<&'static str>, + // amount to send + to_send: u64, + // (derivation index, next unused index) of *change keychain* + expect: (Option, u32), + } + // total wallet funds + let amount = 10_000; + let recipient = Address::from_str("bcrt1q3qtze4ys45tgdvguj66zrk4fu6hq3a3v9pfly5") + .unwrap() + .assume_checked() + .script_pubkey(); + let (desc, change_desc) = get_test_tr_single_sig_xprv_with_change_desc(); + [ + TestCase { + name: "two wildcard, builder error", + descriptor: desc, + change_descriptor: Some(change_desc), + to_send: amount + 1, + // should not use or derive change index + expect: (None, 0), + }, + TestCase { + name: "two wildcard, create change", + descriptor: desc, + change_descriptor: Some(change_desc), + to_send: 5_000, + // should use change index + expect: (Some(0), 1), + }, + TestCase { + name: "two wildcard, no change", + descriptor: desc, + change_descriptor: Some(change_desc), + to_send: 9_850, + // should not use change index + expect: (None, 0), + }, + TestCase { + name: "one wildcard, create change", + descriptor: desc, + change_descriptor: None, + to_send: 5_000, + // should use change index of external keychain + expect: (Some(1), 2), + }, + TestCase { + name: "one wildcard, no change", + descriptor: desc, + change_descriptor: None, + to_send: 9_850, + // should not use change index + expect: (Some(0), 1), + }, + TestCase { + name: "single key, create change", + descriptor: get_test_tr_single_sig(), + change_descriptor: None, + to_send: 5_000, + // single key only has one derivation index (0) + expect: (Some(0), 0), + }, + TestCase { + name: "single key, no change", + descriptor: get_test_tr_single_sig(), + change_descriptor: None, + to_send: 9_850, + expect: (Some(0), 0), + }, + ] + .into_iter() + .for_each(|test| { + // create wallet + let (params, change_keychain) = match test.change_descriptor { + Some(change_desc) => ( + Wallet::create(test.descriptor, change_desc), + KeychainKind::Internal, + ), + None => ( + Wallet::create_single(test.descriptor), + KeychainKind::External, + ), + }; + let mut wallet = params + .network(Network::Regtest) + .create_wallet_no_persist() + .unwrap(); + // fund wallet + receive_output(&mut wallet, amount, ConfirmationTime::unconfirmed(0)); + // create tx + let mut builder = wallet.build_tx(); + builder.add_recipient(recipient.clone(), Amount::from_sat(test.to_send)); + let res = builder.finish(); + if !test.name.contains("error") { + assert!(res.is_ok()); + } + let (exp_derivation_index, exp_next_unused) = test.expect; + assert_eq!( + wallet.derivation_index(change_keychain), + exp_derivation_index, + "derivation index test {}", + test.name, + ); + assert_eq!( + wallet.next_unused_address(change_keychain).index, + exp_next_unused, + "next unused index test {}", + test.name, + ); + }); +} + #[test] fn test_add_foreign_utxo() { let (mut wallet1, _) = get_funded_wallet_wpkh();