0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-08 10:31:50 -05:00

wallet: Upgrade existing descriptor caches

Add functions to upgrade existing descriptor caches to support the use
of last hardened xpub caching.
This commit is contained in:
Andrew Chow 2021-03-01 17:03:52 -05:00
parent 432ba9e543
commit 74fede3b8b
6 changed files with 62 additions and 0 deletions

View file

@ -2278,3 +2278,32 @@ bool DescriptorScriptPubKeyMan::GetDescriptorString(std::string& out, bool priv)
return m_wallet_descriptor.descriptor->ToNormalizedString(provider, out, priv);
}
void DescriptorScriptPubKeyMan::UpgradeDescriptorCache()
{
LOCK(cs_desc_man);
if (m_storage.IsLocked() || m_storage.IsWalletFlagSet(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED)) {
return;
}
// Skip if we have the last hardened xpub cache
if (m_wallet_descriptor.cache.GetCachedLastHardenedExtPubKeys().size() > 0) {
return;
}
// Expand the descriptor
FlatSigningProvider provider;
provider.keys = GetKeys();
FlatSigningProvider out_keys;
std::vector<CScript> scripts_temp;
DescriptorCache temp_cache;
if (!m_wallet_descriptor.descriptor->Expand(0, provider, scripts_temp, out_keys, &temp_cache)){
throw std::runtime_error("Unable to expand descriptor");
}
// Cache the last hardened xpubs
DescriptorCache diff = m_wallet_descriptor.cache.MergeAndDiff(temp_cache);
if (!WalletBatch(m_storage.GetDatabase()).WriteDescriptorCacheItems(GetID(), diff)) {
throw std::runtime_error(std::string(__func__) + ": writing cache items failed");
}
}

View file

@ -631,6 +631,8 @@ public:
const std::vector<CScript> GetScriptPubKeys() const;
bool GetDescriptorString(std::string& out, bool priv) const;
void UpgradeDescriptorCache();
};
#endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H

View file

@ -374,6 +374,19 @@ void CWallet::UpgradeKeyMetadata()
SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
}
void CWallet::UpgradeDescriptorCache()
{
if (!IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS) || IsLocked() || IsWalletFlagSet(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED)) {
return;
}
for (ScriptPubKeyMan* spkm : GetAllScriptPubKeyMans()) {
DescriptorScriptPubKeyMan* desc_spkm = dynamic_cast<DescriptorScriptPubKeyMan*>(spkm);
desc_spkm->UpgradeDescriptorCache();
}
SetWalletFlag(WALLET_FLAG_LAST_HARDENED_XPUB_CACHED);
}
bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_keys)
{
CCrypter crypter;
@ -390,6 +403,8 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool accept_no_key
if (Unlock(_vMasterKey, accept_no_keys)) {
// Now that we've unlocked, upgrade the key metadata
UpgradeKeyMetadata();
// Now that we've unlocked, upgrade the descriptor cache
UpgradeDescriptorCache();
return true;
}
}

View file

@ -117,6 +117,7 @@ static constexpr uint64_t KNOWN_WALLET_FLAGS =
WALLET_FLAG_AVOID_REUSE
| WALLET_FLAG_BLANK_WALLET
| WALLET_FLAG_KEY_ORIGIN_METADATA
| WALLET_FLAG_LAST_HARDENED_XPUB_CACHED
| WALLET_FLAG_DISABLE_PRIVATE_KEYS
| WALLET_FLAG_DESCRIPTORS
| WALLET_FLAG_EXTERNAL_SIGNER;
@ -128,6 +129,7 @@ static const std::map<std::string,WalletFlags> WALLET_FLAG_MAP{
{"avoid_reuse", WALLET_FLAG_AVOID_REUSE},
{"blank", WALLET_FLAG_BLANK_WALLET},
{"key_origin_metadata", WALLET_FLAG_KEY_ORIGIN_METADATA},
{"last_hardened_xpub_cached", WALLET_FLAG_LAST_HARDENED_XPUB_CACHED},
{"disable_private_keys", WALLET_FLAG_DISABLE_PRIVATE_KEYS},
{"descriptor_wallet", WALLET_FLAG_DESCRIPTORS},
{"external_signer", WALLET_FLAG_EXTERNAL_SIGNER}
@ -476,6 +478,9 @@ public:
//! Upgrade stored CKeyMetadata objects to store key origin info as KeyOriginInfo
void UpgradeKeyMetadata() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
//! Upgrade DescriptorCaches
void UpgradeDescriptorCache() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; return true; }
//! Adds a destination data tuple to the store, without saving it to disk

View file

@ -884,6 +884,14 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
result = DBErrors::CORRUPT;
}
// Upgrade all of the descriptor caches to cache the last hardened xpub
// This operation is not atomic, but if it fails, only new entries are added so it is backwards compatible
try {
pwallet->UpgradeDescriptorCache();
} catch (...) {
result = DBErrors::CORRUPT;
}
// Set the inactive chain
if (wss.m_hd_chains.size() > 0) {
LegacyScriptPubKeyMan* legacy_spkm = pwallet->GetLegacyScriptPubKeyMan();

View file

@ -43,6 +43,9 @@ enum WalletFlags : uint64_t {
// Indicates that the metadata has already been upgraded to contain key origins
WALLET_FLAG_KEY_ORIGIN_METADATA = (1ULL << 1),
// Indicates that the descriptor cache has been upgraded to cache last hardened xpubs
WALLET_FLAG_LAST_HARDENED_XPUB_CACHED = (1ULL << 2),
// will enforce the rule that the wallet can't contain any private keys (only watch-only/pubkeys)
WALLET_FLAG_DISABLE_PRIVATE_KEYS = (1ULL << 32),