mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-12 06:58:57 +01:00
Avoid pemanent cs_main/cs_wallet lock during wallet rescans
This commit is contained in:
@@ -1614,14 +1614,15 @@ void CWalletTx::GetAmounts(std::list<COutputEntry>& listReceived,
|
||||
*/
|
||||
int64_t CWallet::RescanFromTime(int64_t startTime, bool update)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
AssertLockHeld(cs_wallet);
|
||||
|
||||
// Find starting block. May be null if nCreateTime is greater than the
|
||||
// highest blockchain timestamp, in which case there is nothing that needs
|
||||
// to be scanned.
|
||||
CBlockIndex* const startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW);
|
||||
LogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0);
|
||||
CBlockIndex* startBlock = nullptr;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
startBlock = chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW);
|
||||
LogPrintf("%s: Rescanning last %i blocks\n", __func__, startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0);
|
||||
}
|
||||
|
||||
if (startBlock) {
|
||||
const CBlockIndex* const failedBlock = ScanForWalletTransactions(startBlock, nullptr, update);
|
||||
@@ -1643,6 +1644,10 @@ int64_t CWallet::RescanFromTime(int64_t startTime, bool update)
|
||||
*
|
||||
* If pindexStop is not a nullptr, the scan will stop at the block-index
|
||||
* defined by pindexStop
|
||||
*
|
||||
* 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, bool fUpdate)
|
||||
{
|
||||
@@ -1656,24 +1661,49 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
|
||||
CBlockIndex* pindex = pindexStart;
|
||||
CBlockIndex* ret = nullptr;
|
||||
{
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
fAbortRescan = false;
|
||||
fScanningWallet = true;
|
||||
|
||||
ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
|
||||
double dProgressStart = GuessVerificationProgress(chainParams.TxData(), pindex);
|
||||
double dProgressTip = GuessVerificationProgress(chainParams.TxData(), chainActive.Tip());
|
||||
CBlockIndex* tip = nullptr;
|
||||
double dProgressStart;
|
||||
double dProgressTip;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
tip = chainActive.Tip();
|
||||
dProgressStart = GuessVerificationProgress(chainParams.TxData(), pindex);
|
||||
dProgressTip = GuessVerificationProgress(chainParams.TxData(), tip);
|
||||
}
|
||||
while (pindex && !fAbortRescan)
|
||||
{
|
||||
if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0)
|
||||
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((GuessVerificationProgress(chainParams.TxData(), pindex) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
|
||||
if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) {
|
||||
double gvp = 0;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
gvp = GuessVerificationProgress(chainParams.TxData(), pindex);
|
||||
}
|
||||
ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((gvp - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
|
||||
}
|
||||
if (GetTime() >= nNow + 60) {
|
||||
nNow = GetTime();
|
||||
LOCK(cs_main);
|
||||
LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex));
|
||||
}
|
||||
|
||||
bool readRet = false;
|
||||
CBlock block;
|
||||
if (ReadBlockFromDisk(block, pindex, Params().GetConsensus())) {
|
||||
{
|
||||
LOCK(cs_main);
|
||||
readRet = ReadBlockFromDisk(block, pindex, Params().GetConsensus());
|
||||
}
|
||||
if (readRet) {
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) {
|
||||
AddToWalletIfInvolvingMe(block.vtx[posInBlock], pindex, posInBlock, fUpdate);
|
||||
}
|
||||
@@ -1683,7 +1713,15 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlock
|
||||
if (pindex == pindexStop) {
|
||||
break;
|
||||
}
|
||||
pindex = chainActive.Next(pindex);
|
||||
{
|
||||
LOCK(cs_main);
|
||||
pindex = chainActive.Next(pindex);
|
||||
if (tip != chainActive.Tip()) {
|
||||
tip = chainActive.Tip();
|
||||
// in case the tip has changed, update progress max
|
||||
dProgressTip = GuessVerificationProgress(chainParams.TxData(), tip);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pindex && fAbortRescan) {
|
||||
LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex));
|
||||
|
||||
Reference in New Issue
Block a user