doc: update CoinsViewOverlay docstring to describe parallel fetching
What changed, and why it matters
This commit only updates a code comment (docstring) in a header file. It explains how a new parallel coin-fetching mechanism works. No actual code logic was changed, so it cannot introduce or fix a security vulnerability on its own.
No security action needed. Review the new documentation for technical accuracy if desired, but treat as non-security.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff is a documentation-only change to src/coins.h. It replaces the old CCoinsViewOverlay docstring with a detailed description of asynchronous, multi-threaded prevout fetching during ConnectBlock, including memory-ordering semantics and a diagram. No executable code, function signatures, or data structures were modified.
Changed components
src/coins.h (documentation only)Inspect captured patch +54 / −5
diff --git a/src/coins.h b/src/coins.h
index 5528bde0..d1b4e0c8 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -564,13 +564,62 @@ private:
};
/**
- * CCoinsViewCache overlay that avoids populating/mutating parent cache layers on cache misses.
+ * CCoinsViewCache subclass that asynchronously fetches most block input prevouts in parallel during ConnectBlock without
+ * mutating the base cache.
*
- * This is achieved by fetching coins from the base view using PeekCoin() instead of GetCoin(),
- * so intermediate CCoinsViewCache layers are not filled.
+ * Only used in ConnectBlock to pass as an ephemeral view that can be reset if the block is invalid.
+ * It provides the same interface as CCoinsViewCache.
+ * It adds an additional StartFetching method to provide the block.
*
- * Used during ConnectBlock() as an ephemeral, resettable top-level view that is flushed only
- * on success, so invalid blocks don't pollute the underlying cache.
+ * When a block is passed to StartFetching, the inputs of the block are flattened into a vector of InputToFetch
+ * objects. StartFetching then submits worker tasks to a ThreadPool and keeps the returned futures alive until fetching
+ * is stopped.
+ *
+ * ProcessInput() atomically fetches and increments m_input_head, so each thread can only access a single element of the
+ * m_inputs vector at a time. Workers race to claim inputs, so they may fetch elements in any order. If the fetched
+ * index is greater than or equal to the size of m_inputs, no more inputs can be fetched and false is returned.
+ *
+ * The worker claims the InputToFetch at this index, fetches the coin from the base cache and moves it into the
+ * InputToFetch object. The ready flag is then set with a release memory order. This allows the ready flag to be
+ * used as a memory fence, guaranteeing the coin being written to the object will have happened before another
+ * thread tests the flag with an acquire memory order.
+ * This assumes all base->PeekCoin() paths are safe for concurrent readers and do not mutate lower cache layers.
+ *
+ * When a coin is requested from the cache on the main thread and is not already in cacheCoins map, FetchCoinFromBase
+ * checks whether the next unconsumed entry in m_inputs has the requested outpoint. On a match, m_input_tail is advanced
+ * and the entry's ready flag is waited on with an acquire memory order until a worker has finished fetching it. The
+ * coin is then moved out and returned. Since the main thread is the only consumer of validation results, it blocks
+ * on the specific input it needs rather than racing workers for other inputs.
+ *
+ * StopFetching() is called in Flush() and in Reset() (the per-block teardown) so workers stop before the block they
+ * reference goes away. It stops fetching by moving m_input_head to the end of m_inputs (so workers quickly exit),
+ * then waits for all futures to complete and clears the per-block state (m_inputs and the head/tail counters).
+ *
+ * Workers advance m_input_head to fetch inputs. Main thread advances m_input_tail to consume.
+ *
+ * Before workers start:
+ *
+ * m_input_head
+ * m_input_tail
+ * │
+ * ▼
+ * ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
+ * m_inputs: │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │ waiting │
+ * │ │ │ │ │ │ │ │ │ │
+ * └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
+ *
+ * After workers start:
+ *
+ * Worker 2 Worker 0 Worker 3 Worker 1 m_input_head
+ * │ │ │ │ │
+ * ▼ ▼ ▼ ▼ ▼
+ * ┌─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐
+ * m_inputs: │ ready │ ready │fetching │ ready │fetching │fetching │fetching │ waiting │ waiting │
+ * │consumed │ ✓ │ ● │ ✓ │ ● │ ● │ ● │ │ │
+ * └─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘
+ * ▲
+ * │
+ * m_input_tail
*/
class CoinsViewOverlay : public CCoinsViewCache
{
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.