@@ -169,7 +169,7 @@ static std::vector<RPCArg> CreateTxDoc()
169169 };
170170}
171171
172- // Update PSBT with information from the mempool, the UTXO set, and the provided descriptors
172+ // Update PSBT with information from the mempool, the UTXO set, the txindex, and the provided descriptors
173173PartiallySignedTransaction ProcessPSBT (const std::string& psbt_string, const std::any& context, const HidingSigningProvider& provider)
174174{
175175 // Unserialize the transactions
@@ -179,50 +179,78 @@ PartiallySignedTransaction ProcessPSBT(const std::string& psbt_string, const std
179179 throw JSONRPCError (RPC_DESERIALIZATION_ERROR, strprintf (" TX decode failed %s" , error));
180180 }
181181
182- // Fetch previous transactions (inputs):
183- CCoinsView viewDummy;
184- CCoinsViewCache view (&viewDummy);
185- {
186- NodeContext& node = EnsureAnyNodeContext (context);
187- const CTxMemPool& mempool = EnsureMemPool (node);
188- ChainstateManager& chainman = EnsureChainman (node);
189- LOCK2 (cs_main, mempool.cs );
190- CCoinsViewCache &viewChain = chainman.ActiveChainstate ().CoinsTip ();
191- CCoinsViewMemPool viewMempool (&viewChain, mempool);
192- view.SetBackend (viewMempool); // temporarily switch cache backend to db+mempool view
193-
194- for (const CTxIn& txin : psbtx.tx ->vin ) {
195- view.AccessCoin (txin.prevout ); // Load entries from viewChain into view; can fail.
196- }
182+ if (g_txindex) g_txindex->BlockUntilSyncedToCurrentChain ();
183+ const NodeContext& node = EnsureAnyNodeContext (context);
197184
198- view.SetBackend (viewDummy); // switch back to avoid locking mempool for too long
199- }
185+ // If we can't find the corresponding full transaction for all of our inputs,
186+ // this will be used to find just the utxos for the segwit inputs for which
187+ // the full transaction isn't found
188+ std::map<COutPoint, Coin> coins;
200189
201- // Fill the inputs
202- const PrecomputedTransactionData txdata = PrecomputePSBTData (psbtx);
190+ // Fetch previous transactions:
191+ // First, look in the txindex and the mempool
203192 for (unsigned int i = 0 ; i < psbtx.tx ->vin .size (); ++i) {
204- PSBTInput& input = psbtx.inputs .at (i);
193+ PSBTInput& psbt_input = psbtx.inputs .at (i);
194+ const CTxIn& tx_in = psbtx.tx ->vin .at (i);
205195
206- if (input.non_witness_utxo || !input.witness_utxo .IsNull ()) {
207- continue ;
196+ // The `non_witness_utxo` is the whole previous transaction
197+ if (psbt_input.non_witness_utxo ) continue ;
198+
199+ CTransactionRef tx;
200+
201+ // Look in the txindex
202+ if (g_txindex) {
203+ uint256 block_hash;
204+ g_txindex->FindTx (tx_in.prevout .hash , block_hash, tx);
205+ }
206+ // If we still don't have it look in the mempool
207+ if (!tx) {
208+ tx = node.mempool ->get (tx_in.prevout .hash );
209+ }
210+ if (tx) {
211+ psbt_input.non_witness_utxo = tx;
212+ } else {
213+ coins[tx_in.prevout ]; // Create empty map entry keyed by prevout
214+ }
215+ }
216+
217+ // If we still haven't found all of the inputs, look for the missing ones in the utxo set
218+ if (!coins.empty ()) {
219+ FindCoins (node, coins);
220+ for (unsigned int i = 0 ; i < psbtx.tx ->vin .size (); ++i) {
221+ PSBTInput& input = psbtx.inputs .at (i);
222+
223+ // If there are still missing utxos, add them if they were found in the utxo set
224+ if (!input.non_witness_utxo ) {
225+ const CTxIn& tx_in = psbtx.tx ->vin .at (i);
226+ const Coin& coin = coins.at (tx_in.prevout );
227+ if (!coin.out .IsNull () && IsSegWitOutput (provider, coin.out .scriptPubKey )) {
228+ input.witness_utxo = coin.out ;
229+ }
230+ }
208231 }
232+ }
209233
210- const Coin& coin = view. AccessCoin (psbtx. tx -> vin [i]. prevout );
234+ const PrecomputedTransactionData& txdata = PrecomputePSBTData (psbtx);
211235
212- if (IsSegWitOutput (provider, coin.out .scriptPubKey )) {
213- input.witness_utxo = coin.out ;
236+ for (unsigned int i = 0 ; i < psbtx.tx ->vin .size (); ++i) {
237+ if (PSBTInputSigned (psbtx.inputs .at (i))) {
238+ continue ;
214239 }
215240
216241 // Update script/keypath information using descriptor data.
217242 // Note that SignPSBTInput does a lot more than just constructing ECDSA signatures
218243 // we don't actually care about those here, in fact.
219- SignPSBTInput (provider, psbtx, i, &txdata, /* sighash=*/ 1 );
244+ SignPSBTInput (provider, psbtx, /* index= */ i, &txdata, /* sighash=*/ 1 );
220245 }
221246
222247 // Update script/keypath information using descriptor data.
223248 for (unsigned int i = 0 ; i < psbtx.tx ->vout .size (); ++i) {
224249 UpdatePSBTOutput (provider, psbtx, i);
225250 }
251+
252+ RemoveUnnecessaryTransactions (psbtx, /* sighash_type=*/ 1 );
253+
226254 return psbtx;
227255}
228256
@@ -1632,7 +1660,7 @@ static RPCHelpMan converttopsbt()
16321660static RPCHelpMan utxoupdatepsbt ()
16331661{
16341662 return RPCHelpMan{" utxoupdatepsbt" ,
1635- " \n Updates all segwit inputs and outputs in a PSBT with data from output descriptors, the UTXO set or the mempool.\n " ,
1663+ " \n Updates all segwit inputs and outputs in a PSBT with data from output descriptors, the UTXO set, txindex, or the mempool.\n " ,
16361664 {
16371665 {" psbt" , RPCArg::Type::STR, RPCArg::Optional::NO, " A base64 string of a PSBT" },
16381666 {" descriptors" , RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, " An array of either strings or objects" , {
0 commit comments