Skip to content

Commit 953feb3

Browse files
committed
Implement loading of keys for DescriptorScriptPubKeyMan
1 parent 2363e9f commit 953feb3

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

src/wallet/scriptpubkeyman.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,3 +1653,21 @@ void DescriptorScriptPubKeyMan::SetCache(const DescriptorCache& cache)
16531653
}
16541654
}
16551655
}
1656+
1657+
bool DescriptorScriptPubKeyMan::AddKey(const CKeyID& key_id, const CKey& key)
1658+
{
1659+
LOCK(cs_desc_man);
1660+
m_map_keys[key_id] = key;
1661+
return true;
1662+
}
1663+
1664+
bool DescriptorScriptPubKeyMan::AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key)
1665+
{
1666+
LOCK(cs_desc_man);
1667+
if (!m_map_keys.empty()) {
1668+
return false;
1669+
}
1670+
1671+
m_map_crypted_keys[key_id] = make_pair(pubkey, crypted_key);
1672+
return true;
1673+
}

src/wallet/scriptpubkeyman.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,11 +488,21 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
488488
WalletDescriptor m_wallet_descriptor GUARDED_BY(cs_desc_man);
489489

490490
using ScriptPubKeyMap = std::map<CScript, int32_t>; // Map of scripts to descriptor range index
491+
using CryptedKeyMap = std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char>>>;
492+
using KeyMap = std::map<CKeyID, CKey>;
491493

492494
ScriptPubKeyMap m_map_script_pub_keys GUARDED_BY(cs_desc_man);
493495

494496
OutputType m_address_type;
495497
bool m_internal;
498+
499+
KeyMap m_map_keys GUARDED_BY(cs_desc_man);
500+
CryptedKeyMap m_map_crypted_keys GUARDED_BY(cs_desc_man);
501+
502+
bool SetCrypted();
503+
504+
//! keeps track of whether Unlock has run a thorough check before
505+
bool m_decryption_thoroughly_checked = false;
496506
public:
497507
DescriptorScriptPubKeyMan(WalletStorage& storage, WalletDescriptor& descriptor)
498508
: ScriptPubKeyMan(storage),
@@ -545,6 +555,9 @@ class DescriptorScriptPubKeyMan : public ScriptPubKeyMan
545555
void SetType(OutputType type, bool internal) override;
546556

547557
void SetCache(const DescriptorCache& cache);
558+
559+
bool AddKey(const CKeyID& key_id, const CKey& key);
560+
bool AddCryptedKey(const CKeyID& key_id, const CPubKey& pubkey, const std::vector<unsigned char>& crypted_key);
548561
};
549562

550563
#endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H

src/wallet/walletdb.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ const std::string TX{"tx"};
4545
const std::string VERSION{"version"};
4646
const std::string WALLETDESCRIPTOR{"walletdescriptor"};
4747
const std::string WALLETDESCRIPTORCACHE{"walletdescriptorcache"};
48+
const std::string WALLETDESCRIPTORCKEY{"walletdescriptorckey"};
49+
const std::string WALLETDESCRIPTORKEY{"walletdescriptorkey"};
4850
const std::string WATCHMETA{"watchmeta"};
4951
const std::string WATCHS{"watchs"};
5052
} // namespace DBKeys
@@ -202,6 +204,8 @@ class CWalletScanState {
202204
std::map<OutputType, uint256> m_active_external_spks;
203205
std::map<OutputType, uint256> m_active_internal_spks;
204206
std::map<uint256, DescriptorCache> m_descriptor_caches;
207+
std::map<std::pair<uint256, CKeyID>, CKey> m_descriptor_keys;
208+
std::map<std::pair<uint256, CKeyID>, std::pair<CPubKey, std::vector<unsigned char>>> m_descriptor_crypt_keys;
205209

206210
CWalletScanState() {
207211
}
@@ -467,6 +471,58 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
467471
} else {
468472
wss.m_descriptor_caches[desc_id].CacheDerivedExtPubKey(key_exp_index, der_index, xpub);
469473
}
474+
} else if (strType == DBKeys::WALLETDESCRIPTORKEY) {
475+
uint256 desc_id;
476+
CPubKey pubkey;
477+
ssKey >> desc_id;
478+
ssKey >> pubkey;
479+
if (!pubkey.IsValid())
480+
{
481+
strErr = "Error reading wallet database: CPubKey corrupt";
482+
return false;
483+
}
484+
CKey key;
485+
CPrivKey pkey;
486+
uint256 hash;
487+
488+
wss.nKeys++;
489+
ssValue >> pkey;
490+
ssValue >> hash;
491+
492+
// hash pubkey/privkey to accelerate wallet load
493+
std::vector<unsigned char> to_hash;
494+
to_hash.reserve(pubkey.size() + pkey.size());
495+
to_hash.insert(to_hash.end(), pubkey.begin(), pubkey.end());
496+
to_hash.insert(to_hash.end(), pkey.begin(), pkey.end());
497+
498+
if (Hash(to_hash.begin(), to_hash.end()) != hash)
499+
{
500+
strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
501+
return false;
502+
}
503+
504+
if (!key.Load(pkey, pubkey, true))
505+
{
506+
strErr = "Error reading wallet database: CPrivKey corrupt";
507+
return false;
508+
}
509+
wss.m_descriptor_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), key));
510+
} else if (strType == DBKeys::WALLETDESCRIPTORCKEY) {
511+
uint256 desc_id;
512+
CPubKey pubkey;
513+
ssKey >> desc_id;
514+
ssKey >> pubkey;
515+
if (!pubkey.IsValid())
516+
{
517+
strErr = "Error reading wallet database: CPubKey corrupt";
518+
return false;
519+
}
520+
std::vector<unsigned char> privkey;
521+
ssValue >> privkey;
522+
wss.nCKeys++;
523+
524+
wss.m_descriptor_crypt_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), std::make_pair(pubkey, privkey)));
525+
wss.fIsEncrypted = true;
470526
} else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE &&
471527
strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY &&
472528
strType != DBKeys::VERSION && strType != DBKeys::SETTINGS) {
@@ -575,6 +631,16 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
575631
((DescriptorScriptPubKeyMan*)spk_man)->SetCache(desc_cache_pair.second);
576632
}
577633

634+
// Set the descriptor keys
635+
for (auto desc_key_pair : wss.m_descriptor_keys) {
636+
auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first);
637+
((DescriptorScriptPubKeyMan*)spk_man)->AddKey(desc_key_pair.first.second, desc_key_pair.second);
638+
}
639+
for (auto desc_key_pair : wss.m_descriptor_crypt_keys) {
640+
auto spk_man = pwallet->GetScriptPubKeyMan(desc_key_pair.first.first);
641+
((DescriptorScriptPubKeyMan*)spk_man)->AddCryptedKey(desc_key_pair.first.second, desc_key_pair.second.first, desc_key_pair.second.second);
642+
}
643+
578644
if (fNoncriticalErrors && result == DBErrors::LOAD_OK)
579645
result = DBErrors::NONCRITICAL_ERROR;
580646

0 commit comments

Comments
 (0)