The error messages should never happen in normal operation. However, if they do, they are helpful to return to the user to debug the issue. For example, to notice a truncated file.
This fixes #28621
Also includes a minor refactor commit.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
For detailed information about the code coverage, see the test coverage report.
See the guideline for information on the review process.
Type | Reviewers |
---|---|
ACK | ryanofsky, fjahr |
Concept ACK | Sjors |
Stale ACK | danielabrozzoni |
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
🚧 At least one of the CI tasks failed. Debug: https://github.com/bitcoin/bitcoin/runs/27742334614
Make sure to run all tests locally, according to the documentation.
The failure may happen due to a number of reasons, for example:
Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.
A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.
An intermittent issue.
Leave a comment here, if you need help tracking down a confusing failure.
Concept ACK
I think the title is a bit confusing here. It sounds like the error message content changes but they are just moved from logs to RPC. I think the title of the the issue that is fixed is a better description.
I think the title is a bit confusing here. It sounds like the error message content changes but they are just moved from logs to RPC. I think the title of the the issue that is fixed is a better description.
Good point, fixed!
The message is not exposed in the GUI or another translated context, so
translating it is useless for now.
Also, fix a nit from https://github.com/bitcoin/bitcoin/pull/30395#discussion_r1670972864
git range-diff bitcoin-core/master fa5c253b4e fa91404c68
5908@@ -5915,7 +5909,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
5909 // means <5MB of memory imprecision.
5910 if (coins_processed % 120000 == 0) {
5911 if (m_interrupt) {
5912- return false;
5913+ return util::Error{};
In commit “rpc: Return precise loadtxoutset error messages” (fa91404c68b4d503e6568f49aaf74a5746887185)
This is ok, but IMO it would be better to change result type from Result<void>
to Result<InterruptResult>
and return Interrupted{}
here. If a function exits early because the user requested a shutdown, it may or may not be an error, and bubbling up InterruptResult
lets the top level caller decide what to do based on context.
For example, in this case because the call is being made by RPC it would probably be good for the RPC call to return an “Snapshot loading was aborted” error. But in the GUI case, if a user tries to load snapshot and then shuts down before it is loaded, it would probably be better to just shut down cleanly and maybe log something, than try to present an error message.
In either case, returning something like return util::Error{Untranslated("Processing snapshot aborted")}
or return Interrupted{}
would be better than returning an error with no message.
it would probably be better to just shut down cleanly and maybe log something, than try to present an error message.
An alternative may be to ask Really shutdown and discard the loadutxoset progress? [Cancel] [Shutdown]
.
But the GUI design can be done later, so I’ll just clarify the error message here for the RPC.
An alternative may be to ask
Really shutdown and discard the loadutxoset progress? [Cancel] [Shutdown]
.
Yes exactly, that is the point of returning Interrupted status, because there are many ways caller may want to handle an interruption, and it should be up to the caller to decide. The behavior shouldn’t be hardcoded into the function that was interrupted.
But the GUI design can be done later, so I’ll just clarify the error message here for the RPC.
That would be better than current version, but I wonder why you don’t want to return interrupted status to make intent of the code clear and avoid needing to revisit this and change it later?
An alternative may be to ask
Really shutdown and discard the loadutxoset progress? [Cancel] [Shutdown]
.Yes exactly, that is the point of returning Interrupted status, because there are many ways caller may want to handle an interruption, and it should be up to the caller to decide. The behavior shouldn’t be hardcoded into the function that was interrupted.
Your suggestion doesn’t allow my suggestion. They are completely separate, because one is about cancelling the shutdown, before it happens, and the other is about returning a shutdown happened in loadtxoutset (after it happened).
I wonder why you don’t want to return interrupted status to make intent of the code clear and avoid needing to revisit this and change it later?
I think the intent of the code is fully clear with return util::Error{Untranslated("Aborting after an interrupt was requested")};
(If not, happy to push an alternative)
In any case, I think Result<InterruptResult>
would be wrong and would have to be revisited later on anyway:
void
. I’ve shared a diff in #30516 (review) to make the inner result non-void. However, I don’t want to block or wait this pull on other stuff.Overall I think it is not clear (at least to me) that Result<InterruptResult>
is the way to go. Given the uncertainty it seems better to hold back on it for now. But that may just be me.
re: #30497 (review)
Overall I think it is not clear (at least to me) that
Result<InterruptResult>
is the way to go. Given the uncertainty it seems better to hold back on it for now. But that may just be me.
Great, thanks for explaining. You may want to add feedback on #29700 which makes extensive use of InterruptResult.
I think Result would be wrong
It sounds like maybe you would want to this to Result<void, InterruptResult>
instead of Result<InterruptResult, void>
. I think that would be reasonable and could have advantages. I didn’t opt for that approach because return Interrupted{}
is shorter and seems more appropriate than return {Error{}, Interrupted{}}
, because I wouldn’t consider a successful interruption to be an error. But maybe it makes sense to support a util::Result constructor for failures that are not necessarily errors and allow return Interrupted{}
syntax for Result<void, InterruptResult>
types. I could experiment with that.
Your suggestion doesn’t allow my suggestion. They are completely separate, because one is about cancelling the shutdown, before it happens, and the other is about returning a shutdown happened in loadtxoutset (after it happened).
Forgot to respond to this part. We would still want to return Interrupted in this case. To implement your suggestion the GUI would make an asynchronous ActivateSnapshot call when the user loaded a snapshot file, and show the [Cancel] [Shutdown]
dialog if there was an attempt to shut down while the call was progress. The question is just what should ActivateSnapshot return after the user clicked [Shutdown], and Interupted{}
makes more than util::Error{Untranslated("Aborting after an interrupt was requested")}
to avoid triggering an error log or dialog when no error happened and the software did exactly what the user requested.
5971@@ -5980,18 +5972,16 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
5972 maybe_stats = ComputeUTXOStats(
5973 CoinStatsHashType::HASH_SERIALIZED, snapshot_coinsdb, m_blockman, [&interrupt = m_interrupt] { SnapshotUTXOHashBreakpoint(interrupt); });
5974 } catch (StopHashingException const&) {
5975- return false;
5976+ return util::Error{};
In commit “rpc: Return precise loadtxoutset error messages” (fa91404c68b4d503e6568f49aaf74a5746887185)
Same comment about InterruptResult
here
5854@@ -5857,8 +5855,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
5855 // ActivateSnapshot(), but is done so that we avoid doing the long work of staging
5856 // a snapshot that isn't actually usable.
5857 if (WITH_LOCK(::cs_main, return !CBlockIndexWorkComparator()(ActiveTip(), snapshot_start_block))) {
5858- LogPrintf("[snapshot] activation failed - work does not exceed active chainstate\n");
5859- return false;
5860+ return util::Error{Untranslated("Activation failed - work does not exceed active chainstate")};
In commit “rpc: Return precise loadtxoutset error messages” (fa91404c68b4d503e6568f49aaf74a5746887185)
The error message seems inconsistent with other ones because it is prefixed with “Activation failed -”. Maybe drop that prefix or also include it in the other messages?
The error messages should never happen in normal operation. However, if
they do, they are helpful to return to the user to debug the issue. For
example, to notice a truncated file.
rfm, or does it need more review?
Looks good to me. I’d tend to wait for 3 current acks on a change to validation.cpp, but in this case there are two current acks and only string changes since that last stale ack so this seem close enough. Will merge soon.