{
 "number": 35716,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35716",
 "title": "wallet: Replace mapWallet and wtxOrdered with a boost::multi_index",
 "author": "achow101",
 "author_association": "MEMBER",
 "created_at": "2026-07-14T00:33:37Z",
 "updated_at": "2026-09-16T21:09:15Z",
 "age_days": 65,
 "draft": false,
 "labels": [
  "Wallet"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "f31dfaeedf99d12ab2fce4f641dff19c6b51b3e9",
 "head_ref": "wallet-mapwallet-multiindex",
 "head_repo": "achow101/bitcoin",
 "head_history": [
  {
   "t": "2026-07-14T17:42:17Z",
   "sha": "94cfe012e5bd807c7a7700785270d6e05729bca8"
  },
  {
   "t": "2026-07-14T17:56:13Z",
   "sha": "45d280323b41a9c98ccbd920061abdca6a2c979b"
  },
  {
   "t": "2026-07-17T19:17:10Z",
   "sha": "1d8337a63e536a683fd00812b5318d6c430c4f5c"
  },
  {
   "t": "2026-07-20T21:37:25Z",
   "sha": "e57b085ddc50108bb5096a898c3e1e1e8145540f"
  },
  {
   "t": "2026-07-21T22:03:01Z",
   "sha": "c56a38e90eaeb966e41eae97527dc8fe3a79b526"
  },
  {
   "t": "2026-08-05T23:24:53Z",
   "sha": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5"
  },
  {
   "t": "2026-08-12T18:17:33Z",
   "sha": "c883fb08c293dfc2dcaf35322dfda72e946acb98"
  },
  {
   "t": "2026-09-14T21:52:24Z",
   "sha": "c34334e9cbcfa8d3d82a2813191af0d5bac086b2"
  },
  {
   "t": "2026-09-14T23:44:00Z",
   "sha": "f31dfaeedf99d12ab2fce4f641dff19c6b51b3e9"
  }
 ],
 "additions": 367,
 "deletions": 302,
 "changed_files": 19,
 "commit_count": 4,
 "size_bucket": "L",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "theuni",
      "url": "https://github.com/bitcoin/bitcoin/pull/35716#issuecomment-4974409897"
     },
     {
      "login": "rkrux",
      "url": "https://github.com/bitcoin/bitcoin/pull/35716#issuecomment-5427418382"
     }
    ],
    "stale_ack": [
     {
      "login": "pablomartin4btc",
      "url": "https://github.com/bitcoin/bitcoin/pull/35716#pullrequestreview-5026667636"
     }
    ]
   },
   "conflicts": [
    {
     "number": 36167,
     "title": "[RFC] Enable `-Wunused`",
     "author": "fanquake"
    },
    {
     "number": 35998,
     "title": "wallet: Handle or explicitly ignore `WalletBatch` write failures",
     "author": "achow101"
    },
    {
     "number": 35786,
     "title": "wallet: drop spent parents redundant cache invalidation and notification",
     "author": "furszy"
    },
    {
     "number": 35569,
     "title": "Encapsulation for CTransaction",
     "author": "purpleKarrot"
    },
    {
     "number": 35511,
     "title": "RFC: consensus: Make `CAmount` a class",
     "author": "hodlinator"
    },
    {
     "number": 35294,
     "title": "wallet: Update tx chain state during loading during AttachChain instead of before",
     "author": "achow101"
    },
    {
     "number": 35151,
     "title": "wallet, follow-up: Refactor IsSpent to use HowSpent",
     "author": "musaHaruna"
    },
    {
     "number": 34909,
     "title": "wallet, refactor: modularise wallet by extracting out legacy wallet migration",
     "author": "rkrux"
    },
    {
     "number": 34371,
     "title": "wallet: allow importprunedfunds for spending transactions",
     "author": "8144225309"
    },
    {
     "number": 33034,
     "title": "wallet: Store transactions in a separate sqlite table",
     "author": "achow101"
    },
    {
     "number": 27865,
     "title": "wallet: Track no-longer-spendable TXOs separately",
     "author": "achow101"
    }
   ]
  }
 },
 "acks_parsed": {
  "theuni": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-07-14T22:03:13Z",
   "stale": false
  },
  "pablomartin4btc": {
   "kind": "ack",
   "hash": "c883fb08c293dfc2dcaf35322dfda72e946acb98",
   "t": "2026-08-26T04:45:27Z",
   "stale": true
  },
  "rkrux": {
   "kind": "concept_ack",
   "hash": "c883fb0",
   "t": "2026-08-26T15:19:05Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 1,
  "concept_ack": 2,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "pablomartin4btc",
   "rkrux",
   "theuni"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-09-14T23:44:00Z",
  "last_reviewer_activity": "2026-08-26T15:19:05Z",
  "last_reviewer": "rkrux",
  "author_silent_days": 2,
  "waiting_on_author_days": 0,
  "days_since_update": 0
 },
 "refs": {
  "mentioned": [],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [],
  "conflicts": [
   36167,
   35998,
   35786,
   35569,
   35511,
   35294,
   35151,
   34909,
   34371,
   33034,
   27865
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/wallet/wallet.cpp",
  "src/wallet/wallet.h"
 ],
 "body": "The wallet needs to access transactions both by txid, and by insertion order into the wallet. `mapWallet` was the main container for the wallet transactions, and it was keyed by txid. `wtxOrdered` was a secondary container which was keyed by order, and held pointers to the `CWalletTx` objects stored in `mapWallet`. 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`.",
 "commits": [
  {
   "sha": "01306fcab75a4ed5900738f46795a217a67ad436",
   "date": "2026-09-14T20:20:52Z",
   "message": "wallet: Replace many direct mapWallet lookups with GetWalletTx"
  },
  {
   "sha": "5deee3bcde68d3b3555fe8f0b849466d67a6e67b",
   "date": "2026-09-14T20:20:53Z",
   "message": "wallet, test: Use AddToWallet instead of direct mapWallet.emplace\n\nWhen a transaction needs to be added to the wallet for testing, we can\nuse AddToWallet instead of direct insertion into mapWallet."
  },
  {
   "sha": "cd552e1ba4dd52d9fad487af6549dd3e3b9b0437",
   "date": "2026-09-14T20:20:53Z",
   "message": "wallet: Mark CWalletTx::MarkDirty as const\n\nSince all of the things that MarkDirty changes are mutable, we can mark\nit as a const so it can be called on const CWalletTx objects."
  },
  {
   "sha": "f31dfaeedf99d12ab2fce4f641dff19c6b51b3e9",
   "date": "2026-09-14T23:43:54Z",
   "message": "wallet: Replace mapWallet with multi index m_txs\n\nSince we need to access transactions both by txid and insertion order,\ninstead of having 2 separate maps, the second with raw pointers into\nfirst, we can use a multi index."
  }
 ],
 "timeline": [
  {
   "t": "2026-07-14T17:42:17Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "94cfe012e5bd807c7a7700785270d6e05729bca8"
  },
  {
   "t": "2026-07-14T17:56:13Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "45d280323b41a9c98ccbd920061abdca6a2c979b"
  },
  {
   "t": "2026-07-14T22:03:13Z",
   "kind": "comment",
   "who": "theuni",
   "assoc": "MEMBER",
   "text": "Concept ACK. 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.\n\nGetting rid of multi_index for the kernel will require something that essentially re-implements its functionality, and I don't see anything new here that would complicate that implementation.\n\nNote that I'm biased: I'm currently working on such a re-implementation that I hope to propose for v33.\n\nI do have a few requests to make my life easier though.\n\n---\n\nFirstly, please specify an index for each operation, as opposed to just using `m_txs`. What happens behind the scenes in that case is that the first index is used, which is not _at all_ obvious to reviewers. In my rewrite I'm hoping to drop the implicit first index functionality and require an index for each call, as that greatly simplifies the implementation.\n\nFor ex, rather than `m_txs.find(hash)` use `m_txs.get<index_by_txid>().find(hash)`. That also means adding the tag for the txid index, which is currently missing.\n\nTo simplify that, in `wallet.h`, you can do:\n```c++\nWalletTxs m_txs;\nWalletTxs::index<index_by_txid>& m_txs_by_txid;\nWalletTxs::index<index_by_pos>& m_txs_by_pos;\n```\n\nAnd in the constructor:\n```c++\nm_txs_by_txid(m_txs.get<index_by_txid>());\nm_txs_by_pos(m_txs.get<m_txs_by_pos>());\n```\n\nThen everywhere you would use `m_txs`, use `m_txs_by_txid` or `m_txs_by_pos` instead. That makes the intent much more clear.\n\nHere's an example of the mempool conversion to work that way (though I used indices rather than tags, which is uglier): https://github.com/theuni/bitcoin/commit/b58ab92f9d6b231967328f560701d42710e04b92 .\n\n---\n\nSecondly, 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. I was planning on removing our existing `modify` calls for the same reason, so it'd be nice to not be adding more in the meantime."
  },
  {
   "t": "2026-07-17T19:01:13Z",
   "kind": "comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nHmm, `modify` is nicer though since it doesn't require remembering to re-insert and I find it easier to read. I'm also running into trouble with `extract` and `insert` where it doesn't work well for looping over the entire multi index and modifying each item."
  },
  {
   "t": "2026-07-17T19:17:10Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "1d8337a63e536a683fd00812b5318d6c430c4f5c"
  },
  {
   "t": "2026-07-20T21:37:25Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "e57b085ddc50108bb5096a898c3e1e1e8145540f"
  },
  {
   "t": "2026-07-20T21:39:06Z",
   "kind": "comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "text": "I've changed all of the `modify` to `extract` then `insert`, with some changes to the functions that iterate over everything in the wallet. These mainly involved calling `CWalletTx::MarkDirty`. Since that function only changes non-key mutable members of `CWalletTx`, I made `MarkDirty` const so that it can be called without needing to do the `extract` then `insert`."
  },
  {
   "t": "2026-07-21T22:03:01Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "c56a38e90eaeb966e41eae97527dc8fe3a79b526"
  },
  {
   "t": "2026-08-05T23:24:53Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5"
  },
  {
   "t": "2026-08-09T23:30:41Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.cpp",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "in_reply_to": null,
   "text": "shouldn't be `continue` instead of `return`?"
  },
  {
   "t": "2026-08-09T23:31:17Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.cpp",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "in_reply_to": null,
   "text": "same as above, shouldn't be `continue`?"
  },
  {
   "t": "2026-08-09T23:32:35Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.cpp",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "in_reply_to": null,
   "text": "same as in `SyncMetaData`, shouldn't be `continue`?"
  },
  {
   "t": "2026-08-09T23:41:12Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.h",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "in_reply_to": null,
   "text": "nit: doc is stale...\n```suggestion\n     * @return iterator to the recently added or updated wtx, or nullopt if there was a db write error.\n```"
  },
  {
   "t": "2026-08-09T23:54:30Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.cpp",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "in_reply_to": null,
   "text": "I think this is redundant? The caller already holds the lock to `cs_wallet`... shouldn't instead define `ComputeTimeSmart` as `EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)`?"
  },
  {
   "t": "2026-08-10T03:01:38Z",
   "kind": "review",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "text": "Concept ACK\n\nReplace two containers \u2014 `mapWallet` (`std::unordered_map<Txid, CWalletTx>`) and `wtxOrdered` (`std::multimap<int64_t, CWalletTx*>` \u2014 a secondary index with raw pointers into `mapWallet`) \u2014 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.\n\nSpecifying an index for each operation (rather than leaving it to the implicit first index usage that could be confusing) and the extract/insert pattern (instead of modify) were both implemented as @theuni suggested, for the latter, it required making `MarkDirty` const (all its changes are to mutable members).\n\nPR description nit: This PR used to be dependent on already merged https://github.com/bitcoin/bitcoin/pull/35501 for the CWalletTx constructor changes that are necessary for this.\n\nLeft a few inline nits..."
  },
  {
   "t": "2026-08-12T18:16:53Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.cpp",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "in_reply_to": 3745661453,
   "text": "Fixed, leftovers from the previous approach"
  },
  {
   "t": "2026-08-12T18:16:57Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.cpp",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "in_reply_to": 3745662873,
   "text": "Fixed, leftovers from the previous approach"
  },
  {
   "t": "2026-08-12T18:17:09Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.cpp",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "in_reply_to": 3745666350,
   "text": "Fixed, leftovers from the previous approach"
  },
  {
   "t": "2026-08-12T18:17:15Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.h",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "in_reply_to": 3745688126,
   "text": "Done"
  },
  {
   "t": "2026-08-12T18:17:20Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.cpp",
   "commit": "347ad6e75cf1164a1bf1e7bfb151d2c56995e4a5",
   "in_reply_to": 3745723713,
   "text": "Fixed, leftovers from the previous approach"
  },
  {
   "t": "2026-08-12T18:17:33Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "c883fb08c293dfc2dcaf35322dfda72e946acb98"
  },
  {
   "t": "2026-08-26T04:07:01Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.h",
   "commit": "f31dfaeedf99d12ab2fce4f641dff19c6b51b3e9",
   "in_reply_to": null,
   "text": "nit: the `AddToWallet` doc comment landed slightly garbled \u2014 \"iterator to the recently added wtx pointer or nullopt...\" mixes \"iterator\" and \"pointer\" and drops the \"or updated\" that was suggested, even though the function still handles both new and existing txs...\n```suggestion\n     * @return iterator to the recently added or updated wtx pointer, or nullopt if there was a db write error.\n```"
  },
  {
   "t": "2026-08-26T04:45:27Z",
   "kind": "review",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "c883fb08c293dfc2dcaf35322dfda72e946acb98",
   "text": "ACK c883fb08c293dfc2dcaf35322dfda72e946acb98\n\nWhile checking `ReorderTransactions()` specifically (it had no direct test coverage), I found this PR incidentally fixes a real bug on `master`: `ReorderTransactions()` mutates each `CWalletTx::nOrderPos` in place but never touches `wtxOrdered`, the `std::multimap` used for position-ordered iteration (used by `listtransactions`/ `listsinceblock` and `ComputeTimeSmart`). Any tx loaded with `nOrderPos == -1` (a legacy/unordered record) is keyed at `-1` in `wtxOrdered` at load time, and since `-1` sorts before every real position, it stays stuck at the front of that ordering forever \u2014 regardless of the real position `ReorderTransactions()` later computes. So a legacy wallet needing reorder can return transactions in the wrong order from listtransactions today. (In practice this only triggers for a `wallet.dat` old enough to predate order-position tracking \u2014 nOrderPos is always assigned before a normal write in every current code path \u2014 so it's a narrow, but real, latent bug.)\n\nThis PR's multi_index refactor makes that bug structurally impossible, since `nOrderPos` is the sort key of the ordered index itself \u2014 any mutation has to go through `extract()`+`insert()`, which re-sorts automatically.\n\nCreated a test in b27d3b9b67ae3fe2d101d567c3dc004255021af5  that reproduces this: writes 3 tx records directly to a mock DB, one of them the chronologically newest but with `nOrderPos == -1` to simulate the legacy state, then loads the wallet and checks it ends up last when iterated in position order. Confirmed red/green \u2014 fails on `master` (`order.back()` returns the wrong tx), passes on this branch.\n\nAlso, left a nit..."
  },
  {
   "t": "2026-08-26T15:19:05Z",
   "kind": "comment",
   "who": "rkrux",
   "assoc": "MEMBER",
   "text": "Concept ACK c883fb0\n\nThis 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."
  },
  {
   "t": "2026-08-26T18:14:53Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/wallet.h",
   "commit": "f31dfaeedf99d12ab2fce4f641dff19c6b51b3e9",
   "in_reply_to": 3859564391,
   "text": "If I retouch"
  },
  {
   "t": "2026-09-14T21:52:24Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "c34334e9cbcfa8d3d82a2813191af0d5bac086b2"
  },
  {
   "t": "2026-09-14T23:44:00Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "f31dfaeedf99d12ab2fce4f641dff19c6b51b3e9"
  }
 ],
 "labels_log": [
  {
   "t": "2026-07-14T00:33:54Z",
   "action": "labeled",
   "label": "Wallet",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-14T01:26:15Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-21T23:06:26Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-04T22:55:06Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-06T00:48:11Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-12T12:02:31Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-14T22:40:33Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-14T23:02:14Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-15T00:44:55Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-08-05T23:25:01Z",
   "kind": "ready_for_review",
   "who": "achow101"
  }
 ],
 "text_chars": 7757,
 "text_tokens_estimate": 1939,
 "changed_paths": [
  "src/CMakeLists.txt",
  "src/wallet/export.cpp",
  "src/wallet/feebumper.cpp",
  "src/wallet/interfaces.cpp",
  "src/wallet/receive.cpp",
  "src/wallet/rpc/coins.cpp",
  "src/wallet/rpc/transactions.cpp",
  "src/wallet/rpc/wallet.cpp",
  "src/wallet/spend.cpp",
  "src/wallet/test/coinselector_tests.cpp",
  "src/wallet/test/fuzz/spend.cpp",
  "src/wallet/test/group_outputs_tests.cpp",
  "src/wallet/test/psbt_wallet_tests.cpp",
  "src/wallet/test/wallet_tests.cpp",
  "src/wallet/transaction.h",
  "src/wallet/wallet.cpp",
  "src/wallet/wallet.h",
  "src/wallet/walletdb.cpp",
  "src/wallet/wallettool.cpp"
 ],
 "files": [
  {
   "path": "src/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/wallet/export.cpp",
   "add": 3,
   "del": 3
  },
  {
   "path": "src/wallet/feebumper.cpp",
   "add": 6,
   "del": 6
  },
  {
   "path": "src/wallet/interfaces.cpp",
   "add": 22,
   "del": 22
  },
  {
   "path": "src/wallet/receive.cpp",
   "add": 4,
   "del": 4
  },
  {
   "path": "src/wallet/rpc/coins.cpp",
   "add": 4,
   "del": 4
  },
  {
   "path": "src/wallet/rpc/transactions.cpp",
   "add": 10,
   "del": 16
  },
  {
   "path": "src/wallet/rpc/wallet.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/wallet/spend.cpp",
   "add": 5,
   "del": 5
  },
  {
   "path": "src/wallet/test/coinselector_tests.cpp",
   "add": 5,
   "del": 6
  },
  {
   "path": "src/wallet/test/fuzz/spend.cpp",
   "add": 2,
   "del": 4
  },
  {
   "path": "src/wallet/test/group_outputs_tests.cpp",
   "add": 5,
   "del": 7
  },
  {
   "path": "src/wallet/test/psbt_wallet_tests.cpp",
   "add": 4,
   "del": 2
  },
  {
   "path": "src/wallet/test/wallet_tests.cpp",
   "add": 20,
   "del": 21
  },
  {
   "path": "src/wallet/transaction.h",
   "add": 5,
   "del": 5
  },
  {
   "path": "src/wallet/wallet.cpp",
   "add": 208,
   "del": 180
  },
  {
   "path": "src/wallet/wallet.h",
   "add": 54,
   "del": 13
  },
  {
   "path": "src/wallet/walletdb.cpp",
   "add": 7,
   "del": 2
  },
  {
   "path": "src/wallet/wallettool.cpp",
   "add": 1,
   "del": 1
  }
 ],
 "test_lines": 76,
 "git": {
  "head": "f31dfaeedf99d12ab2fce4f641dff19c6b51b3e9",
  "head_matches_backup": true,
  "base": "cff00c547e7460fa1ec4aa1e38217793593d4263",
  "commits": [
   {
    "sha": "01306fcab7",
    "subject": "wallet: Replace many direct mapWallet lookups with GetWalletTx",
    "files": 9,
    "add": 71,
    "del": 78
   },
   {
    "sha": "5deee3bcde",
    "subject": "wallet, test: Use AddToWallet instead of direct mapWallet.emplace",
    "files": 5,
    "add": 19,
    "del": 23
   },
   {
    "sha": "cd552e1ba4",
    "subject": "wallet: Mark CWalletTx::MarkDirty as const",
    "files": 1,
    "add": 3,
    "del": 2
   },
   {
    "sha": "f31dfaeedf",
    "subject": "wallet: Replace mapWallet with multi index m_txs",
    "files": 18,
    "add": 287,
    "del": 212
   }
  ],
  "patch_truncated": true
 },
 "input_hash": "9f1ab8336174cf19",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}