Update RPCs for PSBTv2

This commit is contained in:
Ava Chow 2024-07-22 17:14:36 -04:00
parent 44174d76d0
commit a1d5544d16

View file

@ -182,10 +182,7 @@ PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std
// Fetch previous transactions: // Fetch previous transactions:
// First, look in the txindex and the mempool // First, look in the txindex and the mempool
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) { for (PSBTInput& psbt_input : psbtx.inputs) {
PSBTInput& psbt_input = psbtx.inputs.at(i);
const CTxIn& tx_in = psbtx.tx->vin.at(i);
// The `non_witness_utxo` is the whole previous transaction // The `non_witness_utxo` is the whole previous transaction
if (psbt_input.non_witness_utxo) continue; if (psbt_input.non_witness_utxo) continue;
@ -194,29 +191,26 @@ PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std
// Look in the txindex // Look in the txindex
if (g_txindex) { if (g_txindex) {
uint256 block_hash; uint256 block_hash;
g_txindex->FindTx(tx_in.prevout.hash, block_hash, tx); g_txindex->FindTx(psbt_input.prev_txid, block_hash, tx);
} }
// If we still don't have it look in the mempool // If we still don't have it look in the mempool
if (!tx) { if (!tx) {
tx = node.mempool->get(tx_in.prevout.hash); tx = node.mempool->get(psbt_input.prev_txid);
} }
if (tx) { if (tx) {
psbt_input.non_witness_utxo = tx; psbt_input.non_witness_utxo = tx;
} else { } else {
coins[tx_in.prevout]; // Create empty map entry keyed by prevout coins[psbt_input.GetOutPoint()]; // Create empty map entry keyed by prevout
} }
} }
// If we still haven't found all of the inputs, look for the missing ones in the utxo set // If we still haven't found all of the inputs, look for the missing ones in the utxo set
if (!coins.empty()) { if (!coins.empty()) {
FindCoins(node, coins); FindCoins(node, coins);
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) { for (PSBTInput& input : psbtx.inputs) {
PSBTInput& input = psbtx.inputs.at(i);
// If there are still missing utxos, add them if they were found in the utxo set // If there are still missing utxos, add them if they were found in the utxo set
if (!input.non_witness_utxo) { if (!input.non_witness_utxo) {
const CTxIn& tx_in = psbtx.tx->vin.at(i); const Coin& coin = coins.at(input.GetOutPoint());
const Coin& coin = coins.at(tx_in.prevout);
if (!coin.out.IsNull() && IsSegWitOutput(provider, coin.out.scriptPubKey)) { if (!coin.out.IsNull() && IsSegWitOutput(provider, coin.out.scriptPubKey)) {
input.witness_utxo = coin.out; input.witness_utxo = coin.out;
} }
@ -226,7 +220,7 @@ PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std
const PrecomputedTransactionData& txdata = PrecomputePSBTData(psbtx); const PrecomputedTransactionData& txdata = PrecomputePSBTData(psbtx);
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) { for (unsigned int i = 0; i < psbtx.inputs.size(); ++i) {
if (PSBTInputSigned(psbtx.inputs.at(i))) { if (PSBTInputSigned(psbtx.inputs.at(i))) {
continue; continue;
} }
@ -239,7 +233,7 @@ PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std
} }
// Update script/keypath information using descriptor data. // Update script/keypath information using descriptor data.
for (unsigned int i = 0; i < psbtx.tx->vout.size(); ++i) { for (unsigned int i = 0; i < psbtx.outputs.size(); ++i) {
UpdatePSBTOutput(provider, psbtx, i); UpdatePSBTOutput(provider, psbtx, i);
} }
@ -1101,10 +1095,12 @@ static RPCHelpMan decodepsbt()
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
// Add the decoded tx if (psbtx.tx != std::nullopt) {
UniValue tx_univ(UniValue::VOBJ); // Add the decoded tx
TxToUniv(CTransaction(*psbtx.tx), /*block_hash=*/uint256(), /*entry=*/tx_univ, /*include_hex=*/false); UniValue tx_univ(UniValue::VOBJ);
result.pushKV("tx", std::move(tx_univ)); TxToUniv(CTransaction(*psbtx.tx), /*block_hash=*/uint256(), /*entry=*/tx_univ, /*include_hex=*/false);
result.pushKV("tx", std::move(tx_univ));
}
// Add the global xpubs // Add the global xpubs
UniValue global_xpubs(UniValue::VARR); UniValue global_xpubs(UniValue::VARR);
@ -1170,7 +1166,7 @@ static RPCHelpMan decodepsbt()
have_a_utxo = true; have_a_utxo = true;
} }
if (input.non_witness_utxo) { if (input.non_witness_utxo) {
txout = input.non_witness_utxo->vout[psbtx.tx->vin[i].prevout.n]; txout = input.non_witness_utxo->vout[*input.prev_out];
UniValue non_wit(UniValue::VOBJ); UniValue non_wit(UniValue::VOBJ);
TxToUniv(*input.non_witness_utxo, /*block_hash=*/uint256(), /*entry=*/non_wit, /*include_hex=*/false); TxToUniv(*input.non_witness_utxo, /*block_hash=*/uint256(), /*entry=*/non_wit, /*include_hex=*/false);
@ -1529,8 +1525,8 @@ static RPCHelpMan decodepsbt()
outputs.push_back(std::move(out)); outputs.push_back(std::move(out));
// Fee calculation // Fee calculation
if (MoneyRange(psbtx.tx->vout[i].nValue) && MoneyRange(output_value + psbtx.tx->vout[i].nValue)) { if (MoneyRange(*output.amount) && MoneyRange(output_value + *output.amount)) {
output_value += psbtx.tx->vout[i].nValue; output_value += *output.amount;
} else { } else {
// Hack to just not show fee later // Hack to just not show fee later
have_all_utxos = false; have_all_utxos = false;
@ -1842,29 +1838,32 @@ static RPCHelpMan joinpsbts()
} }
psbtxs.push_back(psbtx); psbtxs.push_back(psbtx);
// Choose the highest version number // Choose the highest version number
if (psbtx.tx->version > best_version) { if (*psbtx.tx_version > best_version) {
best_version = psbtx.tx->version; best_version = *psbtx.tx_version;
} }
// Choose the lowest lock time // Choose the lowest lock time
if (psbtx.tx->nLockTime < best_locktime) { if (*psbtx.fallback_locktime < best_locktime) {
best_locktime = psbtx.tx->nLockTime; best_locktime = *psbtx.fallback_locktime;
} }
} }
// Create a blank psbt where everything will be added // Create a blank psbt where everything will be added
PartiallySignedTransaction merged_psbt; PartiallySignedTransaction merged_psbt;
merged_psbt.tx_version = best_version;
merged_psbt.fallback_locktime = best_locktime;
// TODO: Remove for PSBTv2
merged_psbt.tx = CMutableTransaction(); merged_psbt.tx = CMutableTransaction();
merged_psbt.tx->version = best_version; merged_psbt.tx->version = best_version;
merged_psbt.tx->nLockTime = best_locktime; merged_psbt.tx->nLockTime = best_locktime;
// Merge // Merge
for (auto& psbt : psbtxs) { for (auto& psbt : psbtxs) {
for (unsigned int i = 0; i < psbt.tx->vin.size(); ++i) { for (unsigned int i = 0; i < psbt.inputs.size(); ++i) {
if (!merged_psbt.AddInput(psbt.inputs[i])) { if (!merged_psbt.AddInput(psbt.inputs[i])) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input %s:%d exists in multiple PSBTs", psbt.tx->vin[i].prevout.hash.ToString(), psbt.tx->vin[i].prevout.n)); throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input %s:%d exists in multiple PSBTs", psbt.inputs[i].prev_txid.ToString(), *psbt.inputs[i].prev_out));
} }
} }
for (unsigned int i = 0; i < psbt.tx->vout.size(); ++i) { for (unsigned int i = 0; i < psbt.outputs.size(); ++i) {
merged_psbt.AddOutput(psbt.outputs[i]); merged_psbt.AddOutput(psbt.outputs[i]);
} }
for (auto& xpub_pair : psbt.m_xpubs) { for (auto& xpub_pair : psbt.m_xpubs) {
@ -1888,6 +1887,9 @@ static RPCHelpMan joinpsbts()
std::shuffle(output_indices.begin(), output_indices.end(), FastRandomContext()); std::shuffle(output_indices.begin(), output_indices.end(), FastRandomContext());
PartiallySignedTransaction shuffled_psbt; PartiallySignedTransaction shuffled_psbt;
shuffled_psbt.tx_version = merged_psbt.tx_version;
shuffled_psbt.fallback_locktime = merged_psbt.fallback_locktime;
// TODO: Remove for PSBTv2
shuffled_psbt.tx = CMutableTransaction(); shuffled_psbt.tx = CMutableTransaction();
shuffled_psbt.tx->version = merged_psbt.tx->version; shuffled_psbt.tx->version = merged_psbt.tx->version;
shuffled_psbt.tx->nLockTime = merged_psbt.tx->nLockTime; shuffled_psbt.tx->nLockTime = merged_psbt.tx->nLockTime;