Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 1,796 Lines • ▼ Show 20 Lines | CBlockIndex *startBlock = nullptr; | ||||
::ChainActive().FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW); | ::ChainActive().FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW); | ||||
WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, | WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, | ||||
startBlock | startBlock | ||||
? ::ChainActive().Height() - startBlock->nHeight + 1 | ? ::ChainActive().Height() - startBlock->nHeight + 1 | ||||
: 0); | : 0); | ||||
} | } | ||||
if (startBlock) { | if (startBlock) { | ||||
const CBlockIndex *failedBlock; | const CBlockIndex *failedBlock, *stop_block; | ||||
// TODO: this should take into account failure by ScanResult::USER_ABORT | // TODO: this should take into account failure by ScanResult::USER_ABORT | ||||
if (ScanResult::FAILURE == | if (ScanResult::FAILURE == | ||||
ScanForWalletTransactions(startBlock, nullptr, reserver, | ScanForWalletTransactions(startBlock, nullptr, reserver, | ||||
failedBlock, update)) { | failedBlock, stop_block, update)) { | ||||
return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1; | return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1; | ||||
} | } | ||||
} | } | ||||
return startTime; | return startTime; | ||||
} | } | ||||
/** | /** | ||||
* Scan the block chain (starting in pindexStart) for transactions from or to | * Scan the block chain (starting in pindexStart) for transactions from or to | ||||
* us. If fUpdate is true, found transactions that already exist in the wallet | * us. If fUpdate is true, found transactions that already exist in the wallet | ||||
* will be updated. | * will be updated. | ||||
* | * | ||||
* @param[in] pindexStop if not a nullptr, the scan will stop at this | * @param[in] pindexStop if not a nullptr, the scan will stop at this | ||||
* block-index | * block-index | ||||
* @param[out] failed_block if FAILURE is returned, will be set to the most | * @param[out] failed_block if FAILURE is returned, the most recent block | ||||
* recent block that could not be scanned, otherwise nullptr. | * 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 | |||||
* | * | ||||
* @return ScanResult indicating success or failure of the scan. SUCCESS if | * @return ScanResult indicating success or failure of the scan. SUCCESS if | ||||
* scan was successful. FAILURE if a complete rescan was not possible (due to | * 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 | * pruning or corruption). USER_ABORT if the rescan was aborted before it | ||||
* could complete. | * could complete. | ||||
* | * | ||||
* @pre Caller needs to make sure pindexStop (and the optional pindexStart) are | * @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 | * on the main chain after to the addition of any new keys you want to detect | ||||
* transactions for. | * transactions for. | ||||
*/ | */ | ||||
CWallet::ScanResult CWallet::ScanForWalletTransactions( | CWallet::ScanResult CWallet::ScanForWalletTransactions( | ||||
const CBlockIndex *const pindexStart, const CBlockIndex *const pindexStop, | const CBlockIndex *const pindexStart, const CBlockIndex *const pindexStop, | ||||
const WalletRescanReserver &reserver, const CBlockIndex *&failed_block, | const WalletRescanReserver &reserver, const CBlockIndex *&failed_block, | ||||
bool fUpdate) { | const CBlockIndex *&stop_block, bool fUpdate) { | ||||
int64_t nNow = GetTime(); | int64_t nNow = GetTime(); | ||||
assert(reserver.isReserved()); | assert(reserver.isReserved()); | ||||
if (pindexStop) { | if (pindexStop) { | ||||
assert(pindexStop->nHeight >= pindexStart->nHeight); | assert(pindexStop->nHeight >= pindexStart->nHeight); | ||||
} | } | ||||
const CBlockIndex *pindex = pindexStart; | const CBlockIndex *pindex = pindexStart; | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | if (pindex) { | ||||
failed_block = pindex; | failed_block = pindex; | ||||
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], pindex, posInBlock, | SyncTransaction(block.vtx[posInBlock], pindex, posInBlock, | ||||
fUpdate); | fUpdate); | ||||
} | } | ||||
// scan succeeded, record block as most recent successfully | |||||
// scanned | |||||
stop_block = pindex; | |||||
} else { | } else { | ||||
// could not scan block, keep scanning but record this block as | |||||
// the most recent failure | |||||
failed_block = pindex; | failed_block = pindex; | ||||
} | } | ||||
if (pindex == pindexStop) { | if (pindex == pindexStop) { | ||||
break; | break; | ||||
} | } | ||||
{ | { | ||||
auto locked_chain = chain().lock(); | auto locked_chain = chain().lock(); | ||||
pindex = ::ChainActive().Next(pindex); | pindex = ::ChainActive().Next(pindex); | ||||
▲ Show 20 Lines • Show All 2,798 Lines • ▼ Show 20 Lines | if (::ChainActive().Tip() && ::ChainActive().Tip() != pindexRescan) { | ||||
(pindexRescan->GetBlockTime() < | (pindexRescan->GetBlockTime() < | ||||
(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) { | (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) { | ||||
pindexRescan = ::ChainActive().Next(pindexRescan); | pindexRescan = ::ChainActive().Next(pindexRescan); | ||||
} | } | ||||
nStart = GetTimeMillis(); | nStart = GetTimeMillis(); | ||||
{ | { | ||||
WalletRescanReserver reserver(walletInstance.get()); | WalletRescanReserver reserver(walletInstance.get()); | ||||
const CBlockIndex *stop_block; | const CBlockIndex *stop_block, *failed_block; | ||||
if (!reserver.reserve() || | if (!reserver.reserve() || | ||||
(ScanResult::SUCCESS != | (ScanResult::SUCCESS != | ||||
walletInstance->ScanForWalletTransactions( | walletInstance->ScanForWalletTransactions( | ||||
pindexRescan, nullptr, reserver, stop_block, true))) { | pindexRescan, nullptr, reserver, failed_block, stop_block, | ||||
true))) { | |||||
InitError( | InitError( | ||||
_("Failed to rescan the wallet during initialization")); | _("Failed to rescan the wallet during initialization")); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
walletInstance->WalletLogPrintf("Rescan completed in %15dms\n", | walletInstance->WalletLogPrintf("Rescan completed in %15dms\n", | ||||
GetTimeMillis() - nStart); | GetTimeMillis() - nStart); | ||||
walletInstance->ChainStateFlushed(::ChainActive().GetLocator()); | walletInstance->ChainStateFlushed(::ChainActive().GetLocator()); | ||||
▲ Show 20 Lines • Show All 209 Lines • Show Last 20 Lines |