Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 1,800 Lines • ▼ Show 20 Lines | int64_t CWallet::RescanFromTime(int64_t startTime, | ||||
} | } | ||||
if (!start_block.IsNull()) { | if (!start_block.IsNull()) { | ||||
// TODO: this should take into account failure by ScanResult::USER_ABORT | // TODO: this should take into account failure by ScanResult::USER_ABORT | ||||
ScanResult result = ScanForWalletTransactions(start_block, BlockHash(), | ScanResult result = ScanForWalletTransactions(start_block, BlockHash(), | ||||
reserver, update); | reserver, update); | ||||
if (result.status == ScanResult::FAILURE) { | if (result.status == ScanResult::FAILURE) { | ||||
int64_t time_max; | int64_t time_max; | ||||
if (!chain().findBlock(result.failed_block, nullptr /* block */, | if (!chain().findBlock(result.last_failed_block, | ||||
nullptr /* time */, &time_max)) { | nullptr /* block */, nullptr /* time */, | ||||
&time_max)) { | |||||
throw std::logic_error( | throw std::logic_error( | ||||
"ScanForWalletTransactions returned invalid block hash"); | "ScanForWalletTransactions returned invalid block hash"); | ||||
} | } | ||||
return time_max + TIMESTAMP_WINDOW + 1; | return time_max + TIMESTAMP_WINDOW + 1; | ||||
} | } | ||||
} | } | ||||
return startTime; | return startTime; | ||||
} | } | ||||
/** | /** | ||||
* Scan the block chain (starting in start_block) for transactions from or to | * Scan the block chain (starting in start_block) 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] start_block if not null, the scan will start at this block instead | * @param[in] start_block Scan starting block. If block is not on the active | ||||
* of the genesis block | * chain, the scan will return SUCCESS immediately. | ||||
* @param[in] stop_block if not null, the scan will stop at this block instead | * @param[in] stop_block Scan ending block. If block is not on the active | ||||
* of the chain tip | * chain, the scan will continue until it reaches the | ||||
* chain tip. | |||||
* | * | ||||
* @return ScanResult indicating success or failure of the scan. SUCCESS if | * @return ScanResult returning scan information and indicating success or | ||||
* scan was successful. FAILURE if a complete rescan was not possible (due to | * failure. Return status will be set to SUCCESS if scan was | ||||
* pruning or corruption). USER_ABORT if the rescan was aborted before it | * successful. FAILURE if a complete rescan was not possible (due to | ||||
* could complete. | * pruning or corruption). USER_ABORT if the rescan was aborted before | ||||
* it could complete. | |||||
* | * | ||||
* @pre Caller needs to make sure start_block (and the optional stop_block) are | * @pre Caller needs to make sure start_block (and the optional stop_block) 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 BlockHash &start_block, const BlockHash &stop_block, | const BlockHash &start_block, const BlockHash &stop_block, | ||||
const WalletRescanReserver &reserver, bool fUpdate) { | const WalletRescanReserver &reserver, bool fUpdate) { | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | WalletLogPrintf("Rescan started from block %s...\n", | ||||
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.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, fUpdate); | posInBlock, fUpdate); | ||||
} | } | ||||
// scan succeeded, record block as most recent successfully | // scan succeeded, record block as most recent successfully | ||||
// scanned | // scanned | ||||
result.stop_block = block_hash; | result.last_scanned_block = block_hash; | ||||
result.stop_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.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(); | ||||
Show All 19 Lines | WalletLogPrintf("Rescan started from block %s...\n", | ||||
} | } | ||||
} | } | ||||
// Hide progress dialog in GUI. | // Hide progress dialog in GUI. | ||||
ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), | ShowProgress(strprintf("%s " + _("Rescanning..."), 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.value_or(0), 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.value_or(0), progress_current); | *block_height, progress_current); | ||||
result.status = ScanResult::USER_ABORT; | result.status = ScanResult::USER_ABORT; | ||||
} | } | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
void CWallet::ReacceptWalletTransactions() { | void CWallet::ReacceptWalletTransactions() { | ||||
▲ Show 20 Lines • Show All 2,612 Lines • ▼ Show 20 Lines | if (fFirstRun) { | ||||
if (walletInstance->CanGenerateKeys() && | if (walletInstance->CanGenerateKeys() && | ||||
!walletInstance->TopUpKeyPool()) { | !walletInstance->TopUpKeyPool()) { | ||||
chain.initError(_("Unable to generate initial keys")); | chain.initError(_("Unable to generate initial keys")); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
// Temporary. Removed in upcoming lock cleanup | // Temporary. Removed in upcoming lock cleanup | ||||
auto locked_chain = chain.assumeLocked(); | auto locked_chain = chain.assumeLocked(); | ||||
walletInstance->ChainStateFlushed(locked_chain->getLocator()); | walletInstance->ChainStateFlushed(locked_chain->getTipLocator()); | ||||
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) { | } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) { | ||||
// Make it impossible to disable private keys after creation | // Make it impossible to disable private keys after creation | ||||
chain.initError( | chain.initError( | ||||
strprintf(_("Error loading %s: Private keys can only be " | strprintf(_("Error loading %s: Private keys can only be " | ||||
"disabled during creation"), | "disabled during creation"), | ||||
walletFile)); | walletFile)); | ||||
return nullptr; | return nullptr; | ||||
} else if (walletInstance->IsWalletFlagSet( | } else if (walletInstance->IsWalletFlagSet( | ||||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Lines | if (tip_height && *tip_height != rescan_height) { | ||||
.status)) { | .status)) { | ||||
chain.initError( | chain.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(locked_chain->getLocator()); | walletInstance->ChainStateFlushed(locked_chain->getTipLocator()); | ||||
walletInstance->database->IncrementUpdateCounter(); | walletInstance->database->IncrementUpdateCounter(); | ||||
// Restore wallet transaction metadata after -zapwallettxes=1 | // Restore wallet transaction metadata after -zapwallettxes=1 | ||||
if (gArgs.GetBoolArg("-zapwallettxes", false) && | if (gArgs.GetBoolArg("-zapwallettxes", false) && | ||||
gArgs.GetArg("-zapwallettxes", "1") != "2") { | gArgs.GetArg("-zapwallettxes", "1") != "2") { | ||||
WalletBatch batch(*walletInstance->database); | WalletBatch batch(*walletInstance->database); | ||||
for (const CWalletTx &wtxOld : vWtx) { | for (const CWalletTx &wtxOld : vWtx) { | ||||
▲ Show 20 Lines • Show All 188 Lines • Show Last 20 Lines |