@@ -1691,6 +1691,70 @@ UniValue converttopsbt(const JSONRPCRequest& request)
1691
1691
return EncodeBase64 ((unsigned char *)ssTx.data (), ssTx.size ());
1692
1692
}
1693
1693
1694
+ UniValue utxoupdatepsbt (const JSONRPCRequest& request)
1695
+ {
1696
+ if (request.fHelp || request.params .size () != 1 ) {
1697
+ throw std::runtime_error (
1698
+ RPCHelpMan{" utxoupdatepsbt" ,
1699
+ " \n Updates a PSBT with witness UTXOs retrieved from the UTXO set or the mempool.\n " ,
1700
+ {
1701
+ {" psbt" , RPCArg::Type::STR, RPCArg::Optional::NO, " A base64 string of a PSBT" }
1702
+ },
1703
+ RPCResult {
1704
+ " \" psbt\" (string) The base64-encoded partially signed transaction with inputs updated\n "
1705
+ },
1706
+ RPCExamples {
1707
+ HelpExampleCli (" utxoupdatepsbt" , " \" psbt\" " )
1708
+ }}.ToString ());
1709
+ }
1710
+
1711
+ RPCTypeCheck (request.params , {UniValue::VSTR}, true );
1712
+
1713
+ // Unserialize the transactions
1714
+ PartiallySignedTransaction psbtx;
1715
+ std::string error;
1716
+ if (!DecodeBase64PSBT (psbtx, request.params [0 ].get_str (), error)) {
1717
+ throw JSONRPCError (RPC_DESERIALIZATION_ERROR, strprintf (" TX decode failed %s" , error));
1718
+ }
1719
+
1720
+ // Fetch previous transactions (inputs):
1721
+ CCoinsView viewDummy;
1722
+ CCoinsViewCache view (&viewDummy);
1723
+ {
1724
+ LOCK2 (cs_main, mempool.cs );
1725
+ CCoinsViewCache &viewChain = *pcoinsTip;
1726
+ CCoinsViewMemPool viewMempool (&viewChain, mempool);
1727
+ view.SetBackend (viewMempool); // temporarily switch cache backend to db+mempool view
1728
+
1729
+ for (const CTxIn& txin : psbtx.tx ->vin ) {
1730
+ view.AccessCoin (txin.prevout ); // Load entries from viewChain into view; can fail.
1731
+ }
1732
+
1733
+ view.SetBackend (viewDummy); // switch back to avoid locking mempool for too long
1734
+ }
1735
+
1736
+ // Fill the inputs
1737
+ for (unsigned int i = 0 ; i < psbtx.tx ->vin .size (); ++i) {
1738
+ PSBTInput& input = psbtx.inputs .at (i);
1739
+
1740
+ if (input.non_witness_utxo || !input.witness_utxo .IsNull ()) {
1741
+ continue ;
1742
+ }
1743
+
1744
+ const Coin& coin = view.AccessCoin (psbtx.tx ->vin [i].prevout );
1745
+
1746
+ std::vector<std::vector<unsigned char >> solutions_data;
1747
+ txnouttype which_type = Solver (coin.out .scriptPubKey , solutions_data);
1748
+ if (which_type == TX_WITNESS_V0_SCRIPTHASH || which_type == TX_WITNESS_V0_KEYHASH || which_type == TX_WITNESS_UNKNOWN) {
1749
+ input.witness_utxo = coin.out ;
1750
+ }
1751
+ }
1752
+
1753
+ CDataStream ssTx (SER_NETWORK, PROTOCOL_VERSION);
1754
+ ssTx << psbtx;
1755
+ return EncodeBase64 ((unsigned char *)ssTx.data (), ssTx.size ());
1756
+ }
1757
+
1694
1758
// clang-format off
1695
1759
static const CRPCCommand commands[] =
1696
1760
{ // category name actor (function) argNames
@@ -1709,6 +1773,7 @@ static const CRPCCommand commands[] =
1709
1773
{ " rawtransactions" , " finalizepsbt" , &finalizepsbt, {" psbt" , " extract" } },
1710
1774
{ " rawtransactions" , " createpsbt" , &createpsbt, {" inputs" ," outputs" ," locktime" ," replaceable" } },
1711
1775
{ " rawtransactions" , " converttopsbt" , &converttopsbt, {" hexstring" ," permitsigdata" ," iswitness" } },
1776
+ { " rawtransactions" , " utxoupdatepsbt" , &utxoupdatepsbt, {" psbt" } },
1712
1777
1713
1778
{ " blockchain" , " gettxoutproof" , &gettxoutproof, {" txids" , " blockhash" } },
1714
1779
{ " blockchain" , " verifytxoutproof" , &verifytxoutproof, {" proof" } },
0 commit comments