Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 2,165 Lines • ▼ Show 20 Lines | CWallet::ScanResult CWallet::ScanForWalletTransactions( | ||||
assert(reserver.isReserved()); | assert(reserver.isReserved()); | ||||
BlockHash block_hash = start_block; | BlockHash block_hash = start_block; | ||||
ScanResult result; | ScanResult result; | ||||
WalletLogPrintf("Rescan started from block %s...\n", | WalletLogPrintf("Rescan started from block %s...\n", | ||||
start_block.ToString()); | start_block.ToString()); | ||||
{ | |||||
fAbortRescan = false; | fAbortRescan = false; | ||||
// Show rescan progress in GUI as dialog or on splashscreen, if -rescan | // Show rescan progress in GUI as dialog or on splashscreen, if -rescan | ||||
// on startup. | // on startup. | ||||
ShowProgress( | ShowProgress( | ||||
strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), | strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), 0); | ||||
0); | |||||
BlockHash tip_hash; | BlockHash tip_hash; | ||||
// The way the 'block_height' is initialized is just a workaround for | // The way the 'block_height' is initialized is just a workaround for | ||||
// the gcc bug #47679 since version 4.6.0. | // the gcc bug #47679 since version 4.6.0. | ||||
Optional<int> block_height = MakeOptional(false, int()); | Optional<int> block_height = MakeOptional(false, int()); | ||||
double progress_begin; | double progress_begin; | ||||
double progress_end; | double progress_end; | ||||
{ | { | ||||
auto locked_chain = chain().lock(); | auto locked_chain = chain().lock(); | ||||
if (Optional<int> tip_height = locked_chain->getHeight()) { | if (Optional<int> tip_height = locked_chain->getHeight()) { | ||||
tip_hash = locked_chain->getBlockHash(*tip_height); | tip_hash = locked_chain->getBlockHash(*tip_height); | ||||
} | } | ||||
block_height = locked_chain->getBlockHeight(block_hash); | block_height = locked_chain->getBlockHeight(block_hash); | ||||
progress_begin = chain().guessVerificationProgress(block_hash); | progress_begin = chain().guessVerificationProgress(block_hash); | ||||
progress_end = chain().guessVerificationProgress( | progress_end = chain().guessVerificationProgress( | ||||
stop_block.IsNull() ? tip_hash : stop_block); | stop_block.IsNull() ? tip_hash : stop_block); | ||||
} | } | ||||
double progress_current = progress_begin; | double progress_current = progress_begin; | ||||
while (block_height && !fAbortRescan && !chain().shutdownRequested()) { | while (block_height && !fAbortRescan && !chain().shutdownRequested()) { | ||||
m_scanning_progress = (progress_current - progress_begin) / | m_scanning_progress = (progress_current - progress_begin) / | ||||
(progress_end - progress_begin); | (progress_end - progress_begin); | ||||
if (*block_height % 100 == 0 && | if (*block_height % 100 == 0 && progress_end - progress_begin > 0.0) { | ||||
progress_end - progress_begin > 0.0) { | |||||
ShowProgress( | ShowProgress( | ||||
strprintf("%s " + _("Rescanning...").translated, | strprintf("%s " + _("Rescanning...").translated, | ||||
GetDisplayName()), | GetDisplayName()), | ||||
std::max(1, std::min(99, int(m_scanning_progress * 100)))); | std::max(1, std::min(99, int(m_scanning_progress * 100)))); | ||||
} | } | ||||
if (GetTime() >= nNow + 60) { | if (GetTime() >= nNow + 60) { | ||||
nNow = GetTime(); | nNow = GetTime(); | ||||
WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", | WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", | ||||
*block_height, progress_current); | *block_height, progress_current); | ||||
} | } | ||||
CBlock block; | CBlock block; | ||||
if (chain().findBlock(block_hash, &block) && !block.IsNull()) { | if (chain().findBlock(block_hash, &block) && !block.IsNull()) { | ||||
auto locked_chain = chain().lock(); | auto locked_chain = chain().lock(); | ||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
if (!locked_chain->getBlockHeight(block_hash)) { | if (!locked_chain->getBlockHeight(block_hash)) { | ||||
// Abort scan if current block is no longer active, to | // Abort scan if current block is no longer active, to | ||||
// prevent marking transactions as coming from the wrong | // prevent marking transactions as coming from the wrong | ||||
// block. | // block. | ||||
// TODO: This should return success instead of failure, see | // TODO: This should return success instead of failure, see | ||||
// https://github.com/bitcoin/bitcoin/pull/14711#issuecomment-458342518 | // https://github.com/bitcoin/bitcoin/pull/14711#issuecomment-458342518 | ||||
result.last_failed_block = block_hash; | result.last_failed_block = block_hash; | ||||
result.status = ScanResult::FAILURE; | result.status = ScanResult::FAILURE; | ||||
break; | break; | ||||
} | } | ||||
for (size_t posInBlock = 0; posInBlock < block.vtx.size(); | for (size_t posInBlock = 0; posInBlock < block.vtx.size(); | ||||
++posInBlock) { | ++posInBlock) { | ||||
SyncTransaction(block.vtx[posInBlock], block_hash, | SyncTransaction(block.vtx[posInBlock], block_hash, posInBlock, | ||||
posInBlock, fUpdate); | fUpdate); | ||||
} | } | ||||
// scan succeeded, record block as most recent successfully | // scan succeeded, record block as most recent successfully | ||||
// scanned | // scanned | ||||
result.last_scanned_block = block_hash; | result.last_scanned_block = block_hash; | ||||
result.last_scanned_height = *block_height; | result.last_scanned_height = *block_height; | ||||
} else { | } else { | ||||
// could not scan block, keep scanning but record this block as | // could not scan block, keep scanning but record this block as | ||||
// the most recent failure | // the most recent failure | ||||
result.last_failed_block = block_hash; | result.last_failed_block = block_hash; | ||||
result.status = ScanResult::FAILURE; | result.status = ScanResult::FAILURE; | ||||
} | } | ||||
if (block_hash == stop_block) { | if (block_hash == stop_block) { | ||||
break; | break; | ||||
} | } | ||||
{ | { | ||||
auto locked_chain = chain().lock(); | auto locked_chain = chain().lock(); | ||||
Optional<int> tip_height = locked_chain->getHeight(); | Optional<int> tip_height = locked_chain->getHeight(); | ||||
if (!tip_height || *tip_height <= block_height || | if (!tip_height || *tip_height <= block_height || | ||||
!locked_chain->getBlockHeight(block_hash)) { | !locked_chain->getBlockHeight(block_hash)) { | ||||
// break successfully when rescan has reached the tip, or | // break successfully when rescan has reached the tip, or | ||||
// previous block is no longer on the chain due to a reorg | // previous block is no longer on the chain due to a reorg | ||||
break; | break; | ||||
} | } | ||||
// increment block and verification progress | // increment block and verification progress | ||||
block_hash = locked_chain->getBlockHash(++*block_height); | block_hash = locked_chain->getBlockHash(++*block_height); | ||||
progress_current = | progress_current = chain().guessVerificationProgress(block_hash); | ||||
chain().guessVerificationProgress(block_hash); | |||||
// handle updated tip hash | // handle updated tip hash | ||||
const BlockHash prev_tip_hash = tip_hash; | const BlockHash prev_tip_hash = tip_hash; | ||||
tip_hash = locked_chain->getBlockHash(*tip_height); | tip_hash = locked_chain->getBlockHash(*tip_height); | ||||
if (stop_block.IsNull() && prev_tip_hash != tip_hash) { | if (stop_block.IsNull() && prev_tip_hash != tip_hash) { | ||||
// in case the tip has changed, update progress max | // in case the tip has changed, update progress max | ||||
progress_end = chain().guessVerificationProgress(tip_hash); | progress_end = chain().guessVerificationProgress(tip_hash); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Hide progress dialog in GUI. | // Hide progress dialog in GUI. | ||||
ShowProgress( | ShowProgress( | ||||
strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), | strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), | ||||
100); | 100); | ||||
if (block_height && fAbortRescan) { | if (block_height && fAbortRescan) { | ||||
WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", | WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", | ||||
*block_height, progress_current); | *block_height, progress_current); | ||||
result.status = ScanResult::USER_ABORT; | result.status = ScanResult::USER_ABORT; | ||||
} else if (block_height && chain().shutdownRequested()) { | } else if (block_height && chain().shutdownRequested()) { | ||||
WalletLogPrintf("Rescan interrupted by shutdown request at block " | WalletLogPrintf("Rescan interrupted by shutdown request at block " | ||||
"%d. Progress=%f\n", | "%d. Progress=%f\n", | ||||
*block_height, progress_current); | *block_height, progress_current); | ||||
result.status = ScanResult::USER_ABORT; | result.status = ScanResult::USER_ABORT; | ||||
} else { | } else { | ||||
WalletLogPrintf("Rescan completed in %15dms\n", | WalletLogPrintf("Rescan completed in %15dms\n", | ||||
GetTimeMillis() - start_time); | GetTimeMillis() - start_time); | ||||
} | } | ||||
} | |||||
return result; | return result; | ||||
} | } | ||||
void CWallet::ReacceptWalletTransactions( | void CWallet::ReacceptWalletTransactions( | ||||
interfaces::Chain::Lock &locked_chain) { | interfaces::Chain::Lock &locked_chain) { | ||||
// If transactions aren't being broadcasted, don't let them into local | // If transactions aren't being broadcasted, don't let them into local | ||||
// mempool either. | // mempool either. | ||||
if (!fBroadcastTransactions) { | if (!fBroadcastTransactions) { | ||||
▲ Show 20 Lines • Show All 3,142 Lines • Show Last 20 Lines |