Skip to content

Conversation

@andrewtoth
Copy link
Contributor

@andrewtoth andrewtoth commented Dec 28, 2025

This is the first commit of #31132, which can be merged as an independent change. It has a small benefit on its own, but will help in moving the parent PR forward.

Add a Reset() method to CCoinsViewCache that clears cacheCoins, cachedCoinsUsage, and hashBlock without flushing to the base view. This allows efficiently reusing a cache instance across multiple blocks.

Introduce CoinsViewCacheController to wrap a CCoinsViewCache and provide scoped access through a Handle. The Handle dereferences to the cache and automatically calls Reset() on destruction. This RAII pattern ensures the cache is always properly reset between blocks.

Add m_connect_block_controller as a persistent controller for ConnectBlock, avoiding repeated memory allocations.

@DrahtBot
Copy link
Contributor

DrahtBot commented Dec 28, 2025

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage & Benchmarks

For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/34164.

Reviews

See the guideline for information on the review process.

Type Reviewers
Stale ACK l0rinc, bensig

If your review is incorrectly listed, please copy-paste <!--meta-tag:bot-skip--> into the comment that the bot should ignore.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #34165 (coins: don't mutate main cache when connecting block by andrewtoth)
  • #34132 (refactor: inline CCoinsViewErrorCatcher into CCoinsViewDB by l0rinc)
  • #32317 (kernel: Separate UTXO set access from validation functions by sedited)
  • #31132 (validation: fetch block inputs on parallel threads 3x faster IBD by andrewtoth)

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.

Copy link
Contributor

@l0rinc l0rinc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK, carving this out is a small step in speedup up IBD and simplifying the review for the heavier #31132

I want to make sure we make the code safer than before, so I'm suggesting we cleanup up the spread-around state changes a bit since it's hard to reason about it otherwise - especially trying to imagine a multi-threaded context where lazy inits and resets and direct setters and field accesses are potentially competing.

Copy link
Contributor

@l0rinc l0rinc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redid the change locally, ended up with slightly different setup, but your solution might handle the lifecycle slightly better.
I ran a reindex-chainstate benchmark, the difference is within noise 👍.
Left some comments, but I'm fine with merging as is:
ACK b46b61b

{
AssertLockHeld(::cs_main);
m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview);
m_connect_block_view = std::make_unique<CCoinsViewCache>(&*m_cacheview);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed ConnectTip() always uses m_coins_views->m_connect_block_view instead of storing a m_connect_block_view member on Chainstate (initialized in Chainstate::InitCoinsCache()).

Is the intent to keep the connect-block cache’s lifetime tightly coupled to m_coins_views/m_cacheview (since CCoinsViewCache holds a raw backend pointer), so we don’t need to re-point/reset it when coins views are reset?

Maybe we have to rethink the lifetime bound of the backing cache pointer...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the intent to keep the connect-block cache’s lifetime tightly coupled to m_coins_views/m_cacheview (since CCoinsViewCache holds a raw backend pointer), so we don’t need to re-point/reset it when coins views are reset?

Yes. It is also declared after m_cacheview so will be destroyed before the backing pointer.

Maybe we have to rethink the lifetime bound of the backing cache pointer...

We could bound it with an annotation, but anything calling SetBackend would negate it and also update the bounds to the new view passed in.
I think to be correct we would want a shared_ptr as the base. But, I think that type of change is out of scope for this PR.

@bensig
Copy link
Contributor

bensig commented Jan 5, 2026

ACK b46b61b

Built and tested on macOS. Clean implementation - Reset() method is straightforward, tests cover it well, and the m_connect_block_view integration in ConnectTip() correctly calls Reset() on both failure and success paths.

@l0rinc l0rinc mentioned this pull request Jan 14, 2026
23 tasks
@andrewtoth
Copy link
Contributor Author

I updated this to have the ChainState own a controller instead of the actual CCoinsViewCache. The controller owns a private CCoinsViewCache, and returns a handle to it via a Start method. The handle dereferences to the CCoinsViewCache, and automatically calls Reset when the handle goes out of scope.

andrewtoth and others added 2 commits January 15, 2026 18:05
Add a Reset() method to CCoinsViewCache that clears cacheCoins,
cachedCoinsUsage, and hashBlock without flushing to the base view.
This allows efficiently reusing a cache instance across multiple blocks.

Introduce CoinsViewCacheController to wrap a CCoinsViewCache and provide
scoped access through a Handle. The Handle dereferences to the cache and
automatically calls Reset() on destruction. This RAII pattern ensures the
cache is always properly reset between blocks.

Add m_connect_block_controller as a persistent controller for ConnectBlock,
avoiding repeated memory allocations.

Co-authored-by: l0rinc <[email protected]>
More accurately reflects the purpose of the parameter, since
we will keep reusing the cache but don't want to reallocate it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants