Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/wallet/scriptpubkeyman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,11 +427,11 @@ void LegacyScriptPubKeyMan::GenerateNewHDChain(const SecureString& secureMnemoni
}
}

bool LegacyScriptPubKeyMan::LoadHDChain(const CHDChain& chain)
bool LegacyScriptPubKeyMan::LoadHDChain(const CHDChain& chain, bool skip_encryption_check)
{
LOCK(cs_KeyStore);

if (m_storage.HasEncryptionKeys() != chain.IsCrypted()) return false;
if (!skip_encryption_check && m_storage.HasEncryptionKeys() != chain.IsCrypted()) return false;

m_hd_chain = chain;
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/scriptpubkeyman.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ class LegacyScriptPubKeyMan : public ScriptPubKeyMan, public FillableSigningProv
/* Set the HD chain model (chain child index counters) and writes it to the database */
bool AddHDChain(WalletBatch &batch, const CHDChain& chain);
//! Load a HD chain model (used by LoadWallet)
bool LoadHDChain(const CHDChain& chain);
bool LoadHDChain(const CHDChain& chain, bool skip_encryption_check = false);
/**
* Set the HD chain model (chain child index counters) using temporary wallet db object
* which causes db flush every time these methods are used
Expand Down
24 changes: 21 additions & 3 deletions src/wallet/walletdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,9 +572,10 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
CHDChain chain;
ssValue >> chain;
assert ((strType == DBKeys::CRYPTED_HDCHAIN) == chain.IsCrypted());
if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadHDChain(chain))
{
strErr = "Error reading wallet database: SetHDChain failed";
// Skip encryption check during loading as MASTER_KEY records may not be loaded yet.
// Consistency will be validated after all records are loaded.
if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadHDChain(chain, /*skip_encryption_check=*/true)) {
strErr = "Error reading wallet database: LoadHDChain failed";
return false;
}
} else if (strType == DBKeys::HDPUBKEY) {
Expand Down Expand Up @@ -875,6 +876,23 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
}
m_batch->CloseCursor();

// Validate HD chain encryption consistency now that all data is loaded
if (auto spk_man = pwallet->GetLegacyScriptPubKeyMan()) {
CHDChain hdChain;
if (spk_man->GetHDChain(hdChain)) {
// If HD chain exists, validate encryption consistency
bool fHasMasterKeys = pwallet->HasEncryptionKeys();
bool fChainCrypted = hdChain.IsCrypted();

if (fHasMasterKeys != fChainCrypted) {
pwallet->WalletLogPrintf("Error: HD chain encryption state (%s) inconsistent with wallet encryption state (%s)\n",
fChainCrypted ? "encrypted" : "not encrypted",
fHasMasterKeys ? "encrypted" : "not encrypted");
return DBErrors::CORRUPT;
}
}
}

// Set the active ScriptPubKeyMans
for (auto spk_man : wss.m_active_external_spks) {
pwallet->LoadActiveScriptPubKeyMan(spk_man.second, /*internal=*/false);
Expand Down
Loading