diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1140,6 +1140,22 @@ UniValue result(UniValue::VOBJ); try { + const bool internal = + data.exists("internal") ? data["internal"].get_bool() : false; + // Internal addresses should not have a label + if (internal && data.exists("label")) { + throw JSONRPCError(RPC_INVALID_PARAMETER, + "Internal addresses should not have a label"); + } + const std::string &label = + data.exists("label") ? data["label"].get_str() : ""; + + ImportData import_data; + std::map pubkey_map; + std::map privkey_map; + std::set script_pub_keys; + bool have_solving_data; + // First ensure scriptPubKey has either a script or JSON with "address" // string const UniValue &scriptPubKey = data["scriptPubKey"]; @@ -1161,12 +1177,8 @@ data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue(); const UniValue &keys = data.exists("keys") ? data["keys"].get_array() : UniValue(); - const bool internal = - data.exists("internal") ? data["internal"].get_bool() : false; const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false; - const std::string &label = - data.exists("label") && !internal ? data["label"].get_str() : ""; // If private keys are disabled, abort if private keys are being // imported @@ -1200,9 +1212,9 @@ "nonstandard scriptPubKey imports."); } } + script_pub_keys.emplace(script); // Parse all arguments - ImportData import_data; if (strRedeemScript.size()) { if (!IsHex(strRedeemScript)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, @@ -1214,7 +1226,6 @@ import_data.redeemscript = std::make_unique( parsed_redeemscript.begin(), parsed_redeemscript.end()); } - std::map pubkey_map; for (size_t i = 0; i < pubKeys.size(); ++i) { const auto &str = pubKeys[i].get_str(); if (!IsHex(str)) { @@ -1231,7 +1242,6 @@ } pubkey_map.emplace(pubkey.GetID(), pubkey); } - std::map privkey_map; for (size_t i = 0; i < keys.size(); ++i) { const auto &str = keys[i].get_str(); CKey key = DecodeSecret(str); @@ -1247,14 +1257,8 @@ privkey_map.emplace(id, key); } - // Internal addresses should not have a label - if (internal && data.exists("label")) { - throw JSONRPCError(RPC_INVALID_PARAMETER, - "Internal addresses should not have a label"); - } - // Verify and process input data - bool have_solving_data = + have_solving_data = import_data.redeemscript || pubkey_map.size() || privkey_map.size(); if (have_solving_data) { // Match up data in import_data with the scriptPubKey in script. @@ -1332,10 +1336,12 @@ } // Check whether we have any work to do - if (::IsMine(*pwallet, script) & ISMINE_SPENDABLE) { - throw JSONRPCError(RPC_WALLET_ERROR, - "The wallet already contains the private key " - "for this address or script"); + for (const CScript &s : script_pub_keys) { + if (::IsMine(*pwallet, s) & ISMINE_SPENDABLE) { + throw JSONRPCError(RPC_WALLET_ERROR, + "The wallet already contains the private " + "key for this address or script"); + } } // All good, time to import @@ -1372,17 +1378,22 @@ "Error adding address to wallet"); } } - if (!have_solving_data || !::IsMine(*pwallet, script)) { - // Always call AddWatchOnly for non-solvable watch-only, so that - // watch timestamp gets updated - if (!pwallet->AddWatchOnly(script, timestamp)) { - throw JSONRPCError(RPC_WALLET_ERROR, - "Error adding address to wallet"); + + for (const CScript &s : script_pub_keys) { + if (!have_solving_data || !::IsMine(*pwallet, s)) { + // Always call AddWatchOnly for non-solvable watch-only, so that + // watch timestamp gets updated + if (!pwallet->AddWatchOnly(s, timestamp)) { + throw JSONRPCError(RPC_WALLET_ERROR, + "Error adding address to wallet"); + } + } + CTxDestination d; + ExtractDestination(s, d); + if (!internal) { + assert(IsValidDestination(d)); + pwallet->SetAddressBook(d, label, "receive"); } - } - if (!internal) { - assert(IsValidDestination(dest)); - pwallet->SetAddressBook(dest, label, "receive"); } result.pushKV("success", UniValue(true));