aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Dobson <dobsonsa68@gmail.com>2021-09-28 22:00:44 +1300
committerSamuel Dobson <dobsonsa68@gmail.com>2021-09-30 12:06:27 +1300
commitf963b0fa8cdd5223feb828c5faf6c57bc4107c8a (patch)
tree12feca3470a7ff8c17467822cbc1fa30cc0cf2e3
parent6c006495ef07f163d0734ec35d3cd1589a4aae9d (diff)
Corrupt wallet tx shouldn't trigger rescan of all wallets
-rw-r--r--src/wallet/wallet.cpp17
-rw-r--r--src/wallet/wallet.h2
-rw-r--r--src/wallet/walletdb.cpp8
-rw-r--r--src/wallet/walletdb.h3
-rw-r--r--src/wallet/wallettool.cpp4
5 files changed, 23 insertions, 11 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 6885499be2..1888d04f6d 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2007,10 +2007,7 @@ DBErrors CWallet::LoadWallet()
assert(m_internal_spk_managers.empty());
}
- if (nLoadWalletRet != DBErrors::LOAD_OK)
- return nLoadWalletRet;
-
- return DBErrors::LOAD_OK;
+ return nLoadWalletRet;
}
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
// TODO: Can't use std::make_shared because we need a custom deleter but
// should be possible to use std::allocate_shared.
std::shared_ptr<CWallet> walletInstance(new CWallet(chain, name, std::move(database)), ReleaseWallet);
+ bool rescan_required = false;
DBErrors nLoadWalletRet = walletInstance->LoadWallet();
if (nLoadWalletRet != DBErrors::LOAD_OK) {
if (nLoadWalletRet == DBErrors::CORRUPT) {
@@ -2562,6 +2560,10 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
{
error = strprintf(_("Wallet needed to be rewritten: restart %s to complete"), PACKAGE_NAME);
return nullptr;
+ } else if (nLoadWalletRet == DBErrors::RESCAN_REQUIRED) {
+ warnings.push_back(strprintf(_("Error reading %s! Transaction data may be missing or incorrect."
+ " Rescanning wallet."), walletFile));
+ rescan_required = true;
}
else {
error = strprintf(_("Error loading %s"), walletFile);
@@ -2753,7 +2755,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
LOCK(walletInstance->cs_wallet);
- if (chain && !AttachChain(walletInstance, *chain, error, warnings)) {
+ if (chain && !AttachChain(walletInstance, *chain, rescan_required, error, warnings)) {
return nullptr;
}
@@ -2775,7 +2777,7 @@ std::shared_ptr<CWallet> CWallet::Create(WalletContext& context, const std::stri
return walletInstance;
}
-bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, bilingual_str& error, std::vector<bilingual_str>& warnings)
+bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector<bilingual_str>& warnings)
{
LOCK(walletInstance->cs_wallet);
// 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
// interface.
walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
+ // If either rescan_required = true or -rescan is set, rescan_height remains equal to 0
int rescan_height = 0;
- if (!gArgs.GetBoolArg("-rescan", false))
+ if (!rescan_required && !gArgs.GetBoolArg("-rescan", false))
{
WalletBatch batch(walletInstance->GetDatabase());
CBlockLocator locator;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 15a5933424..cedccf7d44 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -337,7 +337,7 @@ private:
* block locator and m_last_block_processed, and registering for
* notifications about new blocks and transactions.
*/
- static bool AttachChain(const std::shared_ptr<CWallet>& wallet, interfaces::Chain& chain, bilingual_str& error, std::vector<bilingual_str>& warnings);
+ static bool AttachChain(const std::shared_ptr<CWallet>& wallet, interfaces::Chain& chain, const bool rescan_required, bilingual_str& error, std::vector<bilingual_str>& warnings);
public:
/**
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index c697534c06..11c35e70e9 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -755,6 +755,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
{
CWalletScanState wss;
bool fNoncriticalErrors = false;
+ bool rescan_required = false;
DBErrors result = DBErrors::LOAD_OK;
LOCK(pwallet->cs_wallet);
@@ -823,7 +824,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
fNoncriticalErrors = true; // ... but do warn the user there is something wrong.
if (strType == DBKeys::TX)
// Rescan if there is a bad transaction record:
- gArgs.SoftSetBoolArg("-rescan", true);
+ rescan_required = true;
}
}
if (!strErr.empty())
@@ -859,8 +860,11 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
((DescriptorScriptPubKeyMan*)spk_man)->AddCryptedKey(desc_key_pair.first.second, desc_key_pair.second.first, desc_key_pair.second.second);
}
- if (fNoncriticalErrors && result == DBErrors::LOAD_OK)
+ if (rescan_required && result == DBErrors::LOAD_OK) {
+ result = DBErrors::RESCAN_REQUIRED;
+ } else if (fNoncriticalErrors && result == DBErrors::LOAD_OK) {
result = DBErrors::NONCRITICAL_ERROR;
+ }
// Any wallet corruption at all: skip any rewriting or
// upgrading, we don't want to make it worse.
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index a549c8039c..39d1e2615c 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -48,7 +48,8 @@ enum class DBErrors
NONCRITICAL_ERROR,
TOO_NEW,
LOAD_FAIL,
- NEED_REWRITE
+ NEED_REWRITE,
+ RESCAN_REQUIRED
};
namespace DBKeys {
diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp
index 50b6c9d29f..4abfde76e2 100644
--- a/src/wallet/wallettool.cpp
+++ b/src/wallet/wallettool.cpp
@@ -76,6 +76,10 @@ static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::pa
} else if (load_wallet_ret == DBErrors::NEED_REWRITE) {
tfm::format(std::cerr, "Wallet needed to be rewritten: restart %s to complete", PACKAGE_NAME);
return nullptr;
+ } else if (load_wallet_ret == DBErrors::RESCAN_REQUIRED) {
+ tfm::format(std::cerr, "Error reading %s! Some transaction data might be missing or"
+ " incorrect. Wallet requires a rescan.",
+ name);
} else {
tfm::format(std::cerr, "Error loading %s", name);
return nullptr;