Merge #11200: Allow for aborting rescans in the GUI

ae1d2b030 Give an error when rescan is aborted by the user (Andrew Chow)
69b01e6f8 Add cancel button to rescan progress dialog (Andrew Chow)

Pull request description:

  A cancel button is added to the `showProgress` dialog that is used only for rescans. When clicked, `AbortRescan` is called directly to cancel the rescan.

  Rescans triggered from the debug console will now be cancelable by clicking the cancel button.

  Rescans triggered by a command (e.g. `importmulti`) will now give an error indicating that the rescan was aborted by the user (either by the `abortrescan` command or by clicking cancel).

Tree-SHA512: 4bb14998766de686e2318fbc9805758eccf5dbe628a7257d072c9ae2fb4f61303a0876f49988d6e5eddb261969b8a307c81c0c2df0a42ae909a43d738af3dc1b
This commit is contained in:
Jonas Schnelli 2018-04-13 20:51:51 +02:00
commit 5f2a39946f
No known key found for this signature in database
GPG key ID: 1EB776BB03C7922D
4 changed files with 49 additions and 10 deletions

View file

@ -130,6 +130,7 @@ public:
{ {
return m_wallet.ChangeWalletPassphrase(old_wallet_passphrase, new_wallet_passphrase); 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); } bool backupWallet(const std::string& filename) override { return m_wallet.BackupWallet(filename); }
std::string getWalletName() override { return m_wallet.GetName(); } std::string getWalletName() override { return m_wallet.GetName(); }
bool getKeyFromPool(bool internal, CPubKey& pub_key) override bool getKeyFromPool(bool internal, CPubKey& pub_key) override

View file

@ -65,6 +65,9 @@ public:
virtual bool changeWalletPassphrase(const SecureString& old_wallet_passphrase, virtual bool changeWalletPassphrase(const SecureString& old_wallet_passphrase,
const SecureString& new_wallet_passphrase) = 0; const SecureString& new_wallet_passphrase) = 0;
//! Abort a rescan.
virtual void abortRescan() = 0;
//! Back up wallet. //! Back up wallet.
virtual bool backupWallet(const std::string& filename) = 0; virtual bool backupWallet(const std::string& filename) = 0;

View file

@ -315,9 +315,9 @@ void WalletView::showProgress(const QString &title, int nProgress)
progressDialog = new QProgressDialog(title, "", 0, 100); progressDialog = new QProgressDialog(title, "", 0, 100);
progressDialog->setWindowModality(Qt::ApplicationModal); progressDialog->setWindowModality(Qt::ApplicationModal);
progressDialog->setMinimumDuration(0); progressDialog->setMinimumDuration(0);
progressDialog->setCancelButton(0);
progressDialog->setAutoClose(false); progressDialog->setAutoClose(false);
progressDialog->setValue(0); progressDialog->setValue(0);
progressDialog->setCancelButtonText(tr("Cancel"));
} }
else if (nProgress == 100) else if (nProgress == 100)
{ {
@ -327,9 +327,14 @@ void WalletView::showProgress(const QString &title, int nProgress)
progressDialog->deleteLater(); progressDialog->deleteLater();
} }
} }
else if (progressDialog) else if (progressDialog) {
if (progressDialog->wasCanceled()) {
getWalletModel()->wallet().abortRescan();
} else {
progressDialog->setValue(nProgress); progressDialog->setValue(nProgress);
} }
}
}
void WalletView::requestedSyncWarningInfo() void WalletView::requestedSyncWarningInfo()
{ {

View file

@ -172,7 +172,13 @@ UniValue importprivkey(const JSONRPCRequest& request)
} }
} }
if (fRescan) { 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; return NullUniValue;
@ -310,7 +316,13 @@ UniValue importaddress(const JSONRPCRequest& request)
} }
if (fRescan) 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(); pwallet->ReacceptWalletTransactions();
} }
@ -479,7 +491,13 @@ UniValue importpubkey(const JSONRPCRequest& request)
} }
if (fRescan) 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(); pwallet->ReacceptWalletTransactions();
} }
@ -534,9 +552,11 @@ UniValue importwallet(const JSONRPCRequest& request)
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg()); int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
file.seekg(0, file.beg); file.seekg(0, file.beg);
pwallet->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI // 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 shoing the import progress. uiInterface.ShowProgress does not have a cancel button.
uiInterface.ShowProgress(_("Importing..."), 0, false); // show progress dialog in GUI
while (file.good()) { 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::string line;
std::getline(file, line); std::getline(file, line);
if (line.empty() || line[0] == '#') if (line.empty() || line[0] == '#')
@ -599,10 +619,17 @@ UniValue importwallet(const JSONRPCRequest& request)
} }
} }
file.close(); file.close();
pwallet->ShowProgress("", 100); // hide progress dialog in GUI uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI
pwallet->UpdateTimeFirstKey(nTimeBegin); pwallet->UpdateTimeFirstKey(nTimeBegin);
} }
pwallet->RescanFromTime(nTimeBegin, reserver, false /* update */); uiInterface.ShowProgress("", 100, false); // hide progress dialog in GUI
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(); pwallet->MarkDirty();
if (!fGood) if (!fGood)
@ -1212,6 +1239,9 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, true /* update */); int64_t scannedTime = pwallet->RescanFromTime(nLowestTimestamp, reserver, true /* update */);
pwallet->ReacceptWalletTransactions(); pwallet->ReacceptWalletTransactions();
if (pwallet->IsAbortingRescan()) {
throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted by user.");
}
if (scannedTime > nLowestTimestamp) { if (scannedTime > nLowestTimestamp) {
std::vector<UniValue> results = response.getValues(); std::vector<UniValue> results = response.getValues();
response.clear(); response.clear();