-
Notifications
You must be signed in to change notification settings - Fork 36.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[wallet] Rescan abortability #10208
[wallet] Rescan abortability #10208
Conversation
31cb886
to
a9fd7c8
Compare
src/wallet/rpcdump.cpp
Outdated
); | ||
|
||
if (!pwallet->fScanningWallet) throw JSONRPCError(RPC_WALLET_ERROR, "No wallet rescans in progress."); | ||
if (pwallet->fAbortRescan) throw JSONRPCError(RPC_WALLET_ERROR, "Rescan abort already in progress."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nits: I don't think it should throw an error. The expected state is correctly reached at the end of the call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a response to the RPC caller, so it's more like feedback and less than an actual error. Compare this to the std::runtime_error thrown for the help message.
Ultimately, if the scan is not in progress and/or if the rescan flag is already set, the end results will be the same even without throwing.
@@ -1558,7 +1560,12 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f | |||
LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex)); | |||
} | |||
} | |||
if (pindex && fAbortRescan) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to set fAbortRescan
to false again.
EDIT: Actually it should be fine... I think it is best that the end state of the variable is known though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's set at line 1530 above. I was thinking of setting it to false at end but it doesn't really matter as it's reset at top anyway.
src/wallet/rpcdump.cpp
Outdated
if (!pwallet->fScanningWallet) throw JSONRPCError(RPC_WALLET_ERROR, "No wallet rescans in progress."); | ||
if (pwallet->fAbortRescan) throw JSONRPCError(RPC_WALLET_ERROR, "Rescan abort already in progress."); | ||
pwallet->fAbortRescan = true; | ||
return "Wallet rescan aborted."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
returning a human readable message feel a bit weird to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was sure I'd seen that elsewhere but now I'm not so sure. Revisiting that part now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the API consumer perspective, what you want is parsable differentiations between the possible states.
Your currently use RPC_WALLET_ERROR
for fScanningWallet
and fAbortRescan
leading to the fact the one needs to parse string to get the correct state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, good point -- I will add error codes for these two and throw those instead.
if (request.fHelp || request.params.size() > 0) | ||
throw std::runtime_error( | ||
"abortrescan\n" | ||
"\nStops current wallet rescan triggered e.g. by an importprivkey call.\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Usually we have the HelpExampleCli
and HelpExampleRpc
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jonasschnelli I wasn't sure that was the case even for no-arg commands. Will add.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.
Nice. Concept ACK. |
Accidentally closed. Reopening. |
a9fd7c8
to
9113eb4
Compare
@jonasschnelli I haven't tried with the GUI. Definitely willing to add that, but wonder if that should be a separate PR? |
Can be separate if this PR does not break the GUI rescan additions (the popup window). |
Gotcha. I will test the GUI. If it doesn't seem overly complex I'll add support there as well while at it. |
@jonasschnelli I tested out the GUI. The only way I could find importing keys was the Help > Debug > Console > importprivkey ... route. It brings up the "Rescanning..." popup with the progress bar, and locks input so I can't abort the rescan to test that part. But the actual GUI works fine. Adding an "Abort" button to the progress popup seems sensible, but I'm going to declare that as a separate PR for now as I don't immediately see a neat solution to doing so. |
@kallewoof You can run bitcoin-qt with the -server flag, and then issue command through bitcoin-cli or any other RPC client. |
@kallewoof: Great. Yes. Let's fix this in an upcoming PR. I think you can also rescan by |
@sipa Ahh that let me try abortrescan from CLI while doing import from the GUI. Thanks! @jonasschnelli GUI fully tested and appears functional. |
fd7f1c1
to
33b93f5
Compare
utACK 33b93f52b4452008075520239f4991440380be1a |
"Wallet is being asked to abort rescan despite already pending rescan abort" I would change "abort" to "abortion"; I believe it may be more grammatically correct, and we need the word abortion in the core code. |
src/wallet/wallet.h
Outdated
@@ -723,6 +723,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface | |||
*/ | |||
mutable CCriticalSection cs_wallet; | |||
|
|||
std::atomic<bool> fAbortRescan; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would turn both these flags to private standard boolean and use CWallet getters&setters to change them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason I didn't think we used getters/setters but clearly we do. Fixed, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish we didn't need this, but we do. Concept ACK.
ACK |
nice! utACK after squash |
0c9af66
to
ae68fa7
Compare
Squashed. ~~~Edit: Crap. Fixing...~~~ |
ae68fa7
to
b0375a8
Compare
b0375a8
to
153d24d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One comment, utACK otherwise.
src/wallet/rpcdump.cpp
Outdated
+ HelpExampleRpc("abortrescan", "") | ||
); | ||
|
||
if (!pwallet->IsScanning()) throw JSONRPCError(RPC_WALLET_NOT_SCANNING, "No wallet rescans in progress."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to agree with the previous comment, throwing here is super strange. The direct API we expose is likely fine, but many API wrappers will throw a corresponding exception like we do here, and I'd consider "not currently scanning" to be a warning, not a critical error - it would be nice to just return a boolean for "we did something".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't find the previous comment you are referring to? (Did you get this and #9622 (comment) mixed up, by any chance?)
Since we're throwing when a user types the word help
, it conceptually feels like a throw is simply a result with a code and a message, rather than a critical error. It's a way to distinguish from "ACK" and "NACK" even for trivial reasons. Compare e.g. the addnode
RPC which throws an error when a node being added is already there, or when a node being removed is not in the list. That feels similarly non-critical to me -- end result is the same -- but could be harder to code for without error codes if we changed to returning a success bool or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was referring to #10208 (comment) The help throw, however, is for when you provide bad arguments, which is the correct "you fucked up" response. Throwing if not scanning is just a race in client applications, an almost-guaranteed-benign race to boot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the worst thing that happens is that you accidentally target the wrong node and one node ends up scanning the entire wallet even though you asked it not to. That's not a biggie, really, especially if you don't even realize it yourself.
I'll switch to returning true/false for did/didn't do something as you suggest.
153d24d
to
9141622
Compare
Per #10208 (comment) I have replaced the RPC throws with true/false for "did something" / "did nothing" return values in |
This still needs (in follow-up PR):
|
postumous utACK |
…nality 896520e [rpc] Add abortrescan command to RPC interface. (kallewoof) ab41ad8 [wallet] Add support for aborting wallet transaction rescans. (furszy) 25440c4 test: wallet_hd.py enable RPC based rescan test case (furszy) d3cdc63 wallet: add rescanblockchain <start_height> <stop_height> RPC command. (furszy) 4d0fa79 wallet: ScanForWalletTransactions returning the last unsuccessfully scanned block or nullptr if scan went well. (furszy) Pull request description: Added the following changes: 1) The wallet scan chain for transactions process will now return null if scan was successful. Otherwise, if a complete rescan was not possible (due to corruption or abort), returns pointer to the most recent block that could not be scanned. 2) New `rescanblockchain` RPC command with two arguments `start_height` `end_height` to trigger a chain rescan at any time during runtime + test case (adaptation of bitcoin#7061). 3) New `abortrescan` RPC command to stop any long running rescan if needed at runtime (this is helpful for example in case of importing a private/sapling key that if the user is not aware of the extra "scan" boolean argument, it will rescan the complete chain). Coming from bitcoin#10208. ACKs for top commit: random-zebra: ACK 896520e Fuzzbawls: ACK 896520e Tree-SHA512: ae7f3a7122d9d140f840154d1cfa703e2ed4d90f37b308da3765cb5bc4760229c26b8a49e835bae056f82f789d7b3b9b0d47859f74222db8d41005c748b51f61
The wallet
importprivkey
command triggers a rescan of the entire block chain unless explicitly asked not to. This oftentimes is not intentional, and there has so far not existed a way to abort a rescan in progress.This PR adds support for a new RPC command
abortrescan
which will promptScanForWalletTransactions
to stop scanning.