From a1b25e12a5f57048a4639964d57c0b46eb84cd4e Mon Sep 17 00:00:00 2001 From: John Newbery Date: Fri, 11 Jan 2019 16:32:44 -0500 Subject: [wallet] Refactor ProcessImport() This commit is move-only and doesn't make any functional changes. It simply moves code around within ProcessImport() in preparation for refactors in the next commits. --- src/wallet/rpcdump.cpp | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 32c36ceaeb..7bd3502276 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -970,6 +970,19 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con 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"]; bool isScript = scriptPubKey.getType() == UniValue::VSTR; @@ -983,9 +996,7 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].get_str() : ""; const UniValue& pubKeys = 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") ? data["label"].get_str() : ""; // If private keys are disabled, abort if private keys are being imported if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.isNull()) { @@ -1011,9 +1022,9 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set to true for 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, "Invalid redeem script \"" + strRedeemScript + "\": must be hex string"); @@ -1028,7 +1039,6 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con auto parsed_witnessscript = ParseHex(witness_script_hex); import_data.witnessscript = MakeUnique(parsed_witnessscript.begin(), parsed_witnessscript.end()); } - std::map pubkey_map; for (size_t i = 0; i < pubKeys.size(); ++i) { const auto& str = pubKeys[i].get_str(); if (!IsHex(str)) { @@ -1041,7 +1051,6 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con } 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); @@ -1056,13 +1065,9 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con 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 = import_data.redeemscript || import_data.witnessscript || pubkey_map.size() || privkey_map.size(); + have_solving_data = import_data.redeemscript || import_data.witnessscript || pubkey_map.size() || privkey_map.size(); if (have_solving_data) { // Match up data in import_data with the scriptPubKey in script. auto error = RecurseImportData(script, import_data, ScriptContext::TOP); @@ -1115,8 +1120,10 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con } // 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& script : script_pub_keys) { + if (::IsMine(*pwallet, script) & ISMINE_SPENDABLE) { + throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script"); + } } // All good, time to import @@ -1146,14 +1153,19 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con throw JSONRPCError(RPC_WALLET_ERROR, "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& script : script_pub_keys) { + 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"); + } + } + CTxDestination dest; + ExtractDestination(script, dest); + if (!internal) { + assert(IsValidDestination(dest)); + pwallet->SetAddressBook(dest, label, "receive"); } - } - if (!internal) { - assert(IsValidDestination(dest)); - pwallet->SetAddressBook(dest, label, "receive"); } result.pushKV("success", UniValue(true)); -- cgit v1.2.3 From 4cac0ddd258bc82258ccc99568d02d3b2415339d Mon Sep 17 00:00:00 2001 From: John Newbery Date: Fri, 11 Jan 2019 16:42:43 -0500 Subject: [wallet] Add ProcessImportLegacy() This commit adds a ProcessImportLegacy() function which currently does nothing. It also unindents a block of code for a future move-only change. Reviewer hint: review with -w to ignore whitespace changes. --- src/wallet/rpcdump.cpp | 240 +++++++++++++++++++++++++------------------------ 1 file changed, 124 insertions(+), 116 deletions(-) (limited to 'src') diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 7bd3502276..58dad78502 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -964,6 +964,12 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d } } +static UniValue ProcessImportLegacy(ImportData& import_data, std::map& pubkey_map, std::map& privkey_map, std::set& script_pub_keys, bool& have_solving_data, const UniValue& data) +{ + UniValue warnings(UniValue::VARR); + return warnings; +} + static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { UniValue warnings(UniValue::VARR); @@ -983,141 +989,143 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con 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"]; - bool isScript = scriptPubKey.getType() == UniValue::VSTR; - if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "scriptPubKey must be string with script or JSON with address string"); + warnings = ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data); + + // First ensure scriptPubKey has either a script or JSON with "address" string + const UniValue& scriptPubKey = data["scriptPubKey"]; + bool isScript = scriptPubKey.getType() == UniValue::VSTR; + if (!isScript && !(scriptPubKey.getType() == UniValue::VOBJ && scriptPubKey.exists("address"))) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "scriptPubKey must be string with script or JSON with address string"); + } + const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str(); + + // Optional fields. + const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : ""; + const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].get_str() : ""; + const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue(); + const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue(); + const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false; + + // If private keys are disabled, abort if private keys are being imported + if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.isNull()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled"); + } + + // Generate the script and destination for the scriptPubKey provided + CScript script; + CTxDestination dest; + if (!isScript) { + dest = DecodeDestination(output); + if (!IsValidDestination(dest)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address \"" + output + "\""); } - const std::string& output = isScript ? scriptPubKey.get_str() : scriptPubKey["address"].get_str(); - - // Optional fields. - const std::string& strRedeemScript = data.exists("redeemscript") ? data["redeemscript"].get_str() : ""; - const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].get_str() : ""; - const UniValue& pubKeys = data.exists("pubkeys") ? data["pubkeys"].get_array() : UniValue(); - const UniValue& keys = data.exists("keys") ? data["keys"].get_array() : UniValue(); - const bool watchOnly = data.exists("watchonly") ? data["watchonly"].get_bool() : false; - - // If private keys are disabled, abort if private keys are being imported - if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled"); + script = GetScriptForDestination(dest); + } else { + if (!IsHex(output)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey \"" + output + "\""); } - - // Generate the script and destination for the scriptPubKey provided - CScript script; - CTxDestination dest; - if (!isScript) { - dest = DecodeDestination(output); - if (!IsValidDestination(dest)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address \"" + output + "\""); - } - script = GetScriptForDestination(dest); - } else { - if (!IsHex(output)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid scriptPubKey \"" + output + "\""); - } - std::vector vData(ParseHex(output)); - script = CScript(vData.begin(), vData.end()); - if (!ExtractDestination(script, dest) && !internal) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set to true for nonstandard scriptPubKey imports."); - } + std::vector vData(ParseHex(output)); + script = CScript(vData.begin(), vData.end()); + if (!ExtractDestination(script, dest) && !internal) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal must be set to true for nonstandard scriptPubKey imports."); } - script_pub_keys.emplace(script); + } + script_pub_keys.emplace(script); - // Parse all arguments - if (strRedeemScript.size()) { - if (!IsHex(strRedeemScript)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script \"" + strRedeemScript + "\": must be hex string"); - } - auto parsed_redeemscript = ParseHex(strRedeemScript); - import_data.redeemscript = MakeUnique(parsed_redeemscript.begin(), parsed_redeemscript.end()); + // Parse all arguments + if (strRedeemScript.size()) { + if (!IsHex(strRedeemScript)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid redeem script \"" + strRedeemScript + "\": must be hex string"); } - if (witness_script_hex.size()) { - if (!IsHex(witness_script_hex)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid witness script \"" + witness_script_hex + "\": must be hex string"); - } - auto parsed_witnessscript = ParseHex(witness_script_hex); - import_data.witnessscript = MakeUnique(parsed_witnessscript.begin(), parsed_witnessscript.end()); + auto parsed_redeemscript = ParseHex(strRedeemScript); + import_data.redeemscript = MakeUnique(parsed_redeemscript.begin(), parsed_redeemscript.end()); + } + if (witness_script_hex.size()) { + if (!IsHex(witness_script_hex)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid witness script \"" + witness_script_hex + "\": must be hex string"); } - for (size_t i = 0; i < pubKeys.size(); ++i) { - const auto& str = pubKeys[i].get_str(); - if (!IsHex(str)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" must be a hex string"); - } - auto parsed_pubkey = ParseHex(str); - CPubKey pubkey(parsed_pubkey.begin(), parsed_pubkey.end()); - if (!pubkey.IsFullyValid()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" is not a valid public key"); - } - pubkey_map.emplace(pubkey.GetID(), pubkey); + auto parsed_witnessscript = ParseHex(witness_script_hex); + import_data.witnessscript = MakeUnique(parsed_witnessscript.begin(), parsed_witnessscript.end()); + } + for (size_t i = 0; i < pubKeys.size(); ++i) { + const auto& str = pubKeys[i].get_str(); + if (!IsHex(str)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" must be a hex string"); } - for (size_t i = 0; i < keys.size(); ++i) { - const auto& str = keys[i].get_str(); - CKey key = DecodeSecret(str); - if (!key.IsValid()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding"); - } - CPubKey pubkey = key.GetPubKey(); - CKeyID id = pubkey.GetID(); - if (pubkey_map.count(id)) { - pubkey_map.erase(id); - } - privkey_map.emplace(id, key); + auto parsed_pubkey = ParseHex(str); + CPubKey pubkey(parsed_pubkey.begin(), parsed_pubkey.end()); + if (!pubkey.IsFullyValid()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" is not a valid public key"); } + pubkey_map.emplace(pubkey.GetID(), pubkey); + } + for (size_t i = 0; i < keys.size(); ++i) { + const auto& str = keys[i].get_str(); + CKey key = DecodeSecret(str); + if (!key.IsValid()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding"); + } + CPubKey pubkey = key.GetPubKey(); + CKeyID id = pubkey.GetID(); + if (pubkey_map.count(id)) { + pubkey_map.erase(id); + } + privkey_map.emplace(id, key); + } - // Verify and process input data - have_solving_data = import_data.redeemscript || import_data.witnessscript || pubkey_map.size() || privkey_map.size(); - if (have_solving_data) { - // Match up data in import_data with the scriptPubKey in script. - auto error = RecurseImportData(script, import_data, ScriptContext::TOP); + // Verify and process input data + have_solving_data = import_data.redeemscript || import_data.witnessscript || pubkey_map.size() || privkey_map.size(); + if (have_solving_data) { + // Match up data in import_data with the scriptPubKey in script. + auto error = RecurseImportData(script, import_data, ScriptContext::TOP); - // Verify whether the watchonly option corresponds to the availability of private keys. - bool spendable = std::all_of(import_data.used_keys.begin(), import_data.used_keys.end(), [&](const std::pair& used_key){ return privkey_map.count(used_key.first) > 0; }); - if (!watchOnly && !spendable) { - warnings.push_back("Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."); - } - if (watchOnly && spendable) { - warnings.push_back("All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag."); - } + // Verify whether the watchonly option corresponds to the availability of private keys. + bool spendable = std::all_of(import_data.used_keys.begin(), import_data.used_keys.end(), [&](const std::pair& used_key){ return privkey_map.count(used_key.first) > 0; }); + if (!watchOnly && !spendable) { + warnings.push_back("Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."); + } + if (watchOnly && spendable) { + warnings.push_back("All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag."); + } - // Check that all required keys for solvability are provided. - if (error.empty()) { - for (const auto& require_key : import_data.used_keys) { - if (!require_key.second) continue; // Not a required key - if (pubkey_map.count(require_key.first) == 0 && privkey_map.count(require_key.first) == 0) { - error = "some required keys are missing"; - } + // Check that all required keys for solvability are provided. + if (error.empty()) { + for (const auto& require_key : import_data.used_keys) { + if (!require_key.second) continue; // Not a required key + if (pubkey_map.count(require_key.first) == 0 && privkey_map.count(require_key.first) == 0) { + error = "some required keys are missing"; } } + } - if (!error.empty()) { - warnings.push_back("Importing as non-solvable: " + error + ". If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript."); - import_data = ImportData(); - pubkey_map.clear(); - privkey_map.clear(); - have_solving_data = false; - } else { - // RecurseImportData() removes any relevant redeemscript/witnessscript from import_data, so we can use that to discover if a superfluous one was provided. - if (import_data.redeemscript) warnings.push_back("Ignoring redeemscript as this is not a P2SH script."); - if (import_data.witnessscript) warnings.push_back("Ignoring witnessscript as this is not a (P2SH-)P2WSH script."); - for (auto it = privkey_map.begin(); it != privkey_map.end(); ) { - auto oldit = it++; - if (import_data.used_keys.count(oldit->first) == 0) { - warnings.push_back("Ignoring irrelevant private key."); - privkey_map.erase(oldit); - } + if (!error.empty()) { + warnings.push_back("Importing as non-solvable: " + error + ". If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript."); + import_data = ImportData(); + pubkey_map.clear(); + privkey_map.clear(); + have_solving_data = false; + } else { + // RecurseImportData() removes any relevant redeemscript/witnessscript from import_data, so we can use that to discover if a superfluous one was provided. + if (import_data.redeemscript) warnings.push_back("Ignoring redeemscript as this is not a P2SH script."); + if (import_data.witnessscript) warnings.push_back("Ignoring witnessscript as this is not a (P2SH-)P2WSH script."); + for (auto it = privkey_map.begin(); it != privkey_map.end(); ) { + auto oldit = it++; + if (import_data.used_keys.count(oldit->first) == 0) { + warnings.push_back("Ignoring irrelevant private key."); + privkey_map.erase(oldit); } - for (auto it = pubkey_map.begin(); it != pubkey_map.end(); ) { - auto oldit = it++; - auto key_data_it = import_data.used_keys.find(oldit->first); - if (key_data_it == import_data.used_keys.end() || !key_data_it->second) { - warnings.push_back("Ignoring public key \"" + HexStr(oldit->first) + "\" as it doesn't appear inside P2PKH or P2WPKH."); - pubkey_map.erase(oldit); - } + } + for (auto it = pubkey_map.begin(); it != pubkey_map.end(); ) { + auto oldit = it++; + auto key_data_it = import_data.used_keys.find(oldit->first); + if (key_data_it == import_data.used_keys.end() || !key_data_it->second) { + warnings.push_back("Ignoring public key \"" + HexStr(oldit->first) + "\" as it doesn't appear inside P2PKH or P2WPKH."); + pubkey_map.erase(oldit); } } } + } // Check whether we have any work to do for (const CScript& script : script_pub_keys) { -- cgit v1.2.3 From d2b381cc91b2c4e74abe11e5bd66af647b70dafb Mon Sep 17 00:00:00 2001 From: John Newbery Date: Fri, 11 Jan 2019 16:47:52 -0500 Subject: [wallet] Refactor ProcessImport() to call ProcessImportLegacy() This is almost entirely a move-only commit. Reviewer hint: use --color-moved=zebra for review. --- src/wallet/rpcdump.cpp | 58 ++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 58dad78502..f91d545a3b 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -967,29 +967,6 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d static UniValue ProcessImportLegacy(ImportData& import_data, std::map& pubkey_map, std::map& privkey_map, std::set& script_pub_keys, bool& have_solving_data, const UniValue& data) { UniValue warnings(UniValue::VARR); - return warnings; -} - -static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) -{ - UniValue warnings(UniValue::VARR); - 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; - - warnings = ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data); // First ensure scriptPubKey has either a script or JSON with "address" string const UniValue& scriptPubKey = data["scriptPubKey"]; @@ -1004,13 +981,9 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con const std::string& witness_script_hex = data.exists("witnessscript") ? data["witnessscript"].get_str() : ""; const UniValue& pubKeys = 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; - // If private keys are disabled, abort if private keys are being imported - if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !keys.isNull()) { - throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled"); - } - // Generate the script and destination for the scriptPubKey provided CScript script; CTxDestination dest; @@ -1127,6 +1100,35 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con } } + return warnings; +} + +static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) +{ + UniValue warnings(UniValue::VARR); + 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; + + warnings = ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data); + + // If private keys are disabled, abort if private keys are being imported + if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !privkey_map.empty()) { + throw JSONRPCError(RPC_WALLET_ERROR, "Cannot import private keys to a wallet with private keys disabled"); + } + // Check whether we have any work to do for (const CScript& script : script_pub_keys) { if (::IsMine(*pwallet, script) & ISMINE_SPENDABLE) { -- cgit v1.2.3 From 9f48053d8f9a1feacc96d7e2a00c8a3a67576948 Mon Sep 17 00:00:00 2001 From: MeshCollider Date: Thu, 13 Dec 2018 13:55:48 +1300 Subject: [wallet] Allow descriptor imports with importmulti --- src/wallet/rpcdump.cpp | 118 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index f91d545a3b..9ed2a16416 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -9,6 +9,7 @@ #include #include #include +#include