@@ -1456,22 +1456,30 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
1456
1456
1457
1457
const std::string& descriptor = data[" desc" ].get_str ();
1458
1458
const bool active = data.exists (" active" ) ? data[" active" ].get_bool () : false ;
1459
- const bool internal = data.exists (" internal" ) ? data[" internal" ].get_bool () : false ;
1460
1459
const std::string& label = data.exists (" label" ) ? data[" label" ].get_str () : " " ;
1461
1460
1462
1461
// Parse descriptor string
1463
1462
FlatSigningProvider keys;
1464
1463
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 ) {
1467
1466
throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, error);
1468
1467
}
1469
1468
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
+
1470
1478
// Range check
1471
1479
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" )) {
1473
1481
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 ()) {
1475
1483
if (data.exists (" range" )) {
1476
1484
auto range = ParseDescriptorRange (data[" range" ]);
1477
1485
range_start = range.first ;
@@ -1493,10 +1501,15 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
1493
1501
}
1494
1502
1495
1503
// Active descriptors must be ranged
1496
- if (active && !parsed_desc ->IsRange ()) {
1504
+ if (active && !parsed_descs. first ->IsRange ()) {
1497
1505
throw JSONRPCError (RPC_INVALID_PARAMETER, " Active descriptors must be ranged" );
1498
1506
}
1499
1507
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
+
1500
1513
// Ranged descriptors should not have a label
1501
1514
if (data.exists (" range" ) && data.exists (" label" )) {
1502
1515
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
1508
1521
}
1509
1522
1510
1523
// Combo descriptor check
1511
- if (active && !parsed_desc ->IsSingleType ()) {
1524
+ if (active && !parsed_descs. first ->IsSingleType ()) {
1512
1525
throw JSONRPCError (RPC_WALLET_ERROR, " Combo descriptors cannot be set to active" );
1513
1526
}
1514
1527
@@ -1517,61 +1530,64 @@ static UniValue ProcessDescriptorImport(CWallet& wallet, const UniValue& data, c
1517
1530
throw JSONRPCError (RPC_WALLET_ERROR, " Cannot import private keys to a wallet with private keys disabled" );
1518
1531
}
1519
1532
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
+ }
1536
1552
}
1537
- }
1538
1553
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
+ }
1548
1563
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);
1550
1565
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
+ }
1556
1572
}
1557
- }
1558
1573
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
+ }
1564
1579
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
+ }
1569
1587
} 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
+ }
1575
1591
}
1576
1592
}
1577
1593
0 commit comments