#35474 node: move index ownership to NodeContext

ReviewabilityReviewsAgreementSize
#35474 w0xlt node: move index ownership to NodeContextNeeds rebase0Positive233 + 24 tests
  • Move secondary index ownership from process-global static variables into individual node contexts
  • Improve node encapsulation and make running multiple nodes in tests or multiprocess setups easier
  • Ready for review
  • Concept approval without stated reasons (sedited, fjahr)
  • Question about interaction with chain sync changes answered by author (Sjors)
  • Suggestion to use standard unique pointers answered by explaining circular header dependencies (fjahr)
  • 233 lines added or modified outside tests
  • 24 lines added or modified in tests
  • 175 lines removed in total
  • 27 files, 6 commits
Indexes#9 of 11
P3 · cleanup
  • P3 because it is an internal architectural cleanup rather than a fix for data integrity or performance
  • Eliminating process-wide global index state unblocks cleaner testing with multiple node instances
Reviewability: ReadyStalePaused
Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets
Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs.
Size: lines added or modified outside tests, then in tests; greener = smaller.

Goal

Moves process-global secondary index instances (`g_txindex`, `g_txospenderindex`, `g_coin_stats_index`, and block filter indexes) into `NodeContext`. Custom deleters are defined in a new `node/indexes.{h,cpp}` module to break circular header dependencies between `node/context.h` and index definitions. RPC, REST, and net processing callers now receive index pointers via `NodeContext` or an injected callback in `PeerManager::Options`.

Problem: Secondary indexes are owned by process-wide static global pointers and maps instead of node instances. This breaks node encapsulation, complicates running multiple node contexts in tests or multiprocess setups, and forces networking and RPC code to reach directly into global state.

Evidence of importance:

  • PR description: "This removes the remaining process-global index ownership and stores node-owned indexes in NodeContext instead."
  • Commit bdaf67c2c8: "Index types are destroyed through deleters defined in node/indexes.cpp because including index headers in node/context.cpp would create circular dependencies"

Scope: Adds custom deleters for index unique_ptrs in NodeContext to avoid circular header dependencies. The key order of returned indexes in the `getindexinfo` RPC changes slightly to follow startup registration order.

Risk of a mistake: medium (rpc_api, p2p). Incorrect shutdown order or destructor lifetime bugs between NodeContext indexes and validation signals could cause crashes or use-after-free errors when closing the node.

Reviewability

Ready · Needs rebase

Conflicts with master; review the logic now, the rebase is mechanical.

Waiting on (from the thread read):

  • reviewer: fjahr to review author's reply regarding circular dependencies and custom deleters 2026-09-30
  • reviewer: fjahr to review author's reply explaining circular dependencies with custom deleters 2026-09-30

Agreement

Positive

support without stated reasons, no open objection (sedited, fjahr)

Thread notes: Added Sjors's question regarding interaction with #24230 (answered by author). Updated fjahr's suggestion regarding custom deleters to answered after author explained circular dependency constraints. / Added Sjors' question regarding interaction with #24230, which the author answered. Updated fjahr's suggestion status to answered after the author explained the circular dependencies preventing plain unique_ptrs.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
Sjors (member)question, approachHow does this interact with #24230?answered · author explained that PR 24230 still keeps process-global ownership and the changes are orthogonalansweredyes2026-06-17: 'How does this interact with #24230?'
Status from: 2026-06-17: w0xlt: 'So this PR is mostly orthogonal to it: #24230 changes how indexes sync with the chain and removes index dependencies on node internals, while this PR moves index ownership into NodeContext.'
fjahr (member)suggestion, maintenanceuse plain std::unique_ptr instead of custom deleters by including index headers in node/context.cppanswered · author explained that including index headers in node/context.cpp introduces circular dependencies with index/base.cppansweredyes2026-09-26: 'Are the custom deleters really needed? NodeContext already handles this for its other unique_ptr members via the destructor here'
Status from: 2026-09-30: w0xlt: 'Plain unique_ptrs would compile, but index/base.cpp includes node/context.h, so including the index headers in node/context.cpp introduces new circular dependencies'

Support:

  • sedited (member) (Concept ACK, 2026-06-06): Concept ACK [not substantive]
  • fjahr (member) (Concept ACK, 2026-06-21): Concept ACK [not substantive]

Participants:

  • sedited (member, support, 2 statements 2026-06-06 to 2026-08-17): Concept ACK; pinged for rebase
  • Sjors (member, question, 1 statements 2026-06-17 to 2026-06-17): asked how this PR interacts with #24230
  • fjahr (member, support, 2 statements 2026-06-21 to 2026-09-26): Concept ACK; suggested plain std::unique_ptr instead of custom deleters

Files

41 lines under test/bench/ci.

  • src/node/indexes.cpp +65/-0
  • src/node/indexes.h +51/-0
  • src/index/blockfilterindex.cpp +0/-35
  • src/init.cpp +20/-13
  • src/rpc/blockchain.cpp +19/-14
  • src/index/blockfilterindex.h +0/-27
  • src/node/context.h +26/-1
  • src/test/blockfilter_index_tests.cpp +12/-11
  • src/rpc/node.cpp +3/-18
  • src/rest.cpp +12/-7
  • src/rpc/mempool.cpp +6/-8
  • src/rpc/rawtransaction.cpp +7/-7
  • src/wallet/test/wallet_tests.cpp +7/-6
  • src/rpc/txoutproof.cpp +7/-4
  • src/node/transaction.cpp +3/-3
  • src/node/transaction.h +4/-2
  • src/net_processing.h +5/-0
  • src/node/interfaces.cpp +3/-2
  • src/test/util/setup_common.cpp +5/-0
  • src/index/txospenderindex.h +0/-4
  • src/index/coinstatsindex.h +0/-3
  • src/index/txindex.h +0/-3
  • src/index/coinstatsindex.cpp +0/-2
  • src/index/txindex.cpp +0/-2
  • src/index/txospenderindex.cpp +0/-2
  • src/net_processing.cpp +1/-1
  • src/CMakeLists.txt +1/-0

Card

The short text the ranking pass compares across PRs.

This pull request transfers ownership of txindex, txospenderindex, coinstatsindex, and block filter indexes from process-wide globals into NodeContext. Secondary indexes previously relied on static global variables, preventing clean node encapsulation and complicating multi-node testing or multiprocess isolation. Networking, RPC, and REST callers now access indexes via NodeContext or a PeerManager callback. The change is refactoring with no external behavior changes aside from key ordering in getindexinfo.

Data

dossier JSON · extract JSON · model ledger, generated 2026-10-02T01:22, confidence high, input hash 3d5dff160b4ce87a
thread read through 2026-09-30 (10 statements), head fc948ca8e4
labels: Refactoring, UTXO Db and Indexes, Needs rebase

Categories

Indexes

P3 · cleanup

Moves index ownership out of process-wide static globals and into NodeContext, improving encapsulation and easing testing with multiple node instances. While this is primarily an architectural refactor rather than a data integrity or performance improvement, eliminating global index state provides clear architectural value.

Membership: Touches src/index/ headers and implementations to eliminate process-global secondary index instances (g_txindex, g_txospenderindex, etc.) and transition ownership to NodeContext.

Factors: security/stability 0, bug 0, performance 0, user value 0, leverage 1