@@ -1490,12 +1490,19 @@ UniValue converttopsbt(const JSONRPCRequest& request)
1490
1490
1491
1491
UniValue utxoupdatepsbt (const JSONRPCRequest& request)
1492
1492
{
1493
- if (request.fHelp || request.params .size () != 1 ) {
1493
+ if (request.fHelp || request.params .size () < 1 || request. params . size () > 2 ) {
1494
1494
throw std::runtime_error (
1495
1495
RPCHelpMan{" utxoupdatepsbt" ,
1496
- " \n Updates a PSBT with witness UTXOs retrieved from the UTXO set or the mempool.\n " ,
1496
+ " \n Updates all segwit inputs and outputs in a PSBT with data from output descriptors, the UTXO set or the mempool.\n " ,
1497
1497
{
1498
- {" psbt" , RPCArg::Type::STR, RPCArg::Optional::NO, " A base64 string of a PSBT" }
1498
+ {" psbt" , RPCArg::Type::STR, RPCArg::Optional::NO, " A base64 string of a PSBT" },
1499
+ {" descriptors" , RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, " An array of either strings or objects" , {
1500
+ {" " , RPCArg::Type::STR, RPCArg::Optional::OMITTED, " An output descriptor" },
1501
+ {" " , RPCArg::Type::OBJ, RPCArg::Optional::OMITTED, " An object with an output descriptor and extra information" , {
1502
+ {" desc" , RPCArg::Type::STR, RPCArg::Optional::NO, " An output descriptor" },
1503
+ {" range" , RPCArg::Type::RANGE, " 1000" , " Up to what index HD chains should be explored (either end or [begin,end])" },
1504
+ }},
1505
+ }},
1499
1506
},
1500
1507
RPCResult {
1501
1508
" \" psbt\" (string) The base64-encoded partially signed transaction with inputs updated\n "
@@ -1505,7 +1512,7 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request)
1505
1512
}}.ToString ());
1506
1513
}
1507
1514
1508
- RPCTypeCheck (request.params , {UniValue::VSTR}, true );
1515
+ RPCTypeCheck (request.params , {UniValue::VSTR, UniValue::VARR }, true );
1509
1516
1510
1517
// Unserialize the transactions
1511
1518
PartiallySignedTransaction psbtx;
@@ -1514,6 +1521,17 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request)
1514
1521
throw JSONRPCError (RPC_DESERIALIZATION_ERROR, strprintf (" TX decode failed %s" , error));
1515
1522
}
1516
1523
1524
+ // Parse descriptors, if any.
1525
+ FlatSigningProvider provider;
1526
+ if (!request.params [1 ].isNull ()) {
1527
+ auto descs = request.params [1 ].get_array ();
1528
+ for (size_t i = 0 ; i < descs.size (); ++i) {
1529
+ EvalDescriptorStringOrObject (descs[i], provider);
1530
+ }
1531
+ }
1532
+ // We don't actually need private keys further on; hide them as a precaution.
1533
+ HidingSigningProvider public_provider (&provider, /* nosign */ true , /* nobip32derivs */ false );
1534
+
1517
1535
// Fetch previous transactions (inputs):
1518
1536
CCoinsView viewDummy;
1519
1537
CCoinsViewCache view (&viewDummy);
@@ -1540,9 +1558,19 @@ UniValue utxoupdatepsbt(const JSONRPCRequest& request)
1540
1558
1541
1559
const Coin& coin = view.AccessCoin (psbtx.tx ->vin [i].prevout );
1542
1560
1543
- if (IsSegWitOutput (DUMMY_SIGNING_PROVIDER , coin.out .scriptPubKey )) {
1561
+ if (IsSegWitOutput (provider , coin.out .scriptPubKey )) {
1544
1562
input.witness_utxo = coin.out ;
1545
1563
}
1564
+
1565
+ // Update script/keypath information using descriptor data.
1566
+ // Note that SignPSBTInput does a lot more than just constructing ECDSA signatures
1567
+ // we don't actually care about those here, in fact.
1568
+ SignPSBTInput (public_provider, psbtx, i, /* sighash_type */ 1 );
1569
+ }
1570
+
1571
+ // Update script/keypath information using descriptor data.
1572
+ for (unsigned int i = 0 ; i < psbtx.tx ->vout .size (); ++i) {
1573
+ UpdatePSBTOutput (public_provider, psbtx, i);
1546
1574
}
1547
1575
1548
1576
CDataStream ssTx (SER_NETWORK, PROTOCOL_VERSION);
0 commit comments