Implement loading of keys for DescriptorScriptPubKeyMan

pull/16528/head
Andrew Chow 5 years ago
parent 2363e9fcaa
commit 953feb3d27

@ -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;
}

@ -488,11 +488,21 @@ private:
WalletDescriptor m_wallet_descriptor GUARDED_BY(cs_desc_man); WalletDescriptor m_wallet_descriptor GUARDED_BY(cs_desc_man);
using ScriptPubKeyMap = std::map<CScript, int32_t>; // Map of scripts to descriptor range index 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); ScriptPubKeyMap m_map_script_pub_keys GUARDED_BY(cs_desc_man);
OutputType m_address_type; OutputType m_address_type;
bool m_internal; 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: public:
DescriptorScriptPubKeyMan(WalletStorage& storage, WalletDescriptor& descriptor) DescriptorScriptPubKeyMan(WalletStorage& storage, WalletDescriptor& descriptor)
: ScriptPubKeyMan(storage), : ScriptPubKeyMan(storage),
@ -545,6 +555,9 @@ public:
void SetType(OutputType type, bool internal) override; void SetType(OutputType type, bool internal) override;
void SetCache(const DescriptorCache& cache); 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 #endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H

@ -45,6 +45,8 @@ const std::string TX{"tx"};
const std::string VERSION{"version"}; const std::string VERSION{"version"};
const std::string WALLETDESCRIPTOR{"walletdescriptor"}; const std::string WALLETDESCRIPTOR{"walletdescriptor"};
const std::string WALLETDESCRIPTORCACHE{"walletdescriptorcache"}; const std::string WALLETDESCRIPTORCACHE{"walletdescriptorcache"};
const std::string WALLETDESCRIPTORCKEY{"walletdescriptorckey"};
const std::string WALLETDESCRIPTORKEY{"walletdescriptorkey"};
const std::string WATCHMETA{"watchmeta"}; const std::string WATCHMETA{"watchmeta"};
const std::string WATCHS{"watchs"}; const std::string WATCHS{"watchs"};
} // namespace DBKeys } // namespace DBKeys
@ -202,6 +204,8 @@ public:
std::map<OutputType, uint256> m_active_external_spks; std::map<OutputType, uint256> m_active_external_spks;
std::map<OutputType, uint256> m_active_internal_spks; std::map<OutputType, uint256> m_active_internal_spks;
std::map<uint256, DescriptorCache> m_descriptor_caches; 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() { CWalletScanState() {
} }
@ -467,6 +471,58 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
} else { } else {
wss.m_descriptor_caches[desc_id].CacheDerivedExtPubKey(key_exp_index, der_index, xpub); 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 && } else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE &&
strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY && strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY &&
strType != DBKeys::VERSION && strType != DBKeys::SETTINGS) { strType != DBKeys::VERSION && strType != DBKeys::SETTINGS) {
@ -575,6 +631,16 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
((DescriptorScriptPubKeyMan*)spk_man)->SetCache(desc_cache_pair.second); ((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) if (fNoncriticalErrors && result == DBErrors::LOAD_OK)
result = DBErrors::NONCRITICAL_ERROR; result = DBErrors::NONCRITICAL_ERROR;

Loading…
Cancel
Save