| 1091 | } |
| 1092 | |
| 1093 | static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID, CPubKey>& pubkey_map, std::map<CKeyID, CKey>& privkey_map, std::set<CScript>& script_pub_keys, bool& have_solving_data, const UniValue& data, std::vector<CKeyID>& ordered_pubkeys) |
| 1094 | { |
| 1095 | UniValue warnings(UniValue::VARR); |
| 1096 | |
| 1097 | const std::string& descriptor = data["desc"].get_str(); |
| 1098 | FlatSigningProvider keys; |
| 1099 | std::string error; |
| 1100 | auto parsed_desc = Parse(descriptor, keys, error, /* require_checksum = */ true); |
| 1101 | if (!parsed_desc) { |
| 1102 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, error); |
| 1103 | } |
| 1104 | if (parsed_desc->GetOutputType() == OutputType::BECH32M) { |
| 1105 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Bech32m descriptors cannot be imported into legacy wallets"); |
| 1106 | } |
| 1107 | |
| 1108 | have_solving_data = parsed_desc->IsSolvable(); |
| 1109 | const bool watch_only = data.exists("watchonly") ? data["watchonly"].get_bool() : false; |
| 1110 | |
| 1111 | int64_t range_start = 0, range_end = 0; |
| 1112 | if (!parsed_desc->IsRange() && data.exists("range")) { |
| 1113 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should not be specified for an un-ranged descriptor"); |
| 1114 | } else if (parsed_desc->IsRange()) { |
| 1115 | if (!data.exists("range")) { |
| 1116 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Descriptor is ranged, please specify the range"); |
| 1117 | } |
| 1118 | std::tie(range_start, range_end) = ParseDescriptorRange(data["range"]); |
| 1119 | } |
| 1120 | |
| 1121 | const UniValue& priv_keys = data.exists("keys") ? data["keys"].get_array() : UniValue(); |
| 1122 | |
| 1123 | // Expand all descriptors to get public keys and scripts, and private keys if available. |
| 1124 | for (int i = range_start; i <= range_end; ++i) { |
| 1125 | FlatSigningProvider out_keys; |
| 1126 | std::vector<CScript> scripts_temp; |
| 1127 | parsed_desc->Expand(i, keys, scripts_temp, out_keys); |
| 1128 | std::copy(scripts_temp.begin(), scripts_temp.end(), std::inserter(script_pub_keys, script_pub_keys.end())); |
| 1129 | for (const auto& key_pair : out_keys.pubkeys) { |
| 1130 | ordered_pubkeys.push_back(key_pair.first); |
| 1131 | } |
| 1132 | |
| 1133 | for (const auto& x : out_keys.scripts) { |
| 1134 | import_data.import_scripts.emplace(x.second); |
| 1135 | } |
| 1136 | |
| 1137 | parsed_desc->ExpandPrivate(i, keys, out_keys); |
| 1138 | |
| 1139 | std::copy(out_keys.pubkeys.begin(), out_keys.pubkeys.end(), std::inserter(pubkey_map, pubkey_map.end())); |
| 1140 | std::copy(out_keys.keys.begin(), out_keys.keys.end(), std::inserter(privkey_map, privkey_map.end())); |
| 1141 | import_data.key_origins.insert(out_keys.origins.begin(), out_keys.origins.end()); |
| 1142 | } |
| 1143 | |
| 1144 | for (size_t i = 0; i < priv_keys.size(); ++i) { |
| 1145 | const auto& str = priv_keys[i].get_str(); |
| 1146 | CKey key = DecodeSecret(str); |
| 1147 | if (!key.IsValid()) { |
| 1148 | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding"); |
| 1149 | } |
| 1150 | CPubKey pubkey = key.GetPubKey(); |
no test coverage detected