diff options
author | Andrew Chow <achow101-github@achow101.com> | 2019-07-09 18:23:51 -0400 |
---|---|---|
committer | Andrew Chow <achow101-github@achow101.com> | 2020-04-23 13:59:48 -0400 |
commit | 953feb3d2724f5398dd48990c4957a19313d2c8c (patch) | |
tree | 5111473bc3650d2fc51eb4a7118e090dac6c706d /src | |
parent | 2363e9fcaa41b68bf11153f591b95f2d41ff9a1a (diff) |
Implement loading of keys for DescriptorScriptPubKeyMan
Diffstat (limited to 'src')
-rw-r--r-- | src/wallet/scriptpubkeyman.cpp | 18 | ||||
-rw-r--r-- | src/wallet/scriptpubkeyman.h | 13 | ||||
-rw-r--r-- | src/wallet/walletdb.cpp | 66 |
3 files changed, 97 insertions, 0 deletions
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index 7142867081..d651816e58 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -1653,3 +1653,21 @@ void DescriptorScriptPubKeyMan::SetCache(const DescriptorCache& cache) } } } + +bool DescriptorScriptPubKeyMan::AddKey(const CKeyID& key_id, const CKey& key) +{ + LOCK(cs_desc_man); + m_map_keys[key_id] = key; + return true; +} + +bool DescriptorScriptPubKeyMan::AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key) +{ + LOCK(cs_desc_man); + if (!m_map_keys.empty()) { + return false; + } + + m_map_crypted_keys[key_id] = make_pair(pubkey, crypted_key); + return true; +} diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index 34ba07967e..8da6757de0 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -488,11 +488,21 @@ private: WalletDescriptor m_wallet_descriptor GUARDED_BY(cs_desc_man); using ScriptPubKeyMap = std::map<CScript, int32_t>; // Map of scripts to descriptor range index + using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>; + using KeyMap = std::map<CKeyID, CKey>; ScriptPubKeyMap m_map_script_pub_keys GUARDED_BY(cs_desc_man); OutputType m_address_type; bool m_internal; + + KeyMap m_map_keys GUARDED_BY(cs_desc_man); + CryptedKeyMap m_map_crypted_keys GUARDED_BY(cs_desc_man); + + bool SetCrypted(); + + //! keeps track of whether Unlock has run a thorough check before + bool m_decryption_thoroughly_checked = false; public: DescriptorScriptPubKeyMan(WalletStorage& storage, WalletDescriptor& descriptor) : ScriptPubKeyMan(storage), @@ -545,6 +555,9 @@ public: void SetType(OutputType type, bool internal) override; void SetCache(const DescriptorCache& cache); + + bool AddKey(const CKeyID& key_id, const CKey& key); + bool AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key); }; #endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index fc4783f932..61546656c4 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -45,6 +45,8 @@ const std::string TX{"tx"}; const std::string VERSION{"version"}; const std::string WALLETDESCRIPTOR{"walletdescriptor"}; const std::string WALLETDESCRIPTORCACHE{"walletdescriptorcache"}; +const std::string WALLETDESCRIPTORCKEY{"walletdescriptorckey"}; +const std::string WALLETDESCRIPTORKEY{"walletdescriptorkey"}; const std::string WATCHMETA{"watchmeta"}; const std::string WATCHS{"watchs"}; } // namespace DBKeys @@ -202,6 +204,8 @@ public: std::map<OutputType, uint256> m_active_external_spks; std::map<OutputType, uint256> m_active_internal_spks; std::map<uint256, DescriptorCache> m_descriptor_caches; + std::map<std::pair<uint256, CKeyID>, CKey> m_descriptor_keys; + std::map<std::pair<uint256, CKeyID>, std::pair<CPubKey, std::vector<unsigned char>>> m_descriptor_crypt_keys; CWalletScanState() { } @@ -467,6 +471,58 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } else { wss.m_descriptor_caches[desc_id].CacheDerivedExtPubKey(key_exp_index, der_index, xpub); } + } else if (strType == DBKeys::WALLETDESCRIPTORKEY) { + uint256 desc_id; + CPubKey pubkey; + ssKey >> desc_id; + ssKey >> pubkey; + if (!pubkey.IsValid()) + { + strErr = "Error reading wallet database: CPubKey corrupt"; + return false; + } + CKey key; + CPrivKey pkey; + uint256 hash; + + wss.nKeys++; + ssValue >> pkey; + ssValue >> hash; + + // hash pubkey/privkey to accelerate wallet load + std::vector<unsigned char> to_hash; + to_hash.reserve(pubkey.size() + pkey.size()); + to_hash.insert(to_hash.end(), pubkey.begin(), pubkey.end()); + to_hash.insert(to_hash.end(), pkey.begin(), pkey.end()); + + if (Hash(to_hash.begin(), to_hash.end()) != hash) + { + strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt"; + return false; + } + + if (!key.Load(pkey, pubkey, true)) + { + strErr = "Error reading wallet database: CPrivKey corrupt"; + return false; + } + wss.m_descriptor_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), key)); + } else if (strType == DBKeys::WALLETDESCRIPTORCKEY) { + uint256 desc_id; + CPubKey pubkey; + ssKey >> desc_id; + ssKey >> pubkey; + if (!pubkey.IsValid()) + { + strErr = "Error reading wallet database: CPubKey corrupt"; + return false; + } + std::vector<unsigned char> privkey; + ssValue >> privkey; + wss.nCKeys++; + + wss.m_descriptor_crypt_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), std::make_pair(pubkey, privkey))); + wss.fIsEncrypted = true; } else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE && strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY && strType != DBKeys::VERSION && strType != DBKeys::SETTINGS) { @@ -575,6 +631,16 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet) ((DescriptorScriptPubKeyMan*)spk_man)->SetCache(desc_cache_pair.second); } + // Set the descriptor keys + for (auto desc_key_pair : wss.m_descriptor_keys) { + auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first); + ((DescriptorScriptPubKeyMan*)spk_man)->AddKey(desc_key_pair.first.second, desc_key_pair.second); + } + for (auto desc_key_pair : wss.m_descriptor_crypt_keys) { + auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first); + ((DescriptorScriptPubKeyMan*)spk_man)->AddCryptedKey(desc_key_pair.first.second, desc_key_pair.second.first, desc_key_pair.second.second); + } + if (fNoncriticalErrors && result == DBErrors::LOAD_OK) result = DBErrors::NONCRITICAL_ERROR; |