diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 8648d519..6372b42b 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -262,7 +262,7 @@ impl DaemonControl { addr_info: &Option, ) { if let Some(AddrInfo { index, is_change }) = addr_info { - if *is_change && db_conn.change_index() < *index { + if *is_change && db_conn.change_index() <= *index { let next_index = index .increment() .expect("Must not get into hardened territory"); @@ -1760,9 +1760,46 @@ mod tests { panic!("expect successful spend creation") }; let tx_manual = psbt.unsigned_tx; - // Check that manual and auto selection give same outputs (including change). - assert_eq!(tx_auto.output, tx_manual.output); + // Check that manual and auto selection give same outputs (except change address). + assert_ne!(tx_auto.output, tx_manual.output); + assert_eq!(tx_auto.output.len(), tx_manual.output.len()); + assert_eq!(tx_auto.output[0], tx_manual.output[0]); + assert_eq!(tx_auto.output[1].value, tx_manual.output[1].value); + assert_ne!( + tx_auto.output[1].script_pubkey, + tx_manual.output[1].script_pubkey + ); // Check inputs are also the same. Need to sort as order is not guaranteed by `create_spend`. + let mut auto_input = tx_auto.clone().input; + let mut manual_input = tx_manual.input; + auto_input.sort(); + manual_input.sort(); + assert_eq!(auto_input, manual_input); + + // Now do the same again, but this time specifying the change address to be the same + // as for the auto spend. + let change_address = bitcoin::Address::from_script( + tx_auto.output[1].script_pubkey.as_script(), + bitcoin::Network::Bitcoin, + ) + .unwrap(); + let psbt = if let CreateSpendResult::Success { psbt, .. } = control + .create_spend( + &destinations, + &[confirmed_op_1, confirmed_op_2], + 1, + Some(change_address.as_unchecked().clone()), + ) + .unwrap() + { + psbt + } else { + panic!("expect successful spend creation") + }; + let tx_manual = psbt.unsigned_tx; + // Now the outputs of each transaction are the same. + assert_eq!(tx_auto.output, tx_manual.output); + // Check again that inputs are still the same. let mut auto_input = tx_auto.input; let mut manual_input = tx_manual.input; auto_input.sort(); diff --git a/tests/test_spend.py b/tests/test_spend.py index 3e7224a2..65105116 100644 --- a/tests/test_spend.py +++ b/tests/test_spend.py @@ -423,10 +423,9 @@ def test_coin_selection(lianad, bitcoind): # Recipient details are the same for both. assert spend_psbt_4.tx.vout[0].nValue == psbt_manual.tx.vout[0].nValue assert spend_psbt_4.tx.vout[0].scriptPubKey == psbt_manual.tx.vout[0].scriptPubKey - # Change details are also the same - # (change address is same as neither transaction has been broadcast) + # Change amount is the same (change address will be different). assert spend_psbt_4.tx.vout[1].nValue == psbt_manual.tx.vout[1].nValue - assert spend_psbt_4.tx.vout[1].scriptPubKey == psbt_manual.tx.vout[1].scriptPubKey + assert spend_psbt_4.tx.vout[1].scriptPubKey != psbt_manual.tx.vout[1].scriptPubKey def test_coin_selection_changeless(lianad, bitcoind):