Skip to content

Commit 2b9279b

Browse files
committed
wallet: Remove unused encryption keys from watchonly wallets
Due to a bug in earlier versions, some wallets without private keys may have an encryption key. This encryption key is unused and can lead to confusing behavior elsewhere. When such wallets are detected, those encryption keys will now be deleted from the wallet. For safety, we only do this to wallets which have private keys disabled, have encryption keys, and definitely do not have encrypted keys.
1 parent 813a16a commit 2b9279b

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

src/wallet/walletdb.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@ bool WalletBatch::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
154154
return WriteIC(std::make_pair(DBKeys::MASTER_KEY, nID), kMasterKey, true);
155155
}
156156

157+
bool WalletBatch::EraseMasterKey(unsigned int id)
158+
{
159+
return EraseIC(std::make_pair(DBKeys::MASTER_KEY, id));
160+
}
161+
157162
bool WalletBatch::WriteCScript(const uint160& hash, const CScript& redeemScript)
158163
{
159164
return WriteIC(std::make_pair(DBKeys::CSCRIPT, hash), redeemScript, false);
@@ -1241,6 +1246,21 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
12411246
result = DBErrors::CORRUPT;
12421247
}
12431248

1249+
// Since it was accidentally possible to "encrypt" a wallet with private keys disabled, we should check if this is
1250+
// such a wallet and remove the encryption key records to avoid any future issues.
1251+
// Although wallets without private keys should not have *ckey records, we should double check that.
1252+
// Removing the mkey records is only safe if there are no *ckey records.
1253+
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && pwallet->HasEncryptionKeys() && !pwallet->HaveCryptedKeys()) {
1254+
pwallet->WalletLogPrintf("Detected extraneous encryption keys in this wallet without private keys. Removing extraneous encryption keys.\n");
1255+
for (const auto& [id, _] : pwallet->mapMasterKeys) {
1256+
if (!EraseMasterKey(id)) {
1257+
pwallet->WalletLogPrintf("Error: Unable to remove extraneous encryption key '%u'. Wallet corrupt.\n", id);
1258+
return DBErrors::CORRUPT;
1259+
}
1260+
}
1261+
pwallet->mapMasterKeys.clear();
1262+
}
1263+
12441264
return result;
12451265
}
12461266

src/wallet/walletdb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ class WalletBatch
238238
bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata &keyMeta);
239239
bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta);
240240
bool WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey);
241+
bool EraseMasterKey(unsigned int id);
241242

242243
bool WriteCScript(const uint160& hash, const CScript& redeemScript);
243244

0 commit comments

Comments
 (0)