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:
// First, look in the txindex and the mempool
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
PSBTInput& psbt_input = psbtx.inputs.at(i);
const CTxIn& tx_in = psbtx.tx->vin.at(i);
for (PSBTInput& psbt_input : psbtx.inputs) {
// The `non_witness_utxo` is the whole previous transaction
if (psbt_input.non_witness_utxo) continue;
@ -194,29 +191,26 @@ PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std
// Look in the txindex
if (g_txindex) {
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 (!tx) {
tx = node.mempool->get(tx_in.prevout.hash);
tx = node.mempool->get(psbt_input.prev_txid);
}
if (tx) {
psbt_input.non_witness_utxo = tx;
} 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 (!coins.empty()) {
FindCoins(node, coins);
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
PSBTInput& input = psbtx.inputs.at(i);
for (PSBTInput& input : psbtx.inputs) {
// If there are still missing utxos, add them if they were found in the utxo set
if (!input.non_witness_utxo) {
const CTxIn& tx_in = psbtx.tx->vin.at(i);
const Coin& coin = coins.at(tx_in.prevout);
const Coin& coin = coins.at(input.GetOutPoint());
if (!coin.out.IsNull() && IsSegWitOutput(provider, coin.out.scriptPubKey)) {
input.witness_utxo = coin.out;
}
@ -226,7 +220,7 @@ PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std
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))) {
continue;
}
@ -239,7 +233,7 @@ PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std
}
// 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);
}
@ -1101,10 +1095,12 @@ static RPCHelpMan decodepsbt()
UniValue result(UniValue::VOBJ);
// Add the decoded tx
UniValue tx_univ(UniValue::VOBJ);
TxToUniv(CTransaction(*psbtx.tx), /*block_hash=*/uint256(), /*entry=*/tx_univ, /*include_hex=*/false);
result.pushKV("tx", std::move(tx_univ));
if (psbtx.tx != std::nullopt) {
// Add the decoded tx
UniValue tx_univ(UniValue::VOBJ);
TxToUniv(CTransaction(*psbtx.tx), /*block_hash=*/uint256(), /*entry=*/tx_univ, /*include_hex=*/false);
result.pushKV("tx", std::move(tx_univ));
}
// Add the global xpubs
UniValue global_xpubs(UniValue::VARR);
@ -1170,7 +1166,7 @@ static RPCHelpMan decodepsbt()
have_a_utxo = true;
}
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);
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));
// Fee calculation
if (MoneyRange(psbtx.tx->vout[i].nValue) && MoneyRange(output_value + psbtx.tx->vout[i].nValue)) {
output_value += psbtx.tx->vout[i].nValue;
if (MoneyRange(*output.amount) && MoneyRange(output_value + *output.amount)) {
output_value += *output.amount;
} else {
// Hack to just not show fee later
have_all_utxos = false;
@ -1842,29 +1838,32 @@ static RPCHelpMan joinpsbts()
}
psbtxs.push_back(psbtx);
// Choose the highest version number
if (psbtx.tx->version > best_version) {
best_version = psbtx.tx->version;
if (*psbtx.tx_version > best_version) {
best_version = *psbtx.tx_version;
}
// Choose the lowest lock time
if (psbtx.tx->nLockTime < best_locktime) {
best_locktime = psbtx.tx->nLockTime;
if (*psbtx.fallback_locktime < best_locktime) {
best_locktime = *psbtx.fallback_locktime;
}
}
// Create a blank psbt where everything will be added
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->version = best_version;
merged_psbt.tx->nLockTime = best_locktime;
// Merge
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])) {
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]);
}
for (auto& xpub_pair : psbt.m_xpubs) {
@ -1888,6 +1887,9 @@ static RPCHelpMan joinpsbts()
std::shuffle(output_indices.begin(), output_indices.end(), FastRandomContext());
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->version = merged_psbt.tx->version;
shuffled_psbt.tx->nLockTime = merged_psbt.tx->nLockTime;