Skip to content

Commit f963b0f

Browse files
committed
Corrupt wallet tx shouldn't trigger rescan of all wallets
1 parent 6c00649 commit f963b0f

File tree

5 files changed

+23
-11
lines changed

5 files changed

+23
-11
lines changed

src/wallet/wallet.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,10 +2007,7 @@ DBErrors CWallet::LoadWallet()
20072007
assert(m_internal_spk_managers.empty());
20082008
}
20092009

2010-
if (nLoadWalletRet != DBErrors::LOAD_OK)
2011-
return nLoadWalletRet;
2012-
2013-
return DBErrors::LOAD_OK;
2010+
return nLoadWalletRet;
20142011
}
20152012

20162013
DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut)
@@ -2542,6 +2539,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
25422539
// TODO: Can't use std::make_shared because we need a custom deleter but
25432540
// should be possible to use std::allocate_shared.
25442541
std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), ReleaseWallet);
2542+
bool rescan_required = false;
25452543
DBErrors nLoadWalletRet = walletInstance->LoadWallet();
25462544
if (nLoadWalletRet != DBErrors::LOAD_OK) {
25472545
if (nLoadWalletRet == DBErrors::CORRUPT) {
@@ -2562,6 +2560,10 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
25622560
{
25632561
error = strprintf(_("Wallet needed to be rewritten: restart %s to complete"), PACKAGE_NAME);
25642562
return nullptr;
2563+
} else if (nLoadWalletRet == DBErrors::RESCAN_REQUIRED) {
2564+
warnings.push_back(strprintf(_("Error reading %s! Transaction data may be missing or incorrect."
2565+
" Rescanning wallet."), walletFile));
2566+
rescan_required = true;
25652567
}
25662568
else {
25672569
error = strprintf(_("Error loading %s"), walletFile);
@@ -2753,7 +2755,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
27532755

27542756
LOCK(walletInstance->cs_wallet);
27552757

2756-
if (chain && !AttachChain(walletInstance, *chain, error, warnings)) {
2758+
if (chain && !AttachChain(walletInstance, *chain, rescan_required, error, warnings)) {
27572759
return nullptr;
27582760
}
27592761

@@ -2775,7 +2777,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
27752777
return walletInstance;
27762778
}
27772779

2778-
bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, bilingual_str& error, std::vector<bilingual_str>& warnings)
2780+
bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector<bilingual_str>& warnings)
27792781
{
27802782
LOCK(walletInstance->cs_wallet);
27812783
// allow setting the chain if it hasn't been set already but prevent changing it
@@ -2792,8 +2794,9 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
27922794
// interface.
27932795
walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
27942796

2797+
// If either rescan_required = true or -rescan is set, rescan_height remains equal to 0
27952798
int rescan_height = 0;
2796-
if (!gArgs.GetBoolArg("-rescan", false))
2799+
if (!rescan_required && !gArgs.GetBoolArg("-rescan", false))
27972800
{
27982801
WalletBatch batch(walletInstance->GetDatabase());
27992802
CBlockLocator locator;

src/wallet/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
337337
* block locator and m_last_block_processed, and registering for
338338
* notifications about new blocks and transactions.
339339
*/
340-
static bool AttachChain(const std::shared_ptr<CWallet>& wallet, interfaces::Chain& chain, bilingual_str& error, std::vector<bilingual_str>& warnings);
340+
static bool AttachChain(const std::shared_ptr<CWallet>& wallet, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector<bilingual_str>& warnings);
341341

342342
public:
343343
/**

src/wallet/walletdb.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
755755
{
756756
CWalletScanState wss;
757757
bool fNoncriticalErrors = false;
758+
bool rescan_required = false;
758759
DBErrors result = DBErrors::LOAD_OK;
759760

760761
LOCK(pwallet->cs_wallet);
@@ -823,7 +824,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
823824
fNoncriticalErrors = true; // ... but do warn the user there is something wrong.
824825
if (strType == DBKeys::TX)
825826
// Rescan if there is a bad transaction record:
826-
gArgs.SoftSetBoolArg("-rescan", true);
827+
rescan_required = true;
827828
}
828829
}
829830
if (!strErr.empty())
@@ -859,8 +860,11 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
859860
((DescriptorScriptPubKeyMan*)spk_man)->AddCryptedKey(desc_key_pair.first.second, desc_key_pair.second.first, desc_key_pair.second.second);
860861
}
861862

862-
if (fNoncriticalErrors && result == DBErrors::LOAD_OK)
863+
if (rescan_required && result == DBErrors::LOAD_OK) {
864+
result = DBErrors::RESCAN_REQUIRED;
865+
} else if (fNoncriticalErrors && result == DBErrors::LOAD_OK) {
863866
result = DBErrors::NONCRITICAL_ERROR;
867+
}
864868

865869
// Any wallet corruption at all: skip any rewriting or
866870
// upgrading, we don't want to make it worse.

src/wallet/walletdb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ enum class DBErrors
4848
NONCRITICAL_ERROR,
4949
TOO_NEW,
5050
LOAD_FAIL,
51-
NEED_REWRITE
51+
NEED_REWRITE,
52+
RESCAN_REQUIRED
5253
};
5354

5455
namespace DBKeys {

src/wallet/wallettool.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::pa
7676
} else if (load_wallet_ret == DBErrors::NEED_REWRITE) {
7777
tfm::format(std::cerr, "Wallet needed to be rewritten: restart %s to complete", PACKAGE_NAME);
7878
return nullptr;
79+
} else if (load_wallet_ret == DBErrors::RESCAN_REQUIRED) {
80+
tfm::format(std::cerr, "Error reading %s! Some transaction data might be missing or"
81+
" incorrect. Wallet requires a rescan.",
82+
name);
7983
} else {
8084
tfm::format(std::cerr, "Error loading %s", name);
8185
return nullptr;

0 commit comments

Comments
 (0)