validation: merge PeekCoin into GetCoin#35078
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please copy-paste ConflictsReviewers, 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. |
The `coinsviewoverlay_tests` post-`Flush()` checks only verify that the spent state reached `main_cache`. A plain `GetCoin()` miss does not populate the cache, so `PeekCoin()` does not provide extra coverage there. Use `GetCoin()` now to keep the later `PeekCoin` removal focused on the call sites that still need side-effect-free reads.
b755269 to
c45d698
Compare
|
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
The `CCoinsView` hierarchy currently exposes peeking through a separate virtual method. Add a `peek_only` parameter to `GetCoin()` declarations and overrides so a later commit can route peeking and fetching through one interface. This commit does not change lookup behavior yet. Co-authored-by: Anthony Towns <aj@erisian.com.au>
Review on bitcoin#34124 made it clear that `PeekCoin()` is hard to distinguish from `GetCoin()` at call sites where caching does not matter. Now that `GetCoin()` already accepts a `peek_only` parameter, remove `PeekCoin()` and let callers request the non-caching path directly through `GetCoin(..., true)`. `CCoinsViewCache` keeps the existing non-caching lookup behavior for `peek_only=true`, and `CoinsViewOverlay` continues to avoid populating parent caches by forwarding `true` to its base view. Fuzz call sites where the caching behavior is irrelevant now randomize `peek_only` via `ConsumeBool()` for broader coverage. This simplification was suggested by: * Rus Yanofsky in bitcoin#34165 (review) * Anthony Towns in bitcoin#34124 (comment) Co-authored-by: ryanofsky <ryan@ofsky.org> Co-authored-by: Anthony Towns <aj@erisian.com.au>
c45d698 to
8892881
Compare
|
This is known as a Boolean Trap. Many design guidelines forbid the use of boolean parameters and instead recommend having separate functions. This PR seems to go into the opposite direction. |
|
@purpleKarrot, I agree, it's an anti-pattern, it's why we avoided it originally, but in this case the end-result is easier to work with and several reviewers mentioned they would prefer it. |
|
Maybe a Non-Virtual Interface? You could make the virtual function |
Yeah, my original suggestion (642fa06 #34165 (comment)) was to make GetCoin PeekCoin and HaveCoin nonvirtual and implement them in terms of virtual hooks for subclasses. I also gave further suggestions there for enforcing GetCoin/PeekCoin distinction at compile time with const, but these would require separating the coin lookup interface from the coin writing interface. In any case 8892881 seems like an improvement over status quo. IMO the booleans are not a significant problem, and could also be avoided with minimal changes by passing enum class values like CacheUpdate::Yes CacheUpdate::No. So concept ACK for 8892881 or anything similar. (Would maybe just clarify the citation in the description since I did suggest a different approach.) |
Thanks for the reminder, I have updated the PR description, please let me know if it reflects your opinion accurately.
I rechecked your approach; splitting the reader and writer is something I would like to move toward. One of the goals of these cleanups was segregating the interface. Do you think this current PR gets us closer there? It makes a few other coins refactors simpler (noticed while rebasing them). |
Yes I think current PR is a basically a strict improvement. I just wanted to mention some other possible alternatives and goals. The only possible downside I see of current PR is that if you combine caching and noncaching lookups into one method it may require a few extra call sites to be updated later if separate const and non-const lookup methods are added. But this does not seem like a big deal since there is no const protection for the cache now. I guess I have a pretty clear idea of how I would design this API differently but many approaches seem reasonable here. I do plan to review this too soon. |
Problem
Review on #34124 made it clear that the new
PeekCoinmethod is hard to distinguish from the existingGetCoinat call sites where caching does not matter.Fix
Merge
PeekCoinintoGetCoinby adding apeek_onlyflag to theCCoinsViewinterface and removing the separate virtual method.This preserves the non-caching lookup behavior in
CCoinsViewCacheandCoinsViewOverlay, while allowing backends without caches to ignore the flag.Details
Tests and fuzz scaffolding now call
GetCoin(..., true)only where side-effect-free reads matter, andCCoinsViewCachenow shares the common result handling between peeking and caching lookups.The post-
Flush()overlay assertions use plainGetCoin()because they only check the flushed spentness and do not need to preserve parent cache state.Context
The unclear boundary between
PeekCoinandGetCoinwas flagged during review by:GetCoin,PeekCoin, andHaveCoinnon-virtual public methods implemented on top of two simpler virtual hooks (LookupCoinandMutableLookupCoin), so subclasses couldn't accidentally violate the caching contract. Russ noted that a fuller solution would enforce the distinction at compile time withconst, which would in turn require splitting the coin lookup interface from the coin writing interface (droppingBatchWritefrom the "view" side into a separate "store" interface).CCoinsViewa pure virtual interface #34124 (comment), who sketched out the single-methodGetCoin(outpoint, peek_only)shape this PR takes (see ajtowns@bff5874).This change is forward-compatible with validation: fetch block inputs on parallel threads #31132 as well.