diff options
author | Andrew Chow <achow101-github@achow101.com> | 2018-12-16 14:08:55 -0500 |
---|---|---|
committer | Andrew Chow <achow101-github@achow101.com> | 2019-02-14 18:34:03 -0500 |
commit | f4b00b70e811d3772589ab3c64d7658f4dbdab69 (patch) | |
tree | 81a3f474331aff4d7bbf1c65567582e92f3fc069 /src/wallet/rpcdump.cpp | |
parent | 9e1551b9ceda0056fcbc78bf5827bff1bfc5d51b (diff) |
Import public keys in order
Do public key imports in the order that they are specified in the import
or in the descriptor range.
Diffstat (limited to 'src/wallet/rpcdump.cpp')
-rw-r--r-- | src/wallet/rpcdump.cpp | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 30555886f7..930274f8a1 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -967,7 +967,7 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d } } -static UniValue ProcessImportLegacy(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) +static UniValue ProcessImportLegacy(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) { UniValue warnings(UniValue::VARR); @@ -1038,6 +1038,7 @@ static UniValue ProcessImportLegacy(ImportData& import_data, std::map<CKeyID, CP throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" is not a valid public key"); } pubkey_map.emplace(pubkey.GetID(), pubkey); + ordered_pubkeys.push_back(pubkey.GetID()); } for (size_t i = 0; i < keys.size(); ++i) { const auto& str = keys[i].get_str(); @@ -1110,7 +1111,7 @@ static UniValue ProcessImportLegacy(ImportData& import_data, std::map<CKeyID, CP return warnings; } -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) +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) { UniValue warnings(UniValue::VARR); @@ -1144,22 +1145,25 @@ static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID const UniValue& priv_keys = data.exists("keys") ? data["keys"].get_array() : UniValue(); - FlatSigningProvider out_keys; - // Expand all descriptors to get public keys and scripts. // TODO: get private keys from descriptors too for (int i = range_start; i <= range_end; ++i) { + FlatSigningProvider out_keys; std::vector<CScript> scripts_temp; parsed_desc->Expand(i, keys, scripts_temp, out_keys); std::copy(scripts_temp.begin(), scripts_temp.end(), std::inserter(script_pub_keys, script_pub_keys.end())); - } + for (const auto& key_pair : out_keys.pubkeys) { + ordered_pubkeys.push_back(key_pair.first); + } - for (const auto& x : out_keys.scripts) { - import_data.import_scripts.emplace(x.second); + for (const auto& x : out_keys.scripts) { + import_data.import_scripts.emplace(x.second); + } + + std::copy(out_keys.pubkeys.begin(), out_keys.pubkeys.end(), std::inserter(pubkey_map, pubkey_map.end())); + import_data.key_origins.insert(out_keys.origins.begin(), out_keys.origins.end()); } - std::copy(out_keys.pubkeys.begin(), out_keys.pubkeys.end(), std::inserter(pubkey_map, pubkey_map.end())); - import_data.key_origins.insert(out_keys.origins.begin(), out_keys.origins.end()); for (size_t i = 0; i < priv_keys.size(); ++i) { const auto& str = priv_keys[i].get_str(); CKey key = DecodeSecret(str); @@ -1218,14 +1222,15 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con std::map<CKeyID, CPubKey> pubkey_map; std::map<CKeyID, CKey> privkey_map; std::set<CScript> script_pub_keys; + std::vector<CKeyID> ordered_pubkeys; bool have_solving_data; if (data.exists("scriptPubKey") && data.exists("desc")) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Both a descriptor and a scriptPubKey should not be provided."); } else if (data.exists("scriptPubKey")) { - warnings = ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data); + warnings = ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data, ordered_pubkeys); } else if (data.exists("desc")) { - warnings = ProcessImportDescriptor(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data); + warnings = ProcessImportDescriptor(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data, ordered_pubkeys); } else { throw JSONRPCError(RPC_INVALID_PARAMETER, "Either a descriptor or scriptPubKey must be provided."); } @@ -1247,25 +1252,28 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con for (const auto& entry : import_data.import_scripts) { if (!pwallet->HaveCScript(CScriptID(entry)) && !pwallet->AddCScript(entry)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding script to wallet"); + } + } + for (const auto& entry : privkey_map) { + const CKey& key = entry.second; + CPubKey pubkey = key.GetPubKey(); + const CKeyID& id = entry.first; + assert(key.VerifyPubKey(pubkey)); + pwallet->mapKeyMetadata[id].nCreateTime = timestamp; + // If the private key is not present in the wallet, insert it. + if (!pwallet->HaveKey(id) && !pwallet->AddKeyPubKey(key, pubkey)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); + } + pwallet->UpdateTimeFirstKey(timestamp); + } + for (const CKeyID& id : ordered_pubkeys) { + auto entry = pubkey_map.find(id); + if (entry == pubkey_map.end()) { + continue; } - } - for (const auto& entry : privkey_map) { - const CKey& key = entry.second; - CPubKey pubkey = key.GetPubKey(); - const CKeyID& id = entry.first; - assert(key.VerifyPubKey(pubkey)); - pwallet->mapKeyMetadata[id].nCreateTime = timestamp; - // If the private key is not present in the wallet, insert it. - if (!pwallet->HaveKey(id) && !pwallet->AddKeyPubKey(key, pubkey)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet"); - } - pwallet->UpdateTimeFirstKey(timestamp); - } - for (const auto& entry : pubkey_map) { - const CPubKey& pubkey = entry.second; - const CKeyID& id = entry.first; - CPubKey temp; - if (!pwallet->GetPubKey(id, temp) && !pwallet->AddWatchOnly(GetScriptForRawPubKey(pubkey), timestamp)) { + const CPubKey& pubkey = entry->second; + CPubKey temp; + if (!pwallet->GetPubKey(id, temp) && !pwallet->AddWatchOnly(GetScriptForRawPubKey(pubkey), timestamp)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); } const auto& key_orig_it = import_data.key_origins.find(id); |