New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix ScanForWalletTransactions to return an enum indicating scan result: success / failure / user_abort #13076
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1613,8 +1613,9 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r | |
} | ||
|
||
if (startBlock) { | ||
const CBlockIndex* const failedBlock = ScanForWalletTransactions(startBlock, nullptr, reserver, update); | ||
if (failedBlock) { | ||
const CBlockIndex *failedBlock, *stop_block; | ||
// TODO: this should take into account failure by ScanResult::USER_ABORT | ||
if (ScanResult::FAILURE == ScanForWalletTransactions(startBlock, nullptr, reserver, failedBlock, stop_block, update)) { | ||
return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1; | ||
} | ||
} | ||
|
@@ -1626,18 +1627,22 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r | |
* from or to us. If fUpdate is true, found transactions that already | ||
* exist in the wallet will be updated. | ||
* | ||
* Returns null if scan was successful. Otherwise, if a complete rescan was not | ||
* possible (due to pruning or corruption), returns pointer to the most recent | ||
* block that could not be scanned. | ||
* @param[in] pindexStop if not a nullptr, the scan will stop at this block-index | ||
* @param[out] failed_block if FAILURE is returned, the most recent block | ||
* that could not be scanned, otherwise nullptr | ||
* @param[out] stop_block the most recent block that could be scanned, | ||
* otherwise nullptr if no block could be scanned | ||
* | ||
* If pindexStop is not a nullptr, the scan will stop at the block-index | ||
* defined by pindexStop | ||
* @return ScanResult indicating success or failure of the scan. SUCCESS if | ||
* scan was successful. FAILURE if a complete rescan was not possible (due to | ||
* pruning or corruption). USER_ABORT if the rescan was aborted before it | ||
* could complete. | ||
* | ||
* Caller needs to make sure pindexStop (and the optional pindexStart) are on | ||
* @pre Caller needs to make sure pindexStop (and the optional pindexStart) are on | ||
* the main chain after to the addition of any new keys you want to detect | ||
* transactions for. | ||
*/ | ||
CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver &reserver, bool fUpdate) | ||
CWallet::ScanResult CWallet::ScanForWalletTransactions(const CBlockIndex* const pindexStart, const CBlockIndex* const pindexStop, const WalletRescanReserver& reserver, const CBlockIndex*& failed_block, const CBlockIndex*& stop_block, bool fUpdate) | ||
{ | ||
int64_t nNow = GetTime(); | ||
const CChainParams& chainParams = Params(); | ||
|
@@ -1647,8 +1652,8 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock | |
assert(pindexStop->nHeight >= pindexStart->nHeight); | ||
} | ||
|
||
CBlockIndex* pindex = pindexStart; | ||
CBlockIndex* ret = nullptr; | ||
const CBlockIndex* pindex = pindexStart; | ||
failed_block = nullptr; | ||
|
||
if (pindex) WalletLogPrintf("Rescan started from block %d...\n", pindex->nHeight); | ||
|
||
|
@@ -1669,8 +1674,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock | |
} | ||
} | ||
double progress_current = progress_begin; | ||
while (pindex && !fAbortRescan && !ShutdownRequested()) | ||
{ | ||
while (pindex && !fAbortRescan && !ShutdownRequested()) { | ||
if (pindex->nHeight % 100 == 0 && progress_end - progress_begin > 0.0) { | ||
ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), std::max(1, std::min(99, (int)((progress_current - progress_begin) / (progress_end - progress_begin) * 100)))); | ||
} | ||
|
@@ -1686,14 +1690,17 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock | |
if (pindex && !chainActive.Contains(pindex)) { | ||
// Abort scan if current block is no longer active, to prevent | ||
// marking transactions as coming from the wrong block. | ||
ret = pindex; | ||
failed_block = pindex; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you might want to drop this line and just return true here, to fix the regression described here: #12275 (comment). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure about that - my inclination is to maintain stricter checking at the risk of spurious failures over less strict checking at the risk of silent failure. How about opening a separate PR for that so it can be considered separately? |
||
break; | ||
} | ||
for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) { | ||
SyncTransaction(block.vtx[posInBlock], pindex, posInBlock, fUpdate); | ||
} | ||
// scan succeeded, record block as most recent successfully scanned | ||
stop_block = pindex; | ||
} else { | ||
ret = pindex; | ||
// could not scan block, keep scanning but record this block as the most recent failure | ||
failed_block = pindex; | ||
} | ||
if (pindex == pindexStop) { | ||
break; | ||
|
@@ -1709,14 +1716,20 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock | |
} | ||
} | ||
} | ||
ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 100); // hide progress dialog in GUI | ||
if (pindex && fAbortRescan) { | ||
WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, progress_current); | ||
return ScanResult::USER_ABORT; | ||
} else if (pindex && ShutdownRequested()) { | ||
WalletLogPrintf("Rescan interrupted by shutdown request at block %d. Progress=%f\n", pindex->nHeight, progress_current); | ||
return ScanResult::USER_ABORT; | ||
} | ||
ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 100); // hide progress dialog in GUI | ||
} | ||
return ret; | ||
if (failed_block) { | ||
return ScanResult::FAILURE; | ||
} else { | ||
return ScanResult::SUCCESS; | ||
} | ||
} | ||
|
||
void CWallet::ReacceptWalletTransactions() | ||
|
@@ -4166,11 +4179,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, | |
nStart = GetTimeMillis(); | ||
{ | ||
WalletRescanReserver reserver(walletInstance.get()); | ||
if (!reserver.reserve()) { | ||
const CBlockIndex *stop_block, *failed_block; | ||
if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, failed_block, stop_block, true))) { | ||
InitError(_("Failed to rescan the wallet during initialization")); | ||
return nullptr; | ||
} | ||
walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, reserver, true); | ||
} | ||
walletInstance->WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - nStart); | ||
walletInstance->ChainStateFlushed(chainActive.GetLocator()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code is not setting
stop_block
null here, which seems unintended and could lead to uninitialized variables. Would be good to fix this or add documentation if it was done intentionally.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right, the code does contradict the comments on line 1634. Will open a PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#14957