#35716 wallet: Replace mapWallet and wtxOrdered with a boost::multi_index

ReviewabilityReviewsAgreementSize
#35716 achow101 wallet: Replace mapWallet and wtxOrdered with a boost::multi_indexNeeds rebase0 (+1)Strong331 + 36 tests
  • Prevent wallet transaction tracking from desynchronizing across lookups
  • Eliminate lifetime risks from holding raw pointers to stored wallet transactions
  • Ready to review: no blockers or invalidating changes known
  • Strong support for eliminating container sync burdens and raw pointer storage
  • Verified it structurally fixes a transaction reordering bug on master (pablomartin4btc)
  • Concept approval because multi-index is appropriate and scoped to wallet (theuni)
  • Resolved concern regarding modify semantics by switching to extract and insert (theuni)
  • Concept approval for improving wallet transaction naming and structure (rkrux)
  • 331 lines added or modified outside tests
  • 36 lines added or modified in tests
  • 302 lines removed in total
  • 19 files, 4 commits
Wallet#63 of 92
P3 · cleanup
  • P3 because it reduces wallet fragility by consolidating transaction storage into one container
  • Removes raw pointer indirection and eliminates container desynchronization hazards
  • Structurally prevents an issue where transaction reordering missed the ordered view
  • Ranking pass: Moved down: structural fragility reduction with no user-visible payoff, ranked with the other internal refactors.
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

Replace the wallet's separate `mapWallet` and `wtxOrdered` containers with a single `boost::multi_index_container` indexed by txid and insertion order. Update wallet internals, RPC handlers, and tests to access transactions through helper functions or explicit index views rather than direct map manipulation. Mark `CWalletTx::MarkDirty` const so it can be called on elements stored in the multi-index container.

Problem: The wallet tracks transactions both by txid and by insertion order, which previously required maintaining two separate containers where `wtxOrdered` stored raw pointers to `CWalletTx` objects inside `mapWallet`. Keeping two containers in sync and holding raw pointers to container elements is fragile and introduces lifetime risks.

Evidence of importance:

  • Author description: 'These are replaced by a new boost multi index which indexes on txid and insertion order, allowing us to get rid of the 2 separate containers, and holding raw pointers to CWalletTx.'

Scope: Mechanically updates call sites across the wallet and wallet tests to use `GetWalletTx()` or index iterators instead of directly manipulating `mapWallet`. Also links `Boost::headers` to `bitcoin-wallet` in CMake.

Reviewability

Ready · Needs rebase

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

Agreement

Strong

substantive support, no open objection (theuni, pablomartin4btc, rkrux, pablomartin4btc)

Thread notes: Initial assessment of the PR. theuni's requests to use explicit index tags and extract/insert semantics instead of modify are recorded as non-blocking claims and were resolved in a subsequent push.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
theuni (member)objection, approachmodify has complex re-insertion failure semantics and is incompatible with standard container APIsfixed · fix pushed · v1, not yet re-checkedansweredyes2026-07-14: 'please use `extract`/`insert` rather than `modify`. The former is compatible with the std container apis and has familiar (and much simpler) semantics wrt re-insertion failure.'
Status from: 2026-07-20: achow101: 'I've changed all of the `modify` to `extract` then `insert`'

Support:

  • theuni (member) (Concept ACK, 2026-07-14): multi_index seems like the right thing to use here. Since this doesn't leak into consensus/node, I don't see the harm in spreading the dependency to wallet.
  • pablomartin4btc (member) (Concept ACK, 2026-08-10): Replace two containers — mapWallet and wtxOrdered — with a single boost::multi_index_container that owns the CWalletTx objects and provides both lookups natively. Most importantly, eliminates the raw pointer indirection and the synchronisation burden of keeping two containers in sync.
  • rkrux (member) (Concept ACK, 2026-08-26): This also scratches the itch of renaming/removing the variable name mapWallet - it was not an intuitive name and didn't represent what the object contained within it.
  • pablomartin4btc (member) (ACK, 2026-08-26): incidentally fixes a real bug on master: ReorderTransactions() mutates each CWalletTx::nOrderPos in place but never touches wtxOrdered... This PR's multi_index refactor makes that bug structurally impossible, since nOrderPos is the sort key of the ordered index itself — any mutation has to go throug

Participants:

  • theuni (member, support, 1 statements 2026-07-14 to 2026-07-14): Concept ACK; requested explicit index tags and extract/insert semantics
  • pablomartin4btc (member, support, 8 statements 2026-08-09 to 2026-08-26): ACK; verified fix for a latent ordering bug in ReorderTransactions
  • rkrux (member, support, 1 statements 2026-08-26 to 2026-08-26): Concept ACK

Files

76 lines under test/bench/ci.

  • src/wallet/wallet.cpp +208/-180
  • src/wallet/wallet.h +54/-13
  • src/wallet/interfaces.cpp +22/-22
  • src/wallet/test/wallet_tests.cpp +20/-21
  • src/wallet/rpc/transactions.cpp +10/-16
  • src/wallet/feebumper.cpp +6/-6
  • src/wallet/test/group_outputs_tests.cpp +5/-7
  • src/wallet/test/coinselector_tests.cpp +5/-6
  • src/wallet/spend.cpp +5/-5
  • src/wallet/transaction.h +5/-5
  • src/wallet/walletdb.cpp +7/-2
  • src/wallet/receive.cpp +4/-4
  • src/wallet/rpc/coins.cpp +4/-4
  • src/wallet/export.cpp +3/-3
  • src/wallet/test/fuzz/spend.cpp +2/-4
  • src/wallet/test/psbt_wallet_tests.cpp +4/-2
  • src/wallet/rpc/wallet.cpp +1/-1
  • src/wallet/wallettool.cpp +1/-1
  • src/CMakeLists.txt +1/-0

Card

The short text the ranking pass compares across PRs.

This PR replaces the wallet's `mapWallet` and `wtxOrdered` containers with a single `boost::multi_index_container` indexed by txid and order position. Today, the wallet maintains two separate data structures to look up transactions by id and insertion order, requiring raw pointers to `CWalletTx` across containers and manual synchronization. The change simplifies transaction storage and removes pointer management between containers. It is an internal refactor with no stated external dependencies.

Data

dossier JSON · extract JSON · model ledger, generated 2026-09-18T03:37, confidence high, input hash 42122d82ee072b12
thread read through 2026-08-26 (18 statements), head f31dfaeedf
Discussion read under schema 1 rules: suggestions and questions may be missing, and an objection may combine several harms (schema history).
labels: Wallet, Needs rebase

Categories

Wallet

P3 · cleanup (ranking pass: Moved down: structural fragility reduction with no user-visible payoff, ranked with the other internal refactors.)

Replaces two synchronized containers and raw pointer references with a unified boost::multi_index container, eliminating lifetime risks and container desynchronization bugs. As noted in review, this refactor removes raw pointer indirection and structurally fixes a bug where 'ReorderTransactions() mutates each CWalletTx::nOrderPos in place but never touches wtxOrdered'.

Membership: Matches the 'Wallet' area label and modifies core wallet transaction storage across src/wallet/.

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