commands: actually use the change descriptor when creating a Spend

This commit is contained in:
Antoine Poinsot 2022-11-04 19:04:24 +01:00
parent 3b2c9109dd
commit 08505b2545
No known key found for this signature in database
GPG Key ID: E13FC145CD3F4304
2 changed files with 21 additions and 18 deletions

View File

@ -348,7 +348,7 @@ impl DaemonControl {
let change_desc = self
.config
.main_descriptor
.receive_descriptor()
.change_descriptor()
.derive(db_conn.change_index(), &self.secp);
db_conn.increment_change_index(&self.secp);
let mut change_txo = bitcoin::TxOut {
@ -451,7 +451,8 @@ impl DaemonControl {
.list_spend()
.into_iter()
.map(|psbt| {
let change_index = change_index(&psbt).map(|i| i.try_into().expect("insane usize"));
let change_index =
change_index(&psbt, &mut db_conn).map(|i| i.try_into().expect("insane usize"));
ListSpendEntry { psbt, change_index }
})
.collect();

View File

@ -1,3 +1,5 @@
use crate::database::DatabaseConnection;
use miniscript::bitcoin::{self, consensus, util::psbt::PartiallySignedTransaction as Psbt};
use serde::{de, Deserialize, Deserializer, Serializer};
@ -34,21 +36,21 @@ where
}
// Utility to gather the index of a change output in a Psbt, if there is one.
// FIXME: this is temporary! This is based on create_spend's behaviour that reuses the
// first coin address and doesn't shuffle the outputs!
pub fn change_index(psbt: &Psbt) -> Option<usize> {
// We always set the witness UTxO in the PSBTs we create.
let first_coin_spk = match psbt.inputs[0]
.witness_utxo
.as_ref()
.map(|o| &o.script_pubkey)
{
Some(spk) => spk,
None => return None,
};
pub fn change_index(psbt: &Psbt, db_conn: &mut Box<dyn DatabaseConnection>) -> Option<usize> {
let network = db_conn.network();
let tx = &psbt.unsigned_tx;
(0..tx.output.len())
.rev()
.find(|&i| &tx.output[i].script_pubkey == first_coin_spk)
for (i, txo) in psbt.unsigned_tx.output.iter().enumerate() {
// Small optimization. TODO: adapt once we have Taproot support.
if !txo.script_pubkey.is_v0_p2wsh() {
continue;
}
if let Ok(address) = bitcoin::Address::from_script(&txo.script_pubkey, network) {
if let Some((_, true)) = db_conn.derivation_index_by_address(&address) {
return Some(i);
}
}
}
None
}