{
 "number": 36598,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/36598",
 "title": "[Demo] validation: remove AssumeUTXO",
 "author": "l0rinc",
 "author_association": "MEMBER",
 "created_at": "2026-10-22T06:38:37Z",
 "updated_at": "2026-10-26T20:52:58Z",
 "description_hash": "c71f927ac71a0a47",
 "age_days": 10,
 "draft": true,
 "labels": [
  "Needs rebase"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "bc62b59b8d631133e307a88c267749917e195860",
 "head_ref": "l0rinc/remove-assumeutxo",
 "head_repo": "l0rinc/bitcoin",
 "head_history": [
  {
   "t": "2026-10-22T09:50:03Z",
   "sha": "bc62b59b8d631133e307a88c267749917e195860"
  }
 ],
 "additions": 672,
 "deletions": 5795,
 "changed_files": 82,
 "commit_count": 35,
 "size_bucket": "XL",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_nack": [
     {
      "login": "Sjors",
      "url": "https://github.com/bitcoin/bitcoin/pull/36598#issuecomment-6379989317"
     }
    ],
    "concept_ack": [
     {
      "login": "ismaelsadeeq",
      "url": "https://github.com/bitcoin/bitcoin/pull/36598#issuecomment-6338865042"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "ismaelsadeeq": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-10-22T10:46:14Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 1,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "Sjors",
   "ariard",
   "ismaelsadeeq"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-10-22T09:50:03Z",
  "last_reviewer_activity": "2026-10-24T04:43:14Z",
  "last_reviewer": "Sjors",
  "author_silent_days": 10,
  "waiting_on_author_days": 8,
  "days_since_update": 6
 },
 "refs": {
  "mentioned": [
   32377,
   34075,
   35054,
   35295,
   36543,
   36557,
   36601
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 35295,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-07-09",
    "title": "validation: fetch block input prevouts in parallel during ConnectBlock"
   },
   {
    "number": 32377,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "AssumeUTXO: crowdsource trust through independent snapshot verification"
   },
   {
    "number": 36543,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "validation: check the most recent AssumeUTXO commitment during IBD"
   },
   {
    "number": 36557,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "AssumeUTXO: drop background sync?"
   },
   {
    "number": 36601,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "test: avoid reusing AssumeUTXO coin insertion method in test fixtures"
   },
   {
    "number": 35054,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "p2p: UTXO set sharing"
   },
   {
    "number": 34075,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-08-21",
    "title": "fees: Introduce Mempool Based Fee Estimation to reduce overestimation"
   }
  ],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [
   36601
  ],
  "based_on": [
   36601
  ],
  "base_for": []
 },
 "review_paths": [],
 "body": "**Draft demo:** this is meant to showcase what complete AssumeUTXO removal could look like and the simplifications that AssumeUTXO currently prevents.\nThe decision about complete removal is of course still open. This draft is meant to serve as a concrete reference for the smaller proposals below - it's not meant to be merged.\n\n**Smaller PRs:** I will carve out individual changes to gauge interest in each part, and link them here as they are opened.\nSome of the findings are useful even if snapshot loading or background validation stays.\nFeedback on which parts seem worth pursuing, and in which order, is welcome.\n\n**Motivation:** this follows our in-person discussion at the October 2026 Core Dev meeting.\nMy impression was that there was rough agreement about the ambiguity background validation introduces: we trust a snapshot enough to use it immediately, but describe that trust as temporary until the same node finishes checking history.\n\nMultiple chainstates affect much more than snapshot loading: ordinary validation changes have to account for different chainstate roles, candidate sets, notifications, downloads, pruning, cache allocation, database lifetimes and locks.\nI am not sure this amount of complexity in the most critical part of our codebase is still worth it, given that adoption [isn't where we hoped it would be](https://github.com/bitcoin/bitcoin/pull/35054#issuecomment-4468360424).\nOrdinary IBD is also getting faster: #35295 is already merged, and the upcoming `pruneassumevalid` will make pruned IBD even faster.\n\nSnapshot bootstrapping without background validation can still offer an advantage: a new node becomes usable before ordinary IBD would finish because snapshot loading time scales with the UTXO set size, while ordinary IBD time scales with the blockchain size.\nWhether that is worth its maintenance cost is a fair question, and we can discuss it here or in the dedicated PR where I will propose the removal.\nEven after removal, we could decide to add it back in a cleaner way, for example isolated through IPC.\nThis demo makes that cost, and the code we could remove, visible for that discussion.\n\n**Background validation can be considered separately:** if we keep snapshot loading, I would prefer making its trust assumption explicit and distributing verification across ordinary IBD nodes, as proposed in #32377 and #36543.\nThat could give us wider independent checking of the commitment without making every snapshot user maintain a second chainstate.\n\nUsers who want to validate history themselves and transition to an archival node could rebuild with `-reindex` and pruning disabled.\nAlternatively, they could run IBD in a separate datadir while their snapshot node remains usable, then switch once it is ready.\n@Sjors's #36557 discusses dropping mandatory background sync and these alternatives.\n\n**What the series demonstrates:**\n\n* After the fixture cleanup in #36601, the next eight commits remove background validation while snapshot loading keeps working, a stopping point that can be reviewed on its own.\n* The middle commits remove snapshot imports and startup resumption, then the validation, block storage, notification and release-process special cases they needed.\n* The final seven commits add the simplifications this removal enables: startup in one pass, stable database ownership, one download path, a single prune height, and removal of the locks and diagnostics used to select and identify chainstates.\n\nOrdinary validation, `-assumevalid`, pruning, `ChainstateManager` and UTXO export (`dumptxoutset`) remain.\n\n**Related work:**\n\n* [AJ's recent faster-loader branch](https://github.com/ajtowns/bitcoin/tree/202610-loadtxoutset-speedy) and [Sjors's chunked-import experiments](https://github.com/Sjors/bitcoin/tree/2026/10/utxo-coin-chunks) explore reducing import overhead while retaining snapshot support.\n* #35054 contains the broader discussion about P2P snapshot distribution, its users and its costs.",
 "commits": [
  {
   "sha": "1c62336903ccf5f7f2aa1217eaf8344dee4e197a",
   "date": "2026-10-22T07:19:59Z",
   "message": "test: avoid snapshot insertion in coin fixtures\n\nUse `AddCoin` and `SpendCoin` to set up the flush, reset and overlay tests, leaving direct coverage of `EmplaceCoinInternalDANGER` in the simulation, fuzz target and duplicate-insertion test.\nSet `possible_overwrite=true` to keep the entries DIRTY but not FRESH, as before."
  },
  {
   "sha": "6d3f3c2852a6524f6b8ea389b34b79381146f07a",
   "date": "2026-10-22T09:42:35Z",
   "message": "test: prepare coverage for AssumeUTXO removal\n\nPreserve tip notifications, candidate rebuilding and explicit rollback exports before removing mixed snapshot tests."
  },
  {
   "sha": "d72e3a733326712f397b74c30d1727634f082b2a",
   "date": "2026-10-22T09:42:35Z",
   "message": "validation: stop background cache reprioritization\n\nKeep the existing snapshot-first cache split after the snapshot reaches tip.\nRemove the IBD-exit resize trigger and the allocation reversal that prioritizes historical validation.\nActivation and startup still resize caches while snapshot loading is supported.\nThe existing allocation test no longer needs to force IBD to select this split."
  },
  {
   "sha": "05f043e63ee4b4b85cd61f2082297f52d504cc5c",
   "date": "2026-10-22T09:42:35Z",
   "message": "rpc: remove background validation progress\n\nRemove the backgroundvalidation object from getblockchaininfo and its dedicated assertions.\nSnapshot import, background validation and the getchainstates diagnostic remain available."
  },
  {
   "sha": "cc4ba39fe943f343e347177f8311f570c21902ba",
   "date": "2026-10-22T09:42:35Z",
   "message": "wallet: remove background progress hints\n\nUse the ordinary missing-block rescan errors instead of making wallets depend on background progress.\nKeep the snapshot wallet-load restriction and describe explicit reindex recovery.\nUpdate only the existing error assertions while background validation and wallet scenarios remain supported."
  },
  {
   "sha": "d084a285cc65217377fb4aba99235ea20bc74a68",
   "date": "2026-10-22T09:42:36Z",
   "message": "index: stop following the historical chainstate\n\nUse the active chain and existing block-availability checks for index startup.\nReject snapshot imports while indexes are running and remove automatic index restarts at snapshot completion.\nKeep background validation and its network-service restoration.\nThe existing snapshot test starts indexes on its ordinary restart after historical validation completes."
  },
  {
   "sha": "46f5f90c041549ff6f31715c1d86fa920d8eacba",
   "date": "2026-10-22T09:42:36Z",
   "message": "validation: stop historical synchronization\n\nDownload blocks only for the active chain and stop historical activation at its common entry point.\nKeep the guard with download removal so startup and direct callers cannot advance incomplete historical candidates.\nAdapt the existing import, wallet and native scenarios to stopped history and explicit reindex recovery."
  },
  {
   "sha": "ba09b96c9a830b10abc1659b42424d6a73ff8eec",
   "date": "2026-10-22T09:42:36Z",
   "message": "validation: delete historical activation callers\n\nHistorical activation is already disabled. Remove its callers in ProcessNewBlock and ActivateBestChains.\nRemove completion handling from ConnectTip and the remaining network-service callback.\nKeep periodic flushing and the genesis interrupt ordering.\nSnapshot imports and startup resumption remain supported."
  },
  {
   "sha": "436d2ec19753eca4e5e0ee8266674a09b2894f79",
   "date": "2026-10-22T09:42:36Z",
   "message": "validation: delete background completion\n\nRemove historical UTXO hashing, its failure handling and the restart-time directory normalization it drove.\nRemove the hash-mismatch test and reuse the completion scenario to check that restart keeps the snapshot assumed.\nSnapshot loading still checks the compiled commitment before activation.\nSnapshot databases now remain assumed across restart until explicitly discarded by reindexing.\nPreviously completed imports can be normalized with a compatible older release before upgrading.\nRemove background progress and prefixes from the existing tip-log helper."
  },
  {
   "sha": "e5ac89973982f2f3f335d519af933229bb897707",
   "date": "2026-10-22T09:42:36Z",
   "message": "rpc: stop new snapshot imports\n\nRetire loadtxoutset after background validation has been removed independently.\nKeep a hidden RPC tombstone and string argument conversion to explain the removal to existing callers.\nExisting snapshot datadirs still resume, so keep getchainstates and startup coverage until resumption is retired.\nRemove import instructions and end-to-end import scenarios, preserving ordinary kernel-tool coverage.\nReuse the export test to check the removed RPC's error code with both RPC and CLI transports."
  },
  {
   "sha": "060ea8908b3491eb07d50c72b712f4fea3f77a61",
   "date": "2026-10-22T09:42:37Z",
   "message": "net: drop mutable AssumeUTXO service flags\n\nAssumeUTXO import and completion were the only runtime writers of local services.\nTheir removal lets CConnman store the startup services without an atomic.\nInit sets them before network threads start and before RPC warmup ends.\nKeep the constructor's initial NODE_NONE value through its existing Init call."
  },
  {
   "sha": "ad4cefb50f9a4cf48b3ec51d4a1fb7442b7d8e86",
   "date": "2026-10-22T09:42:37Z",
   "message": "validation: reject legacy snapshot startup\n\nAfter snapshot import removal, refuse snapshot datadirs with an active marker before destructive node or kernel initialization.\nKeep normalized ordinary datadirs usable and preserve rejected data for recovery with a compatible older release.\nRemove getchainstates and activation, restart and import fuzz coverage now that supported entry points are closed.\nKeep cache resizing, commitment and metadata parsing tests until their corresponding APIs are removed.\nDocument this transition alongside the compatibility tests.\nDelete candidate clearing with its last snapshot-test caller.\nRemove unused database and validation-cache fixture options with their last snapshot test callers."
  },
  {
   "sha": "a9ce3d5d6c58356b2846a48b1e9414fa012d38a0",
   "date": "2026-10-22T09:42:37Z",
   "message": "rpc: require an explicit UTXO rollback target\n\nKeep UTXO exports available without trusted snapshot commitments.\nRequire a rollback height or hash instead of choosing a supported AssumeUTXO snapshot."
  },
  {
   "sha": "52ee1d9a161500c41bc27a86f5bc68225b45c13f",
   "date": "2026-10-22T09:42:37Z",
   "message": "chainparams: remove AssumeUTXO commitments\n\nRemove the trusted snapshot entries now that import and startup resumption are unavailable.\nKeep the lookup interfaces until their remaining callers are removed."
  },
  {
   "sha": "d8b0ddc02f8492edd18070326f1c07eb3aba767c",
   "date": "2026-10-22T09:42:38Z",
   "message": "validation: drop snapshot chain restrictions\n\nSnapshot startup and imports are disabled. Remove the remaining snapshot-base peer filter and historical fork-warning exception."
  },
  {
   "sha": "95fd82307d0ab8481c485e31ac724c7f7ee7965d",
   "date": "2026-10-22T09:42:38Z",
   "message": "validation: load only the active chainstate\n\nSnapshot imports and startup resumption are unavailable.\nInitialize and verify the ordinary chainstate directly, retaining interruption and database errors.\nCompletion hashing and directory normalization were removed with background validation.\nDelete the unused restart loader and chainstate deletion helper with their last startup callers.\nRemove the deletion test while retaining ordinary kernel operation without a mempool."
  },
  {
   "sha": "d5c7d02f56866709d6b5eeb5fe6db5154f2ce78c",
   "date": "2026-10-22T09:42:38Z",
   "message": "validation: delete AssumeUTXO coin loading\n\nDelete snapshot activation, coin import and their unused helpers.\nKeep AddChainstate until its remaining cache-rebalancing test is removed."
  },
  {
   "sha": "69a90c66442b171919ff48b5cf620d2ea57f83b6",
   "date": "2026-10-22T09:42:39Z",
   "message": "coins: delete AssumeUTXO insertion bypass\n\nSnapshot import bypassed the normal AddCoin spentness checks through EmplaceCoinInternalDANGER.\nWith the importer removed and fixtures using AddCoin and SpendCoin, delete the bypass and its entry constructor together with the remaining simulation, fuzz and duplicate-insertion coverage."
  },
  {
   "sha": "9880f12c59efa7288b39fb0cda909ae17956f184",
   "date": "2026-10-22T09:42:39Z",
   "message": "validation: delete obsolete cache resizing\n\nAssumeUTXO activation and cache sharing no longer need runtime resizing.\nRemove the final startup rebalance call and the unused rebalancing and resizing APIs.\nKeep startup cache-budget storage and use the existing test budget field directly.\nThe database is no longer replaced, so compaction needs no extra mutex.\nRemove AddChainstate with its final cache-rebalancing test caller.\nRemove the resizing and rebalancing tests with the APIs they exercise."
  },
  {
   "sha": "e749dc5bdd94e6c684a76b111e225ddf16f5629f",
   "date": "2026-10-22T09:42:39Z",
   "message": "node: delete AssumeUTXO directory metadata\n\nUse the ordinary chainstate directory without snapshot path selection.\nRemove the base-block metadata readers, writers and StoragePath helper.\nRetain the UTXO export file format and its metadata parser."
  },
  {
   "sha": "c824984cd396de3100a0281ff71852ddc8c50ae6",
   "date": "2026-10-22T09:42:39Z",
   "message": "validation: remove AssumeUTXO index exceptions\n\nSnapshot loading has already been removed, so candidates require transaction history back to genesis.\nRemove snapshot-base exceptions from transaction counts and consistency checks.\nOrdinary script, sigop, BIP30 and proof-of-work checks are unchanged."
  },
  {
   "sha": "9cf0eaa0b7a248423bde14408d26e6aa240e5be7",
   "date": "2026-10-22T09:42:40Z",
   "message": "node: load block counts without AssumeUTXO\n\nReconstruct cumulative transaction counts from downloaded block history.\nRemove the trusted snapshot count supplied during block-index loading.\nRemove the commitment type, storage and lookup interfaces with their last caller.\nDelete FindFirst with the lookup methods that used it.\nInclude util/vector.h directly for the external signer now that chainparams no longer supplies it."
  },
  {
   "sha": "f3d6b9f3cbac6913444e5e55febed219fc3a2108",
   "date": "2026-10-22T09:42:40Z",
   "message": "node: use one block-file cursor and prune budget\n\nWithout AssumeUTXO, historical and tip downloads no longer need separate block files or divided prune budgets.\nWrite blocks and undo data through the ordinary block-file cursor.\nKeep cs_main locking, undo flush failures and pruning retention unchanged.\nWith one cursor, flushing always targets the current block file. Remove the separate file selector and forwarding wrapper.\nThe undivided prune target already satisfies the configured minimum, so it needs no per-chainstate clamp.\nDelete the obsolete cursor selector and printer with their last callers.\nRemove the snapshot lower prune bound while preserving the existing pruning helper interfaces."
  },
  {
   "sha": "d08f939dc38607b47cc5e3dc1afb7b99c2b5f34a",
   "date": "2026-10-22T09:42:40Z",
   "message": "wallet: use ordinary block availability checks\n\nRetain pruning and rescan errors without the removed AssumeUTXO state.\nDo not change wallet transaction accounting.\nRemove hasAssumedValidChain with its last wallet callers."
  },
  {
   "sha": "48c5977694d736fa35d941117bc3e9b7badbfbd6",
   "date": "2026-10-22T09:42:41Z",
   "message": "refactor: drop AssumeUTXO notification roles\n\nAll remaining notifications come from the ordinary chainstate.\nRemove the role argument from internal callbacks and their callers.\nThe public kernel callback ABI is unchanged.\nDelete the unused role accessor, formatter and type with their consumers."
  },
  {
   "sha": "ce6993c4f340710e31aa8192c39059e4e70fabdc",
   "date": "2026-10-22T09:42:41Z",
   "message": "refactor: use the ordinary chainstate accessors\n\nUse the active chainstate for indexing and progress.\nNo snapshot chainstate can be constructed or loaded.\nRemove the unused snapshot target, base and chainstate-selection methods with their last callers."
  },
  {
   "sha": "8372144e28c23ce0f8e12a05fea8a2786d930b9e",
   "date": "2026-10-22T09:42:41Z",
   "message": "validation: retain one ordinary chainstate\n\nReplace the chainstate vector with one owned chainstate.\nRemove snapshot targets, validity state and obsolete aliases.\nSnapshot activation no longer transfers the optional mempool between chainstates.\nKeep its pointer mutable for fuzz fixtures that replace the pool.\nKeep shutdown flushing and block activation on the ordinary path.\nRemove ResetChainstates with its last caller instead of rewriting its unused body.\nA successfully created kernel manager always owns that state at destruction.\nTip notifications no longer need to check which chainstate is active."
  },
  {
   "sha": "19a40435cc0071be6f36844fac114185b17f0bca",
   "date": "2026-10-22T09:42:41Z",
   "message": "rpc: remove snapshot metadata decoding\n\nDeleting the AssumeUTXO importer leaves only the export side of the snapshot metadata format.\nDelete the unused metadata parser, its deserialization fuzzer and the parser-only network-magic lookup.\nKeep the existing export serializer and its callers unchanged."
  },
  {
   "sha": "bbdaa554a7a4845ca30eb20f1ef2109ab236595c",
   "date": "2026-10-22T09:42:42Z",
   "message": "node: initialize one chainstate in one pass\n\nAssumeUTXO completion no longer tears down and reloads chainstates during startup.\nFold the remaining initialization pass into LoadChainstate and pass the cache budgets directly to the sole chainstate instead of retaining totals for redistribution."
  },
  {
   "sha": "646997a90395f10874796e2e53f2719a88400aae",
   "date": "2026-10-22T09:42:42Z",
   "message": "txdb: own the coins database directly\n\nRemoving AssumeUTXO cache resizing leaves the coins database open for the lifetime of its view.\nStore the wrapper by value and retain only the path used in compaction logs instead of parameters for reopening it.\nPass database parameters by reference now that neither view retains them.\nKeep the compaction future, overlap check and destructor wait so a worker cannot outlive the database."
  },
  {
   "sha": "f5f80498b028922b506e9aab0520f79580fcf6b6",
   "date": "2026-10-22T09:42:42Z",
   "message": "net: use one block download path\n\nHistorical AssumeUTXO downloads were the only caller that omitted the active chain and staller tracking.\nFold the shared traversal into the ordinary download path and evaluate its in-flight budget once now that there is no second download pass."
  },
  {
   "sha": "7c084b907045ef3a21955f7e5c173c6f03eaaf4c",
   "date": "2026-10-22T09:42:43Z",
   "message": "node: prune using a single upper height\n\nThe snapshot base was the only nonzero lower bound on pruning.\nWith AssumeUTXO removed, keep the tip-distance and requested-height limits in block storage and drop the always-zero lower bound and chainstate range accessor."
  },
  {
   "sha": "701ada3a7462ae2d73686d7392ea08a8cf7b8994",
   "date": "2026-10-22T09:42:43Z",
   "message": "validation: drop chainstate selection locking\n\nSnapshot activation no longer replaces the active chainstate while the node is running.\nRead the fixed owner without cs_main and remove locks that existed only to select it, including the outer fee-estimation lock around a block assembler that locks internally.\nChain contents and validation still retain their existing synchronization."
  },
  {
   "sha": "824d0fb5777f7e5a320cd61af3eff2b5c7e2e903",
   "date": "2026-10-22T09:42:43Z",
   "message": "validation: drop chainstate identity diagnostics\n\nWith AssumeUTXO gone, activation visits one chainstate and no longer needs to identify which state failed.\nUse the singular activation name and remove the chainstate formatter, its startup log and the lock used only to format the activation error."
  },
  {
   "sha": "bc62b59b8d631133e307a88c267749917e195860",
   "date": "2026-10-22T09:42:43Z",
   "message": "rpc: keep UTXO export serialization local\n\nRemoving snapshot imports leaves dumptxoutset as the only consumer of the snapshot header and export helpers.\nWrite the unchanged version 2 header at its sole call site and keep the helpers inside the RPC translation unit.\nDrop unused default arguments from these now-local export helpers."
  }
 ],
 "timeline": [
  {
   "t": "2026-10-22T09:50:03Z",
   "kind": "force_push",
   "who": "l0rinc",
   "commit": "bc62b59b8d631133e307a88c267749917e195860",
   "id": "push:bc62b59b8d631133e307a88c267749917e195860"
  },
  {
   "t": "2026-10-22T10:46:14Z",
   "kind": "comment",
   "who": "ismaelsadeeq",
   "assoc": "MEMBER",
   "text": "Concept ACK.\n\nFollowing on from what we discussed in person: a feature-ready, usable assumeUTXO is with P2P utxo snapshot sharing, no background validation, and potentially on by default. I don't think it's a state we want to be in.\nThat variant of assumeUTXO trusts the whole money supply and UTXO set without ever reconstructing it. Making that the default new user experience, for the dominant full node implementation, is a shift in what running a node means, I'd rather we lean on fewer assumptions, e.g. even removing assumevalid as default.\n\nIf the feature-ready version lands and most new nodes come up from a snapshot and never pull the history, then over time the archival nodes thin out and validating/having the chain's history becomes something only a handful of nodes still do. Worst case, you can recover your funds but not the history. Pruning already nudges us that way (though it's not on by default, and most users only prune when they actually need to), but a snapshot default would speed it up. It's a bit of an extreme scenario, but I don't think it's an implausible state to be in, if the direction is future ready assumeUTXO.\n\nAnd as discussed, as-is it's not even that usable, loading the snapshot takes too long. I remember giving up when trying it for the first time. (This can be fixed though)\n\nI've also hit a maintenance cost directly. e.g. in #34075 we do block building, and query the tip which needs the chainstate, and multiple chainstates make that harder than it should be. Any node component that needs chainstate has no guarantee the chainstate it grabbed is still live, and the active one can get swapped under it, so you end up holding onto the chainstate manager and re-fetching the active chainstate every time instead of just keeping a stable handle. The last seven commits here show what you get back once this is gone.\n\nI do think there's probably still a group of users who'd want assumeUTXO like snapshot bootstrapping. But I'd rather that live outside the dominant full node, `libbitcoinkernel` c header api should gives downstream projects a way to embed a ready UTXO set without risking a consensus split? and with LLMs now, that node-like projects can easily be vibe coded.\n\nSnapshot loading scales with the UTXO set size while IBD scales with chain length indeed, so there is some argument on the linear growth concern and that #35295 and your pruneassumevalid idea don't fully close that gap for a new node that validates/semi validates the chain history, and that gap only grows as the chain gets longer.\nThat's a genuine advantage of assumeUTXO. But I don't think it's worth the complexity and assumptions it adds to the the reference implementation.\n\n@l0rinc should we do it through the usual deprecate then remove style? Also thanks for putting the demo together, having the removable code and the simplifications it shows is nice to see.",
   "id": "c:6338865042",
   "url": "https://github.com/bitcoin/bitcoin/pull/36598#issuecomment-6338865042",
   "hash": "87d73f23326e4b3f",
   "edited": null
  },
  {
   "t": "2026-10-24T02:30:00Z",
   "kind": "comment",
   "who": "ariard",
   "assoc": "CONTRIBUTOR",
   "text": "After the amount of time spent reviewing and testing assumeutxo, some folks might have a Stockholm syndroma removing assume utxo and me not the last...\n\nMore technically, it would has been possible to find an intermediary technical solution, where we would have kept the AssumeUTXO feature has an optional special build flag side-companion process available through a new `ipc/capnp/sidevalidation.cpp`. Somehow, the folks who wish to use AssumeUTXO would be able to do so, and this would ease diminish the maintenance burden for the libbitcoinkernel folks.\n\nOn a more usage level, I did share [few ideas](https://gnusha.org/pi/bitcoindev/CALZpt+FRPThy4qwYThXOY_YJWsGKJuCOqpX1Zt_8SqkeA4bQsg@mail.gmail.com/) in the past on how to use AssumeUTXO for second-layers reputation systems, see here. Never been practical, though it would have been interesting for second-layers nodes, as they would have been able to join the system \"on-the-fly\" by leveraging assumeutxo activate chainstate.",
   "id": "c:6378769111",
   "url": "https://github.com/bitcoin/bitcoin/pull/36598#issuecomment-6378769111",
   "hash": "677ac1b72ebbc3c1",
   "edited": null
  },
  {
   "t": "2026-10-24T04:43:14Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nThis is fine and useful.\n\nBut to be clear, I'm concept NACK on actually removing AssumeUTXO.\n\nI think we should drop background validation first, as I suggested in #36557. After that we can reconsider if code complexity is still too high.\n\n@ismaelsadeeq wrote:\n\n[quoted text omitted]\n(nit: the total supply can easily be checked against the issuance schedule. The distribution of the supply can't be checked.)\n\nI don't think we should revisit `-assumevalid` in a discussion of removing AssumeUTXO, but it does raise an important point: we already allow users to skip part of validation and we even do it by default. And indeed perhaps we shouldn't, if the goal is to have every user verify everything even if they don't care and don't want to.\n\n[quoted text omitted]\nBetween the current reality of hardly anyone using AssumeUTXO, and the scenario you're describing, I think many decades will pass. By 2050 the blockchain might be 4 TB. The worst case UTXO set growth by then is 3+ TB, but at the current trend it might only be 35 GB.\n\n100x less stuff to download (and process) creates a strong incentive for new users to use a client that _does_ offer AssumeUTXO. It's a similar dynamic as with RBF: there's a limit to how far we can push against individual incentives to achieve network health. That goes for miner and for (non-miner) user incentives.\n\nAlso note that a user who didn't fully validate from genesis is still useful to the network if they provide mempool and (compact) block relay.\n\nThe big unpredictable factor here is Moore's law. In the optimistic scenario you'll download 4 TB in a few minutes in even the poorest and remote places on Earth. In a worst case scenario of technological regression, with a few quantum computers still surviving so we can't use compact signatures, everyone will just be using SPV or custodial wallets, because even after IBD keeping up with the chain would be too much.\n\n@l0rinc wrote:\n\n[quoted text omitted]\nI'm fine with refactoring things towards a cleaner approach, but it's not realistic to expect that if we remove this, it's going to come back. I'm also not convinced that the feature is so problematic that it needs to be temporarily removed. Even UPnP wasn't removed, merely disabled by default after the RCE vulnerabilities, but AssumeUTXO is already opt-in (and should stay that way).",
   "id": "c:6379989317",
   "url": "https://github.com/bitcoin/bitcoin/pull/36598#issuecomment-6379989317",
   "hash": "d4e568782f1483af",
   "edited": "2026-10-24T04:46:29Z"
  }
 ],
 "labels_log": [
  {
   "t": "2026-10-22T08:54:25Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-10-22T12:08:22Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-10-26T20:52:57Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 22732,
 "text_tokens_estimate": 5683,
 "changed_paths": [
  "ci/test/03_test_script.sh",
  "doc/assumeutxo.md",
  "doc/design/assumeutxo.md",
  "doc/release-notes-remove-assumeutxo.md",
  "doc/release-process.md",
  "doc/zmq.md",
  "src/CMakeLists.txt",
  "src/bench/wallet_create_tx.cpp",
  "src/chain.h",
  "src/coins.cpp",
  "src/coins.h",
  "src/external_signer.cpp",
  "src/index/base.cpp",
  "src/index/base.h",
  "src/init.cpp",
  "src/interfaces/chain.h",
  "src/kernel/CMakeLists.txt",
  "src/kernel/bitcoinkernel.cpp",
  "src/kernel/bitcoinkernel.h",
  "src/kernel/chain.cpp",
  "src/kernel/chain.h",
  "src/kernel/chainparams.cpp",
  "src/kernel/chainparams.h",
  "src/kernel/coinstats.cpp",
  "src/kernel/types.h",
  "src/net.h",
  "src/net_processing.cpp",
  "src/node/blockstorage.cpp",
  "src/node/blockstorage.h",
  "src/node/chainstate.cpp",
  "src/node/interfaces.cpp",
  "src/node/utxo_snapshot.cpp",
  "src/node/utxo_snapshot.h",
  "src/policy/fees/mempool_estimator.cpp",
  "src/rpc/blockchain.cpp",
  "src/rpc/blockchain.h",
  "src/test/baseindex_tests.cpp",
  "src/test/chainstate_write_tests.cpp",
  "src/test/coins_tests.cpp",
  "src/test/coinsviewoverlay_tests.cpp",
  "src/test/fuzz/CMakeLists.txt",
  "src/test/fuzz/coins_view.cpp",
  "src/test/fuzz/connman.cpp",
  "src/test/fuzz/deserialize.cpp",
  "src/test/fuzz/rpc.cpp",
  "src/test/fuzz/utxo_snapshot.cpp",
  "src/test/kernel/test_kernel.cpp",
  "src/test/util/chainstate.h",
  "src/test/util/mining.cpp",
  "src/test/util/mining.h",
  "src/test/util/setup_common.cpp",
  "src/test/util/setup_common.h",
  "src/test/util/validation.cpp",
  "src/test/util/validation.h",
  "src/test/validation_block_tests.cpp",
  "src/test/validation_chainstate_tests.cpp",
  "src/test/validation_chainstatemanager_tests.cpp",
  "src/test/validation_flush_tests.cpp",
  "src/test/validation_tests.cpp",
  "src/txdb.cpp",
  "src/txdb.h",
  "src/util/vector.h",
  "src/validation.cpp",
  "src/validation.h",
  "src/validationinterface.cpp",
  "src/validationinterface.h",
  "src/wallet/imports.cpp",
  "src/wallet/rpc/transactions.cpp",
  "src/wallet/wallet.cpp",
  "src/wallet/wallet.h",
  "src/zmq/zmqnotificationinterface.cpp",
  "src/zmq/zmqnotificationinterface.h",
  "test/functional/feature_assumeutxo.py",
  "test/functional/feature_assumeutxo_compat.py",
  "test/functional/feature_init.py",
  "test/functional/rpc_blockchain.py",
  "test/functional/rpc_dumptxoutset.py",
  "test/functional/test_framework/test_framework.py",
  "test/functional/test_runner.py",
  "test/functional/tool_bitcoin_chainstate.py",
  "test/functional/wallet_assumeutxo.py",
  "test/lint/lint-circular-dependencies.py"
 ],
 "files": [
  {
   "path": "ci/test/03_test_script.sh",
   "add": 1,
   "del": 1
  },
  {
   "path": "doc/assumeutxo.md",
   "add": 0,
   "del": 85
  },
  {
   "path": "doc/design/assumeutxo.md",
   "add": 0,
   "del": 127
  },
  {
   "path": "doc/release-notes-remove-assumeutxo.md",
   "add": 16,
   "del": 0
  },
  {
   "path": "doc/release-process.md",
   "add": 0,
   "del": 2
  },
  {
   "path": "doc/zmq.md",
   "add": 4,
   "del": 6
  },
  {
   "path": "src/CMakeLists.txt",
   "add": 0,
   "del": 1
  },
  {
   "path": "src/bench/wallet_create_tx.cpp",
   "add": 1,
   "del": 3
  },
  {
   "path": "src/chain.h",
   "add": 6,
   "del": 17
  },
  {
   "path": "src/coins.cpp",
   "add": 0,
   "del": 10
  },
  {
   "path": "src/coins.h",
   "add": 2,
   "del": 16
  },
  {
   "path": "src/external_signer.cpp",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/index/base.cpp",
   "add": 3,
   "del": 25
  },
  {
   "path": "src/index/base.h",
   "add": 5,
   "del": 10
  },
  {
   "path": "src/init.cpp",
   "add": 13,
   "del": 46
  },
  {
   "path": "src/interfaces/chain.h",
   "add": 2,
   "del": 10
  },
  {
   "path": "src/kernel/CMakeLists.txt",
   "add": 0,
   "del": 1
  },
  {
   "path": "src/kernel/bitcoinkernel.cpp",
   "add": 8,
   "del": 9
  },
  {
   "path": "src/kernel/bitcoinkernel.h",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/kernel/chain.cpp",
   "add": 0,
   "del": 14
  },
  {
   "path": "src/kernel/chain.h",
   "add": 0,
   "del": 4
  },
  {
   "path": "src/kernel/chainparams.cpp",
   "add": 0,
   "del": 154
  },
  {
   "path": "src/kernel/chainparams.h",
   "add": 0,
   "del": 42
  },
  {
   "path": "src/kernel/coinstats.cpp",
   "add": 1,
   "del": 12
  },
  {
   "path": "src/kernel/types.h",
   "add": 0,
   "del": 30
  },
  {
   "path": "src/net.h",
   "add": 2,
   "del": 9
  },
  {
   "path": "src/net_processing.cpp",
   "add": 7,
   "del": 109
  },
  {
   "path": "src/node/blockstorage.cpp",
   "add": 48,
   "del": 144
  },
  {
   "path": "src/node/blockstorage.h",
   "add": 6,
   "del": 58
  },
  {
   "path": "src/node/chainstate.cpp",
   "add": 94,
   "del": 186
  },
  {
   "path": "src/node/interfaces.cpp",
   "add": 4,
   "del": 11
  },
  {
   "path": "src/node/utxo_snapshot.cpp",
   "add": 0,
   "del": 94
  },
  {
   "path": "src/node/utxo_snapshot.h",
   "add": 0,
   "del": 136
  },
  {
   "path": "src/policy/fees/mempool_estimator.cpp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/rpc/blockchain.cpp",
   "add": 43,
   "del": 216
  },
  {
   "path": "src/rpc/blockchain.h",
   "add": 0,
   "del": 14
  },
  {
   "path": "src/test/baseindex_tests.cpp",
   "add": 1,
   "del": 4
  },
  {
   "path": "src/test/chainstate_write_tests.cpp",
   "add": 2,
   "del": 4
  },
  {
   "path": "src/test/coins_tests.cpp",
   "add": 3,
   "del": 24
  },
  {
   "path": "src/test/coinsviewoverlay_tests.cpp",
   "add": 8,
   "del": 4
  },
  {
   "path": "src/test/fuzz/CMakeLists.txt",
   "add": 0,
   "del": 1
  },
  {
   "path": "src/test/fuzz/coins_view.cpp",
   "add": 5,
   "del": 9
  },
  {
   "path": "src/test/fuzz/connman.cpp",
   "add": 0,
   "del": 16
  },
  {
   "path": "src/test/fuzz/deserialize.cpp",
   "add": 0,
   "del": 7
  },
  {
   "path": "src/test/fuzz/rpc.cpp",
   "add": 1,
   "del": 2
  },
  {
   "path": "src/test/fuzz/utxo_snapshot.cpp",
   "add": 0,
   "del": 235
  },
  {
   "path": "src/test/kernel/test_kernel.cpp",
   "add": 7,
   "del": 0
  },
  {
   "path": "src/test/util/chainstate.h",
   "add": 0,
   "del": 139
  },
  {
   "path": "src/test/util/mining.cpp",
   "add": 0,
   "del": 37
  },
  {
   "path": "src/test/util/mining.h",
   "add": 0,
   "del": 4
  },
  {
   "path": "src/test/util/setup_common.cpp",
   "add": 3,
   "del": 9
  },
  {
   "path": "src/test/util/setup_common.h",
   "add": 0,
   "del": 5
  },
  {
   "path": "src/test/util/validation.cpp",
   "add": 2,
   "del": 8
  },
  {
   "path": "src/test/util/validation.h",
   "add": 1,
   "del": 2
  },
  {
   "path": "src/test/validation_block_tests.cpp",
   "add": 1,
   "del": 3
  },
  {
   "path": "src/test/validation_chainstate_tests.cpp",
   "add": 0,
   "del": 126
  },
  {
   "path": "src/test/validation_chainstatemanager_tests.cpp",
   "add": 7,
   "del": 750
  },
  {
   "path": "src/test/validation_flush_tests.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/test/validation_tests.cpp",
   "add": 0,
   "del": 23
  },
  {
   "path": "src/txdb.cpp",
   "add": 18,
   "del": 35
  },
  {
   "path": "src/txdb.h",
   "add": 4,
   "del": 9
  },
  {
   "path": "src/util/vector.h",
   "add": 0,
   "del": 13
  },
  {
   "path": "src/validation.cpp",
   "add": 113,
   "del": 1177
  },
  {
   "path": "src/validation.h",
   "add": 22,
   "del": 325
  },
  {
   "path": "src/validationinterface.cpp",
   "add": 6,
   "del": 9
  },
  {
   "path": "src/validationinterface.h",
   "add": 6,
   "del": 10
  },
  {
   "path": "src/wallet/imports.cpp",
   "add": 0,
   "del": 4
  },
  {
   "path": "src/wallet/rpc/transactions.cpp",
   "add": 0,
   "del": 4
  },
  {
   "path": "src/wallet/wallet.cpp",
   "add": 3,
   "del": 17
  },
  {
   "path": "src/wallet/wallet.h",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/zmq/zmqnotificationinterface.cpp",
   "add": 1,
   "del": 7
  },
  {
   "path": "src/zmq/zmqnotificationinterface.h",
   "add": 1,
   "del": 1
  },
  {
   "path": "test/functional/feature_assumeutxo.py",
   "add": 0,
   "del": 821
  },
  {
   "path": "test/functional/feature_assumeutxo_compat.py",
   "add": 125,
   "del": 0
  },
  {
   "path": "test/functional/feature_init.py",
   "add": 35,
   "del": 1
  },
  {
   "path": "test/functional/rpc_blockchain.py",
   "add": 0,
   "del": 3
  },
  {
   "path": "test/functional/rpc_dumptxoutset.py",
   "add": 15,
   "del": 2
  },
  {
   "path": "test/functional/test_framework/test_framework.py",
   "add": 0,
   "del": 3
  },
  {
   "path": "test/functional/test_runner.py",
   "add": 1,
   "del": 2
  },
  {
   "path": "test/functional/tool_bitcoin_chainstate.py",
   "add": 7,
   "del": 44
  },
  {
   "path": "test/functional/wallet_assumeutxo.py",
   "add": 0,
   "del": 288
  },
  {
   "path": "test/lint/lint-circular-dependencies.py",
   "add": 0,
   "del": 2
  }
 ],
 "test_lines": 2810,
 "git": {
  "head": "bc62b59b8d631133e307a88c267749917e195860",
  "head_matches_backup": true,
  "base": "de96f3ae6d163e97a2cf29bbd7c2bf2d56e11019",
  "patch_id": "181b0f1817885a55",
  "commits": [
   {
    "sha": "1c62336903",
    "subject": "test: avoid snapshot insertion in coin fixtures",
    "files": 2,
    "add": 10,
    "del": 6
   },
   {
    "sha": "6d3f3c2852",
    "subject": "test: prepare coverage for AssumeUTXO removal",
    "files": 2,
    "add": 22,
    "del": 1
   },
   {
    "sha": "d72e3a7333",
    "subject": "validation: stop background cache reprioritization",
    "files": 3,
    "add": 4,
    "del": 41
   },
   {
    "sha": "05f043e63e",
    "subject": "rpc: remove background validation progress",
    "files": 3,
    "add": 1,
    "del": 48
   },
   {
    "sha": "cc4ba39fe9",
    "subject": "wallet: remove background progress hints",
    "files": 4,
    "add": 10,
    "del": 24
   },
   {
    "sha": "d084a285cc",
    "subject": "index: stop following the historical chainstate",
    "files": 7,
    "add": 27,
    "del": 70
   },
   {
    "sha": "46f5f90c04",
    "subject": "validation: stop historical synchronization",
    "files": 12,
    "add": 119,
    "del": 234
   },
   {
    "sha": "ba09b96c9a",
    "subject": "validation: delete historical activation callers",
    "files": 3,
    "add": 8,
    "del": 98
   },
   {
    "sha": "436d2ec197",
    "subject": "validation: delete background completion",
    "files": 5,
    "add": 14,
    "del": 474
   },
   {
    "sha": "e5ac899739",
    "subject": "rpc: stop new snapshot imports",
    "files": 12,
    "add": 24,
    "del": 1282
   },
   {
    "sha": "060ea8908b",
    "subject": "net: drop mutable AssumeUTXO service flags",
    "files": 2,
    "add": 2,
    "del": 25
   },
   {
    "sha": "ad4cefb50f",
    "subject": "validation: reject legacy snapshot startup",
    "files": 23,
    "add": 212,
    "del": 1280
   },
   {
    "sha": "a9ce3d5d6c",
    "subject": "rpc: require an explicit UTXO rollback target",
    "files": 3,
    "add": 7,
    "del": 8
   },
   {
    "sha": "52ee1d9a16",
    "subject": "chainparams: remove AssumeUTXO commitments",
    "files": 2,
    "add": 0,
    "del": 142
   },
   {
    "sha": "d8b0ddc02f",
    "subject": "validation: drop snapshot chain restrictions",
    "files": 2,
    "add": 0,
    "del": 15
   },
   {
    "sha": "95fd82307d",
    "subject": "validation: load only the active chainstate",
    "files": 4,
    "add": 66,
    "del": 158
   },
   {
    "sha": "d5c7d02f56",
    "subject": "validation: delete AssumeUTXO coin loading",
    "files": 6,
    "add": 1,
    "del": 464
   },
   {
    "sha": "69a90c6644",
    "subject": "coins: delete AssumeUTXO insertion bypass",
    "files": 4,
    "add": 4,
    "del": 49
   },
   {
    "sha": "9880f12c59",
    "subject": "validation: delete obsolete cache resizing",
    "files": 10,
    "add": 7,
    "del": 211
   },
   {
    "sha": "e749dc5bdd",
    "subject": "node: delete AssumeUTXO directory metadata",
    "files": 8,
    "add": 2,
    "del": 146
   },
   {
    "sha": "c824984cd3",
    "subject": "validation: remove AssumeUTXO index exceptions",
    "files": 1,
    "add": 61,
    "del": 132
   },
   {
    "sha": "9cf0eaa0b7",
    "subject": "node: load block counts without AssumeUTXO",
    "files": 9,
    "add": 23,
    "del": 129
   },
   {
    "sha": "f3d6b9f3cb",
    "subject": "node: use one block-file cursor and prune budget",
    "files": 4,
    "add": 26,
    "del": 157
   },
   {
    "sha": "d08f939dc3",
    "subject": "wallet: use ordinary block availability checks",
    "files": 4,
    "add": 2,
    "del": 18
   },
   {
    "sha": "48c5977694",
    "subject": "refactor: drop AssumeUTXO notification roles",
    "files": 24,
    "add": 48,
    "del": 175
   },
   {
    "sha": "ce6993c4f3",
    "subject": "refactor: use the ordinary chainstate accessors",
    "files": 5,
    "add": 8,
    "del": 108
   },
   {
    "sha": "8372144e28",
    "subject": "validation: retain one ordinary chainstate",
    "files": 7,
    "add": 47,
    "del": 141
   },
   {
    "sha": "19a40435cc",
    "subject": "rpc: remove snapshot metadata decoding",
    "files": 4,
    "add": 2,
    "del": 84
   },
   {
    "sha": "bbdaa554a7",
    "subject": "node: initialize one chainstate in one pass",
    "files": 3,
    "add": 27,
    "del": 47
   },
   {
    "sha": "646997a903",
    "subject": "txdb: own the coins database directly",
    "files": 6,
    "add": 27,
    "del": 27
   },
   {
    "sha": "f5f80498b0",
    "subject": "net: use one block download path",
    "files": 1,
    "add": 4,
    "del": 42
   },
   {
    "sha": "7c084b9070",
    "subject": "node: prune using a single upper height",
    "files": 4,
    "add": 21,
    "del": 38
   },
   {
    "sha": "701ada3a74",
    "subject": "validation: drop chainstate selection locking",
    "files": 5,
    "add": 7,
    "del": 19
   },
   {
    "sha": "824d0fb577",
    "subject": "validation: drop chainstate identity diagnostics",
    "files": 5,
    "add": 7,
    "del": 20
   },
   {
    "sha": "bc62b59b8d",
    "subject": "rpc: keep UTXO export serialization local",
    "files": 3,
    "add": 24,
    "del": 84
   }
  ],
  "patch_truncated": true
 },
 "patch_id": "181b0f1817885a55",
 "input_hash": "5bdec6457c8527d9",
 "extracted_at": "2026-11-02T01:09:49+00:00"
}