diff --git a/doc/API.md b/doc/API.md index d35f2402..096abb0b 100644 --- a/doc/API.md +++ b/doc/API.md @@ -341,9 +341,9 @@ feerate. #### Response -| Field | Type | Description | -| ---------- | ------ | ----------------------------------------------- | -| `spend_tx` | string | Base64-encoded Spend transaction PSBT | +| Field | Type | Description | +| ---------- | ----------------------------------------------------------- | ------------------------------ | +| `spend_tx` | [Spend transaction resources](#spend_transaction_resources) | Spend transaction informations | ### `updatespendtx` @@ -401,7 +401,7 @@ Please note that this status refers only to the Spend transaction, with regardin | Field | Type | Description | | -------------- | ------ | -------------------------------------------------------------------- | -| `spend_txs` | array | Array of [Spend transaction resources](#spend_transaction_reources) | +| `spend_txs` | array | Array of [Spend transaction resources](#spend_transaction_resources) | ##### Spend transaction resources diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 279cf6a8..40d19c72 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -35,7 +35,7 @@ use crate::{ }; use utils::{ deser_amount_from_sats, deser_from_str, finalized_emer_txs, gethistory, listvaults_from_db, - presigned_txs, ser_amount, ser_to_string, unvault_tx, vaults_from_deposits, + presigned_txs, ser_amount, ser_to_string, spend_entry, unvault_tx, vaults_from_deposits, }; use revault_tx::{ @@ -43,15 +43,13 @@ use revault_tx::{ consensus::encode, secp256k1, util::bip32, Address, Amount, Network, OutPoint, PublicKey as BitcoinPubKey, Transaction as BitcoinTransaction, TxOut, Txid, }, - miniscript::DescriptorTrait, scripts::{CpfpDescriptor, DepositDescriptor, UnvaultDescriptor}, transactions::{ spend_tx_from_deposits, transaction_chain, transaction_chain_manager, CancelTransaction, CpfpableTransaction, EmergencyTransaction, RevaultPresignedTransaction, RevaultTransaction, SpendTransaction, UnvaultEmergencyTransaction, UnvaultTransaction, }, - txins::RevaultTxIn, - txouts::{DepositTxOut, RevaultTxOut, SpendTxOut}, + txouts::{DepositTxOut, SpendTxOut}, }; use std::{collections::BTreeMap, fmt}; @@ -929,7 +927,7 @@ impl DaemonControl { outpoints: &[OutPoint], destinations: &BTreeMap, feerate_vb: u64, - ) -> Result { + ) -> Result { let revaultd = self.revaultd.read().unwrap(); manager_only!(revaultd); let db_file = &revaultd.db_file(); @@ -937,6 +935,8 @@ impl DaemonControl { // FIXME: have a feerate type to avoid that assert!(feerate_vb > 0, "Spend feerate can't be null."); + // TODO: remove the txins vec, just use the spent_vaults one. + let mut spent_vaults = Vec::with_capacity(outpoints.len()); // Reconstruct the DepositTxin s from the outpoints and the vaults informations let mut txins = Vec::with_capacity(outpoints.len()); // If we need a change output, use the highest derivation index of the vaults @@ -952,6 +952,7 @@ impl DaemonControl { change_index = vault.derivation_index; } txins.push((*outpoint, vault.amount, vault.derivation_index)); + spent_vaults.push(vault); } else { return Err(CommandError::InvalidStatus( vault.status, @@ -1076,7 +1077,12 @@ impl DaemonControl { }; log::debug!("Final Spend transaction: '{:?}'", tx_res); - Ok(tx_res) + Ok(spend_entry( + &revaultd, + tx_res, + spent_vaults.iter(), + ListSpendStatus::NonFinal, + )) } /// Store a new or update an existing Spend transaction in database. @@ -1172,7 +1178,7 @@ impl DaemonControl { let spend_tx_map = db_list_spends(&db_path).expect("Database must be available"); let mut listspend_entries = Vec::with_capacity(spend_tx_map.len()); - for (_, (db_spend, deposit_outpoints)) in spend_tx_map { + for (_, (db_spend, _)) in spend_tx_map { let mut status = match db_spend.broadcasted { Some(true) => ListSpendStatus::Broadcasted, Some(false) => ListSpendStatus::Pending, @@ -1204,62 +1210,12 @@ impl DaemonControl { } } - let (deposit_amount, mut cpfp_amount) = spent_vaults.iter().fold( - (Amount::from_sat(0), Amount::from_sat(0)), - |(deposit_total, cpfp_total), (_, vault)| { - let unvault = unvault_tx(&revaultd, vault) - .expect("Spent vault must have a correct unvault transaction"); - - let cpfp_amount = Amount::from_sat( - unvault - .cpfp_txin(&revaultd.cpfp_descriptor, &revaultd.secp_ctx) - .expect("Unvault tx has always a cpfp output") - .txout() - .txout() - .value, - ); - - (deposit_total + vault.amount, cpfp_total + cpfp_amount) - }, - ); - - let derivation_index = spent_vaults - .values() - .map(|v| v.derivation_index) - .max() - .expect("Spent vaults should not be empty"); - let cpfp_script_pubkey = revaultd - .cpfp_descriptor - .derive(derivation_index, &revaultd.secp_ctx) - .into_inner() - .script_pubkey(); - let deposit_address = revaultd - .deposit_descriptor - .derive(derivation_index, &revaultd.secp_ctx) - .into_inner() - .script_pubkey(); - let mut cpfp_index = None; - let mut change_index = None; - for (i, txout) in db_spend.psbt.tx().output.iter().enumerate() { - if cpfp_index.is_none() && cpfp_script_pubkey == txout.script_pubkey { - cpfp_index = Some(i); - cpfp_amount += Amount::from_sat(txout.value); - } - - if deposit_address == txout.script_pubkey { - change_index = Some(i); - } - } - - listspend_entries.push(ListSpendEntry { - psbt: db_spend.psbt, - deposit_outpoints, - deposit_amount, - cpfp_amount, - cpfp_index: cpfp_index.expect("We always create a CPFP output"), - change_index, + listspend_entries.push(spend_entry( + &revaultd, + db_spend.psbt, + spent_vaults.values(), status, - }); + )); } Ok(listspend_entries) diff --git a/src/commands/utils.rs b/src/commands/utils.rs index c73b567b..4da536eb 100644 --- a/src/commands/utils.rs +++ b/src/commands/utils.rs @@ -4,7 +4,8 @@ use crate::{ commands::{ - CommandError, HistoryEvent, HistoryEventKind, ListPresignedTxEntry, ListVaultsEntry, + CommandError, HistoryEvent, HistoryEventKind, ListPresignedTxEntry, ListSpendEntry, + ListSpendStatus, ListVaultsEntry, }, database::{ interface::{ @@ -21,18 +22,20 @@ use crate::{ use revault_tx::{ bitcoin::{ - consensus::encode, hashes::hex::FromHex, Amount, OutPoint, + consensus::encode, hashes::hex::FromHex, util::bip32, Amount, OutPoint, Transaction as BitcoinTransaction, Txid, }, miniscript::DescriptorTrait, transactions::{ - transaction_chain_manager, CpfpableTransaction, RevaultTransaction, UnvaultTransaction, + transaction_chain_manager, CpfpableTransaction, RevaultTransaction, SpendTransaction, + UnvaultTransaction, }, txins::{DepositTxIn, RevaultTxIn}, txouts::{DepositTxOut, RevaultTxOut}, }; use std::{ + cmp, collections::{HashMap, HashSet}, fmt, str::FromStr, @@ -490,6 +493,82 @@ pub fn gethistory( Ok(events) } +/// Get the ListSpendEntry for a given Spend transaction. +/// This relies on brittle assumptions about how we construct the Spend. Those might not hold if +/// used on a Spend PSBT we did not create. +pub fn spend_entry<'a>( + revaultd: &RevaultD, + psbt: SpendTransaction, + spent_vaults: impl IntoIterator, + status: ListSpendStatus, +) -> ListSpendEntry { + // The derivation index for the change is assumed to be reusing the largest one of the inputs. + let (deposit_amount, mut cpfp_amount, deposit_outpoints, derivation_index) = + spent_vaults.into_iter().fold( + ( + Amount::from_sat(0), + Amount::from_sat(0), + Vec::new(), + bip32::ChildNumber::from(0), + ), + |(deposit_total, cpfp_total, mut deposit_outpoints, derivation_index), vault| { + deposit_outpoints.push(vault.deposit_outpoint); + + let unvault = unvault_tx(&revaultd, &vault) + .expect("Spent vault must have a correct unvault transaction"); + let cpfp_amount = Amount::from_sat( + unvault + .cpfp_txin(&revaultd.cpfp_descriptor, &revaultd.secp_ctx) + .expect("Unvault tx has always a cpfp output") + .txout() + .txout() + .value, + ); + + ( + deposit_total + vault.amount, + cpfp_total + cpfp_amount, + deposit_outpoints, + cmp::max(derivation_index, vault.derivation_index), + ) + }, + ); + + let cpfp_script_pubkey = revaultd + .cpfp_descriptor + .derive(derivation_index, &revaultd.secp_ctx) + .into_inner() + .script_pubkey(); + let deposit_address = revaultd + .deposit_descriptor + .derive(derivation_index, &revaultd.secp_ctx) + .into_inner() + .script_pubkey(); + let mut cpfp_index = None; + let mut change_index = None; + for (i, txout) in psbt.tx().output.iter().enumerate() { + if cpfp_index.is_none() && cpfp_script_pubkey == txout.script_pubkey { + cpfp_index = Some(i); + cpfp_amount += Amount::from_sat(txout.value); + } + + if deposit_address == txout.script_pubkey { + change_index = Some(i); + } + } + + ListSpendEntry { + psbt, + deposit_outpoints, + deposit_amount, + cpfp_amount, + // FIXME: this won't hold post optional-CPFP + cpfp_index: cpfp_index.expect("We always have a CPFP index"), + change_index, + status, + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/tests/test_chain.py b/tests/test_chain.py index 0d2128a2..2065c3cd 100644 --- a/tests/test_chain.py +++ b/tests/test_chain.py @@ -676,7 +676,7 @@ def test_retrieve_vault_status(revault_network, bitcoind): revault_network.activate_vault(vault) deposits = [f"{vault['txid']}:{vault['vout']}"] destinations = {bitcoind.rpc.getnewaddress(): vault["amount"] // 2} - spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"] + spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"]["psbt"] for m in [man] + mans: spend_tx = m.man_keychain.sign_spend_psbt(spend_tx, [vault["derivation_index"]]) mans[0].rpc.updatespendtx(spend_tx) @@ -719,7 +719,7 @@ def test_retrieve_vault_status(revault_network, bitcoind): revault_network.activate_vault(vault) deposits = [f"{vault['txid']}:{vault['vout']}"] destinations = {bitcoind.rpc.getnewaddress(): vault["amount"] // 2} - spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"] + spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"]["psbt"] for m in [man] + mans: spend_tx = m.man_keychain.sign_spend_psbt(spend_tx, [vault["derivation_index"]]) mans[0].rpc.updatespendtx(spend_tx) @@ -759,7 +759,7 @@ def test_retrieve_vault_status(revault_network, bitcoind): revault_network.activate_vault(vault) deposits = [f"{vault['txid']}:{vault['vout']}"] destinations = {bitcoind.rpc.getnewaddress(): vault["amount"] // 2} - spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"] + spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"]["psbt"] for m in [man] + mans: spend_tx = m.man_keychain.sign_spend_psbt(spend_tx, [vault["derivation_index"]]) mans[0].rpc.updatespendtx(spend_tx) @@ -800,7 +800,7 @@ def test_retrieve_vault_status(revault_network, bitcoind): revault_network.activate_vault(vault) deposits = [f"{vault['txid']}:{vault['vout']}"] destinations = {bitcoind.rpc.getnewaddress(): vault["amount"] // 2} - spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"] + spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"]["psbt"] for m in [man] + mans: spend_tx = m.man_keychain.sign_spend_psbt(spend_tx, [vault["derivation_index"]]) mans[0].rpc.updatespendtx(spend_tx) @@ -842,7 +842,7 @@ def test_retrieve_vault_status(revault_network, bitcoind): revault_network.activate_vault(vault) deposits = [f"{vault['txid']}:{vault['vout']}"] destinations = {bitcoind.rpc.getnewaddress(): vault["amount"] // 2} - spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"] + spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"]["psbt"] for m in [man] + mans: spend_tx = m.man_keychain.sign_spend_psbt(spend_tx, [vault["derivation_index"]]) mans[0].rpc.updatespendtx(spend_tx) @@ -876,7 +876,7 @@ def test_retrieve_vault_status(revault_network, bitcoind): revault_network.activate_vault(vault) deposits = [f"{vault['txid']}:{vault['vout']}"] destinations = {bitcoind.rpc.getnewaddress(): vault["amount"] // 2} - spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"] + spend_tx = mans[0].rpc.getspendtx(deposits, destinations, 1)["spend_tx"]["psbt"] for m in [man] + mans: spend_tx = m.man_keychain.sign_spend_psbt(spend_tx, [vault["derivation_index"]]) mans[0].rpc.updatespendtx(spend_tx) diff --git a/tests/test_framework/revault_network.py b/tests/test_framework/revault_network.py index 28b39c49..0a840f85 100644 --- a/tests/test_framework/revault_network.py +++ b/tests/test_framework/revault_network.py @@ -608,7 +608,9 @@ def broadcast_unvaults(self, vaults, destinations, feerate, priority=False): deriv_indexes.append(v["derivation_index"]) man.wait_for_active_vaults(deposits) - spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"] + spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"][ + "psbt" + ] for man in self.mans(): spend_tx = man.man_keychain.sign_spend_psbt(spend_tx, deriv_indexes) man.rpc.updatespendtx(spend_tx) @@ -654,7 +656,9 @@ def spend_vaults_unconfirmed(self, vaults, destinations, feerate, priority=False for man in self.mans(): man.wait_for_active_vaults(deposits) - spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"] + spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"][ + "psbt" + ] for man in self.mans(): spend_tx = man.man_keychain.sign_spend_psbt(spend_tx, deriv_indexes) man.rpc.updatespendtx(spend_tx) diff --git a/tests/test_rpc.py b/tests/test_rpc.py index 95fe3421..3ef54809 100644 --- a/tests/test_rpc.py +++ b/tests/test_rpc.py @@ -265,7 +265,7 @@ def test_listspendtxs(revault_network, bitcoind): deposits.append(f"{v['txid']}:{v['vout']}") deriv_indexes.append(v["derivation_index"]) man.wait_for_active_vaults(deposits) - spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"] + spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"]["psbt"] for man in rn.mans(): spend_tx = man.man_keychain.sign_spend_psbt(spend_tx, deriv_indexes) @@ -879,16 +879,27 @@ def test_getspendtx(revault_network, bitcoind): # The amount was not enough to afford a change output, everything went to # fees. + spend_tx = man.rpc.getspendtx(spent_vaults, destination, feerate)["spend_tx"] + assert spend_tx["deposit_outpoints"] == [deposit] + assert spend_tx["deposit_amount"] == amount * 100_000_000 + assert spend_tx["cpfp_amount"] == 44336 + assert spend_tx["change_index"] is None + assert spend_tx["cpfp_index"] == 0 + assert spend_tx["status"] == "non_final" psbt = serializations.PSBT() - psbt.deserialize(man.rpc.getspendtx(spent_vaults, destination, feerate)["spend_tx"]) + psbt.deserialize(spend_tx["psbt"]) assert len(psbt.inputs) == 1 and len(psbt.outputs) == 2 # But if we decrease it enough, it'll create a change output destinations = {addr: vault["amount"] - fees - 1_000_000} + spend_tx = man.rpc.getspendtx(spent_vaults, destinations, feerate)["spend_tx"] + assert spend_tx["deposit_outpoints"] == [deposit] + assert spend_tx["deposit_amount"] == amount * 100_000_000 + assert spend_tx["cpfp_amount"] == 47088 + assert spend_tx["change_index"] is not None + assert spend_tx["status"] == "non_final" psbt = serializations.PSBT() - psbt.deserialize( - man.rpc.getspendtx(spent_vaults, destinations, feerate)["spend_tx"] - ) + psbt.deserialize(spend_tx["psbt"]) assert len(psbt.inputs) == 1 and len(psbt.outputs) == 3 # Asking for an impossible feerate will error @@ -929,7 +940,7 @@ def test_getspendtx(revault_network, bitcoind): destinations = {addr: sent_amount} psbt = serializations.PSBT() psbt.deserialize( - man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"] + man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"]["psbt"] ) assert ( len(psbt.inputs) == len(deposits) and len(psbt.outputs) == 2 @@ -943,7 +954,7 @@ def test_getspendtx(revault_network, bitcoind): destinations[bitcoind.rpc.getnewaddress()] = vault["amount"] // 20 psbt = serializations.PSBT() psbt.deserialize( - man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"] + man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"]["psbt"] ) assert ( len(psbt.inputs) == len(deposits) @@ -954,11 +965,19 @@ def test_getspendtx(revault_network, bitcoind): # And we can do both deposits = [] destinations = {} + total_amount = 0 for vault in man.rpc.listvaults(["active"])["vaults"]: + total_amount += vault["amount"] deposits.append(f"{vault['txid']}:{vault['vout']}") destinations[bitcoind.rpc.getnewaddress()] = vault["amount"] // 2 + + spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"] + assert spend_tx["deposit_outpoints"] == deposits + assert spend_tx["deposit_amount"] == total_amount + assert spend_tx["change_index"] is not None + assert spend_tx["status"] == "non_final" psbt = serializations.PSBT() - psbt.deserialize(man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"]) + psbt.deserialize(spend_tx["psbt"]) assert ( len(psbt.inputs) == len(deposits) # destinations + CPFP + change diff --git a/tests/test_spend.py b/tests/test_spend.py index 1a773973..283d3d37 100644 --- a/tests/test_spend.py +++ b/tests/test_spend.py @@ -90,7 +90,9 @@ def test_spendtx_management(revault_network, bitcoind): revault_network.secure_vault(vault) revault_network.activate_vault(vault) - spend_tx = man.rpc.getspendtx(spent_vaults, destination, feerate)["spend_tx"] + spend_tx = man.rpc.getspendtx(spent_vaults, destination, feerate)["spend_tx"][ + "psbt" + ] # If we are not a manager, it'll fail with pytest.raises(RpcError, match="This is a manager command"): @@ -140,7 +142,9 @@ def test_spendtx_management(revault_network, bitcoind): } revault_network.secure_vault(vault_b) revault_network.activate_vault(vault_b) - spend_tx_b = man.rpc.getspendtx(spent_vaults, destination, feerate)["spend_tx"] + spend_tx_b = man.rpc.getspendtx(spent_vaults, destination, feerate)["spend_tx"][ + "psbt" + ] man.rpc.updatespendtx(spend_tx_b) man.wait_for_log("Storing new Spend transaction") spend_txs = man.rpc.listspendtxs()["spend_txs"] @@ -155,6 +159,14 @@ def test_spendtx_management(revault_network, bitcoind): "status": "non_final", } in spend_txs assert { + "deposit_outpoints": [deposit_b, deposit], + "deposit_amount": vault["amount"] + vault_b["amount"], + "cpfp_amount": 95808, + "psbt": spend_tx_b, + "change_index": 3, + "cpfp_index": 0, + "status": "non_final", + } in spend_txs or { "deposit_outpoints": [deposit, deposit_b], "deposit_amount": vault["amount"] + vault_b["amount"], "cpfp_amount": 95808, @@ -201,7 +213,7 @@ def test_spendtx_management(revault_network, bitcoind): revault_network.activate_vault(vault_c) rogue_spend_tx = man.rpc.getspendtx(rogue_spent_vaults, destination, feerate)[ "spend_tx" - ] + ]["psbt"] deriv_indexes = deriv_indexes + [vault_c["derivation_index"]] for man in revault_network.mans(): rogue_spend_tx = man.man_keychain.sign_spend_psbt(rogue_spend_tx, deriv_indexes) @@ -263,7 +275,8 @@ def test_spendtx_management(revault_network, bitcoind): # The spend is confirmed spend_tx = txs[0] - assert spend_tx["deposit_outpoints"] == [deposit, deposit_b] + assert deposit in spend_tx["deposit_outpoints"] + assert deposit_b in spend_tx["deposit_outpoints"] assert spend_tx["deposit_amount"] == vault["amount"] + vault_b["amount"] assert spend_tx["cpfp_amount"] == 95808 assert spend_tx["change_index"] == 3 @@ -272,7 +285,9 @@ def test_spendtx_management(revault_network, bitcoind): # The conflicting spend is deprecated rogue_spend_tx = txs[1] - assert rogue_spend_tx["deposit_outpoints"] == [deposit, deposit_b, deposit_c] + assert deposit in rogue_spend_tx["deposit_outpoints"] + assert deposit_b in rogue_spend_tx["deposit_outpoints"] + assert deposit_c in rogue_spend_tx["deposit_outpoints"] assert ( rogue_spend_tx["deposit_amount"] == vault["amount"] + vault_b["amount"] + vault_c["amount"] @@ -313,14 +328,14 @@ def test_spends_concurrent(revault_network, bitcoind): # Spending to a P2WSH (effectively a change but hey), with a change output destinations = {man.rpc.getdepositaddress()["address"]: sum(amounts_a) // 2} - spend_tx_a = man.rpc.getspendtx(deposits_a, destinations, 1)["spend_tx"] + spend_tx_a = man.rpc.getspendtx(deposits_a, destinations, 1)["spend_tx"]["psbt"] for man in revault_network.mans(): spend_tx_a = man.man_keychain.sign_spend_psbt(spend_tx_a, indexes_a) man.rpc.updatespendtx(spend_tx_a) # Spending to a P2WPKH, with a change output destinations = {bitcoind.rpc.getnewaddress(): sum(amounts_b) // 2} - spend_tx_b = man.rpc.getspendtx(deposits_b, destinations, 1)["spend_tx"] + spend_tx_b = man.rpc.getspendtx(deposits_b, destinations, 1)["spend_tx"]["psbt"] for man in revault_network.mans(): spend_tx_b = man.man_keychain.sign_spend_psbt(spend_tx_b, indexes_b) man.rpc.updatespendtx(spend_tx_b) @@ -411,7 +426,7 @@ def test_spends_conflicting(revault_network, bitcoind): feerate = 5_000 fees = revault_network.compute_spendtx_fees(feerate, len(deposits_a), 1) destinations = {bitcoind.rpc.getnewaddress(): sum(amounts_a) - fees} - spend_tx_a = man.rpc.getspendtx(deposits_a, destinations, 1)["spend_tx"] + spend_tx_a = man.rpc.getspendtx(deposits_a, destinations, 1)["spend_tx"]["psbt"] for man in revault_network.mans(): spend_tx_a = man.man_keychain.sign_spend_psbt(spend_tx_a, indexes_a) man.rpc.updatespendtx(spend_tx_a) @@ -419,7 +434,7 @@ def test_spends_conflicting(revault_network, bitcoind): feerate = 10_000 fees = revault_network.compute_spendtx_fees(feerate, len(deposits_b), 1, True) destinations = {bitcoind.rpc.getnewaddress(): (sum(amounts_b) - fees) // 2} - spend_tx_b = man.rpc.getspendtx(deposits_b, destinations, 1)["spend_tx"] + spend_tx_b = man.rpc.getspendtx(deposits_b, destinations, 1)["spend_tx"]["psbt"] for man in revault_network.mans(): spend_tx_b = man.man_keychain.sign_spend_psbt(spend_tx_b, indexes_b) man.rpc.updatespendtx(spend_tx_b) @@ -504,7 +519,7 @@ def test_spend_threshold(revault_network, bitcoind, executor): bitcoind.rpc.getnewaddress(): (total_amount - fees) // n_outputs for _ in range(n_outputs) } - spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"] + spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"]["psbt"] # Trying to broadcast when managers_threshold - 1 managers signed for man in revault_network.mans()[: managers_threshold - 1]: @@ -610,7 +625,7 @@ def test_large_spends(revault_network, bitcoind, executor): bitcoind.rpc.getnewaddress(): (total_amount - fees) // n_outputs for _ in range(n_outputs) } - spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"] + spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"]["psbt"] for man in revault_network.mans(): spend_tx = man.man_keychain.sign_spend_psbt(spend_tx, deriv_indexes) @@ -702,7 +717,7 @@ def test_not_announceable_spend(revault_network, bitcoind, executor): output_value = int((total_amount - fees) // n_outputs) for addr in destinations: destinations[addr] = output_value - spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"] + spend_tx = man.rpc.getspendtx(deposits, destinations, feerate)["spend_tx"]["psbt"] for man in revault_network.mans(): spend_tx = man.man_keychain.sign_spend_psbt(spend_tx, deriv_indexes) man.rpc.updatespendtx(spend_tx)