diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -71,6 +71,9 @@ changeWalletPassphrase(const SecureString &old_wallet_passphrase, const SecureString &new_wallet_passphrase) = 0; + //! Abort a rescan. + virtual void abortRescan() = 0; + //! Back up wallet. virtual bool backupWallet(const std::string &filename) = 0; diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -131,6 +131,7 @@ return m_wallet.ChangeWalletPassphrase(old_wallet_passphrase, new_wallet_passphrase); } + void abortRescan() override { m_wallet.AbortRescan(); } bool backupWallet(const std::string &filename) override { return m_wallet.BackupWallet(filename); } diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -354,16 +354,20 @@ progressDialog = new QProgressDialog(title, "", 0, 100); progressDialog->setWindowModality(Qt::ApplicationModal); progressDialog->setMinimumDuration(0); - progressDialog->setCancelButton(0); progressDialog->setAutoClose(false); progressDialog->setValue(0); + progressDialog->setCancelButtonText(tr("Cancel")); } else if (nProgress == 100) { if (progressDialog) { progressDialog->close(); progressDialog->deleteLater(); } } else if (progressDialog) { - progressDialog->setValue(nProgress); + if (progressDialog->wasCanceled()) { + getWalletModel()->wallet().abortRescan(); + } else { + progressDialog->setValue(nProgress); + } } } diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -191,7 +191,16 @@ } } if (fRescan) { - pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */); + int64_t scanned_time = + pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */); + if (pwallet->IsAbortingRescan()) { + throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user."); + } + if (scanned_time > TIMESTAMP_MIN) { + throw JSONRPCError(RPC_WALLET_ERROR, + "Rescan was unable to fully rescan the " + "blockchain. Some transactions may be missing."); + } } return NullUniValue; @@ -358,7 +367,16 @@ } } if (fRescan) { - pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */); + int64_t scanned_time = + pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */); + if (pwallet->IsAbortingRescan()) { + throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user."); + } + if (scanned_time > TIMESTAMP_MIN) { + throw JSONRPCError(RPC_WALLET_ERROR, + "Rescan was unable to fully rescan the " + "blockchain. Some transactions may be missing."); + } pwallet->ReacceptWalletTransactions(); } @@ -570,7 +588,16 @@ pwallet->LearnAllRelatedScripts(pubKey); } if (fRescan) { - pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */); + int64_t scanned_time = + pwallet->RescanFromTime(TIMESTAMP_MIN, reserver, true /* update */); + if (pwallet->IsAbortingRescan()) { + throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user."); + } + if (scanned_time > TIMESTAMP_MIN) { + throw JSONRPCError(RPC_WALLET_ERROR, + "Rescan was unable to fully rescan the " + "blockchain. Some transactions may be missing."); + } pwallet->ReacceptWalletTransactions(); } @@ -629,13 +656,20 @@ int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg()); file.seekg(0, file.beg); + // Use uiInterface.ShowProgress instead of pwallet.ShowProgress because + // pwallet.ShowProgress has a cancel button tied to AbortRescan which we + // don't want for this progress bar showing the import progress. + // uiInterface.ShowProgress does not have a cancel button. + // show progress dialog in GUI - pwallet->ShowProgress(_("Importing..."), 0); + uiInterface.ShowProgress(_("Importing..."), 0, false); while (file.good()) { - pwallet->ShowProgress( - "", std::max(1, std::min(99, (int)(((double)file.tellg() / - (double)nFilesize) * - 100)))); + uiInterface.ShowProgress( + "", + std::max(1, std::min(99, (int)(((double)file.tellg() / + (double)nFilesize) * + 100))), + false); std::string line; std::getline(file, line); if (line.empty() || line[0] == '#') { @@ -711,10 +745,21 @@ file.close(); // hide progress dialog in GUI - pwallet->ShowProgress("", 100); + uiInterface.ShowProgress("", 100, false); pwallet->UpdateTimeFirstKey(nTimeBegin); } - pwallet->RescanFromTime(nTimeBegin, reserver, false /* update */); + // hide progress dialog in GUI + uiInterface.ShowProgress("", 100, false); + int64_t scanned_time = + pwallet->RescanFromTime(nTimeBegin, reserver, false /* update */); + if (pwallet->IsAbortingRescan()) { + throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user."); + } + if (scanned_time > nTimeBegin) { + throw JSONRPCError(RPC_WALLET_ERROR, + "Rescan was unable to fully rescan the blockchain. " + "Some transactions may be missing."); + } pwallet->MarkDirty(); if (!fGood) { @@ -1412,6 +1457,9 @@ nLowestTimestamp, reserver, true /* update */); pwallet->ReacceptWalletTransactions(); + if (pwallet->IsAbortingRescan()) { + throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user."); + } if (scannedTime > nLowestTimestamp) { std::vector results = response.getValues(); response.clear();