@@ -1456,22 +1456,30 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
14561456
14571457 const std::string& descriptor = data[" desc" ].get_str ();
14581458 const bool active = data.exists (" active" ) ? data[" active" ].get_bool () : false ;
1459- const bool internal = data.exists (" internal" ) ? data[" internal" ].get_bool () : false ;
14601459 const std::string& label = data.exists (" label" ) ? data[" label" ].get_str () : " " ;
14611460
14621461 // Parse descriptor string
14631462 FlatSigningProvider keys;
14641463 std::string error;
1465- auto parsed_desc = Parse (descriptor, keys, error, /* require_checksum = */ true ). first ;
1466- if (!parsed_desc ) {
1464+ auto parsed_descs = Parse (descriptor, keys, error, /* require_checksum = */ true );
1465+ if (!parsed_descs. first ) {
14671466 throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, error);
14681467 }
14691468
1469+ std::optional<bool > internal;
1470+ bool multipath = parsed_descs.second != nullptr ;
1471+ if (data.exists (" internal" )) {
1472+ if (multipath) {
1473+ throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, " Cannot have multipath descriptor while also specifying \' internal\' " );
1474+ }
1475+ internal = data[" internal" ].get_bool ();
1476+ }
1477+
14701478 // Range check
14711479 int64_t range_start = 0 , range_end = 1 , next_index = 0 ;
1472- if (!parsed_desc ->IsRange () && data.exists (" range" )) {
1480+ if (!parsed_descs. first ->IsRange () && data.exists (" range" )) {
14731481 throw JSONRPCError (RPC_INVALID_PARAMETER, " Range should not be specified for an un-ranged descriptor" );
1474- } else if (parsed_desc ->IsRange ()) {
1482+ } else if (parsed_descs. first ->IsRange ()) {
14751483 if (data.exists (" range" )) {
14761484 auto range = ParseDescriptorRange (data[" range" ]);
14771485 range_start = range.first ;
@@ -1493,10 +1501,15 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
14931501 }
14941502
14951503 // Active descriptors must be ranged
1496- if (active && !parsed_desc ->IsRange ()) {
1504+ if (active && !parsed_descs. first ->IsRange ()) {
14971505 throw JSONRPCError (RPC_INVALID_PARAMETER, " Active descriptors must be ranged" );
14981506 }
14991507
1508+ // Multipath descriptors should not have a label
1509+ if (multipath && data.exists (" label" )) {
1510+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Multipath descriptors should not have a label" );
1511+ }
1512+
15001513 // Ranged descriptors should not have a label
15011514 if (data.exists (" range" ) && data.exists (" label" )) {
15021515 throw JSONRPCError (RPC_INVALID_PARAMETER, " Ranged descriptors should not have a label" );
@@ -1508,7 +1521,7 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
15081521 }
15091522
15101523 // Combo descriptor check
1511- if (active && !parsed_desc ->IsSingleType ()) {
1524+ if (active && !parsed_descs. first ->IsSingleType ()) {
15121525 throw JSONRPCError (RPC_WALLET_ERROR, " Combo descriptors cannot be set to active" );
15131526 }
15141527
@@ -1517,61 +1530,64 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
15171530 throw JSONRPCError (RPC_WALLET_ERROR, " Cannot import private keys to a wallet with private keys disabled" );
15181531 }
15191532
1520- // Need to ExpandPrivate to check if private keys are available for all pubkeys
1521- FlatSigningProvider expand_keys;
1522- std::vector<CScript> scripts;
1523- if (!parsed_desc->Expand (0 , keys, scripts, expand_keys)) {
1524- throw JSONRPCError (RPC_WALLET_ERROR, " Cannot expand descriptor. Probably because of hardened derivations without private keys provided" );
1525- }
1526- parsed_desc->ExpandPrivate (0 , keys, expand_keys);
1527-
1528- // Check if all private keys are provided
1529- bool have_all_privkeys = !expand_keys.keys .empty ();
1530- for (const auto & entry : expand_keys.origins ) {
1531- const CKeyID& key_id = entry.first ;
1532- CKey key;
1533- if (!expand_keys.GetKey (key_id, key)) {
1534- have_all_privkeys = false ;
1535- break ;
1533+ for (int j = 0 ; j < (multipath ? 2 : 1 ); ++j) {
1534+ auto parsed_desc = j ? std::move (parsed_descs.second ) : std::move (parsed_descs.first );
1535+ // Need to ExpandPrivate to check if private keys are available for all pubkeys
1536+ FlatSigningProvider expand_keys;
1537+ std::vector<CScript> scripts;
1538+ if (!parsed_desc->Expand (0 , keys, scripts, expand_keys)) {
1539+ throw JSONRPCError (RPC_WALLET_ERROR, " Cannot expand descriptor. Probably because of hardened derivations without private keys provided" );
1540+ }
1541+ parsed_desc->ExpandPrivate (0 , keys, expand_keys);
1542+
1543+ // Check if all private keys are provided
1544+ bool have_all_privkeys = !expand_keys.keys .empty ();
1545+ for (const auto & entry : expand_keys.origins ) {
1546+ const CKeyID& key_id = entry.first ;
1547+ CKey key;
1548+ if (!expand_keys.GetKey (key_id, key)) {
1549+ have_all_privkeys = false ;
1550+ break ;
1551+ }
15361552 }
1537- }
15381553
1539- // If private keys are enabled, check some things.
1540- if (!wallet.IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
1541- if (keys.keys .empty ()) {
1542- throw JSONRPCError (RPC_WALLET_ERROR, " Cannot import descriptor without private keys to a wallet with private keys enabled" );
1543- }
1544- if (!have_all_privkeys) {
1545- warnings.push_back (" Not all private keys provided. Some wallet functionality may return unexpected errors" );
1546- }
1547- }
1554+ // If private keys are enabled, check some things.
1555+ if (!wallet.IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
1556+ if (keys.keys .empty ()) {
1557+ throw JSONRPCError (RPC_WALLET_ERROR, " Cannot import descriptor without private keys to a wallet with private keys enabled" );
1558+ }
1559+ if (!have_all_privkeys) {
1560+ warnings.push_back (" Not all private keys provided. Some wallet functionality may return unexpected errors" );
1561+ }
1562+ }
15481563
1549- WalletDescriptor w_desc (std::move (parsed_desc), timestamp, range_start, range_end, next_index);
1564+ WalletDescriptor w_desc (std::move (parsed_desc), timestamp, range_start, range_end, next_index);
15501565
1551- // Check if the wallet already contains the descriptor
1552- auto existing_spk_manager = wallet.GetDescriptorScriptPubKeyMan (w_desc);
1553- if (existing_spk_manager) {
1554- if (!existing_spk_manager->CanUpdateToWalletDescriptor (w_desc, error)) {
1555- throw JSONRPCError (RPC_INVALID_PARAMETER, error);
1566+ // Check if the wallet already contains the descriptor
1567+ auto existing_spk_manager = wallet.GetDescriptorScriptPubKeyMan (w_desc);
1568+ if (existing_spk_manager) {
1569+ if (!existing_spk_manager->CanUpdateToWalletDescriptor (w_desc, error)) {
1570+ throw JSONRPCError (RPC_INVALID_PARAMETER, error);
1571+ }
15561572 }
1557- }
15581573
1559- // Add descriptor to the wallet
1560- auto spk_manager = wallet.AddWalletDescriptor (w_desc, keys, label, internal);
1561- if (spk_manager == nullptr ) {
1562- throw JSONRPCError (RPC_WALLET_ERROR, strprintf (" Could not add descriptor '%s'" , descriptor));
1563- }
1574+ // Add descriptor to the wallet
1575+ auto spk_manager = wallet.AddWalletDescriptor (w_desc, keys, label, ( internal. has_value () ? internal. value () : j) );
1576+ if (spk_manager == nullptr ) {
1577+ throw JSONRPCError (RPC_WALLET_ERROR, strprintf (" Could not add descriptor '%s'" , descriptor));
1578+ }
15641579
1565- // Set descriptor as active if necessary
1566- if (active) {
1567- if (!w_desc.descriptor ->GetOutputType ()) {
1568- warnings.push_back (" Unknown output type, cannot set descriptor to active." );
1580+ // Set descriptor as active if necessary
1581+ if (active) {
1582+ if (!w_desc.descriptor ->GetOutputType ()) {
1583+ warnings.push_back (" Unknown output type, cannot set descriptor to active." );
1584+ } else {
1585+ wallet.AddActiveScriptPubKeyMan (spk_manager->GetID (), *w_desc.descriptor ->GetOutputType (), (internal.has_value () ? internal.value () : j));
1586+ }
15691587 } else {
1570- wallet.AddActiveScriptPubKeyMan (spk_manager->GetID (), *w_desc.descriptor ->GetOutputType (), internal);
1571- }
1572- } else {
1573- if (w_desc.descriptor ->GetOutputType ()) {
1574- wallet.DeactivateScriptPubKeyMan (spk_manager->GetID (), *w_desc.descriptor ->GetOutputType (), internal);
1588+ if (w_desc.descriptor ->GetOutputType ()) {
1589+ wallet.DeactivateScriptPubKeyMan (spk_manager->GetID (), *w_desc.descriptor ->GetOutputType (), (internal.has_value () ? internal.value () : j));
1590+ }
15751591 }
15761592 }
15771593
0 commit comments