{
 "number": 33117,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/33117",
 "title": "Interfaces: Expose UTXO Snapshot Loading and Add Progress Notifications",
 "author": "D33r-Gee",
 "author_association": "FIRST_TIME_CONTRIBUTOR",
 "created_at": "2025-08-01T15:31:46Z",
 "updated_at": "2026-09-09T16:36:28Z",
 "age_days": 412,
 "draft": false,
 "labels": [
  "Needs rebase",
  "IPC"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "c765d9fa113f032c0f6fa54369e3add1a7edcb38",
 "head_ref": "interface-load-snapshot",
 "head_repo": "D33r-Gee/bitcoin",
 "head_history": [
  {
   "t": "2025-08-04T16:15:06Z",
   "sha": "e79c50cea2096e4d4bf018d2672b94d8c2bc959a"
  },
  {
   "t": "2025-08-06T14:57:36Z",
   "sha": "8bc4035570acfe512c756c6de30d6440d322d514"
  },
  {
   "t": "2025-09-15T16:28:17Z",
   "sha": "30d9bdb77324d234d4aacd155075b4dfc00930c7"
  },
  {
   "t": "2025-09-15T22:02:41Z",
   "sha": "94d68d12a6c19060a4c2447a414f51049906f965"
  },
  {
   "t": "2025-09-16T14:35:44Z",
   "sha": "668f98edb7a218e23100aa1a6adf6841cd281a41"
  },
  {
   "t": "2025-11-19T18:24:06Z",
   "sha": "36ae2effba30f6806a6171fa6a8018fde5215302"
  },
  {
   "t": "2025-11-19T23:22:51Z",
   "sha": "d0c32c28e59d3076100bf4c12d94f8b2d4060943"
  },
  {
   "t": "2026-02-25T18:14:34Z",
   "sha": "8c932ff59f58ee2f39a58cbeeaf8c16722c8c272"
  },
  {
   "t": "2026-03-31T16:28:56Z",
   "sha": "34e536d42529ac6f4b70b1802ce709282de2e28a"
  },
  {
   "t": "2026-04-09T19:34:41Z",
   "sha": "9dbfdf81caff7cab40db94be9553601eacffd63c"
  },
  {
   "t": "2026-04-13T18:57:35Z",
   "sha": "9dab30ad3d82567e60a18d7a657f0420d604b04f"
  },
  {
   "t": "2026-04-21T18:37:49Z",
   "sha": "328fef6bae4007cb3903c6d2b5653f91c9bf14be"
  },
  {
   "t": "2026-06-02T17:18:55Z",
   "sha": "af0c25311f084217e43502dd8f7081b7a77ab44a"
  },
  {
   "t": "2026-06-10T16:47:57Z",
   "sha": "8c435b5a000cfd0016c09bda5e14043f4127a0ab"
  },
  {
   "t": "2026-08-11T17:25:35Z",
   "sha": "5142e2e8fe1c22c6bcc095854b80afc389ead55a"
  },
  {
   "t": "2026-08-21T22:27:23Z",
   "sha": "486e6d72000f90eb2431d026dc639a7b3169872c"
  },
  {
   "t": "2026-08-27T15:27:55Z",
   "sha": "c765d9fa113f032c0f6fa54369e3add1a7edcb38"
  }
 ],
 "additions": 129,
 "deletions": 21,
 "changed_files": 10,
 "commit_count": 3,
 "size_bucket": "M",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "approach_ack": [
     {
      "login": "sedited",
      "url": "https://github.com/bitcoin/bitcoin/pull/33117#issuecomment-3265507664"
     }
    ],
    "stale_ack": [
     {
      "login": "pinheadmz",
      "url": "https://github.com/bitcoin/bitcoin/pull/33117#pullrequestreview-3683920243"
     }
    ]
   },
   "conflicts": [
    {
     "number": 36167,
     "title": "[RFC] Enable `-Wunused`",
     "author": "fanquake"
    },
    {
     "number": 36116,
     "title": "iwyu: Fix warnings in `src/rpc` and treat them as errors",
     "author": "hebasto"
    },
    {
     "number": 35675,
     "title": "mining: add block template manager",
     "author": "ismaelsadeeq"
    }
   ]
  }
 },
 "acks_parsed": {
  "pinheadmz": {
   "kind": "ack",
   "hash": null,
   "t": "2026-01-20T20:32:08Z",
   "stale": true
  },
  "sedited": {
   "kind": "approach_ack",
   "hash": null,
   "t": "2025-09-08T09:54:01Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 1,
  "concept_ack": 0,
  "approach_ack": 1,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "Sjors",
   "fanquake",
   "pinheadmz",
   "ryanofsky",
   "sedited"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-08-27T15:29:49Z",
  "last_reviewer_activity": "2026-08-10T20:25:34Z",
  "last_reviewer": "sedited",
  "author_silent_days": 21,
  "waiting_on_author_days": 0,
  "days_since_update": 7
 },
 "refs": {
  "mentioned": [
   10102,
   30267,
   30395
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 30267,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2024-07-02",
    "title": "assumeutxo: Check snapshot base block is not in invalid chain"
   },
   {
    "number": 30395,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2024-07-09",
    "title": "rpc: Use untranslated error strings in loadtxoutset"
   },
   {
    "number": 10102,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Multiprocess bitcoin"
   }
  ],
  "conflicts": [
   36167,
   36116,
   35675
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/interfaces/node.h",
  "src/interfaces/snapshot.h",
  "src/node/interfaces.cpp",
  "src/rpc/blockchain.cpp",
  "src/validation.cpp"
 ],
 "body": "# Add UTXO Snapshot Loading Interface and Progress Notifications\n\nThis PR implements a complete interface for loading UTXO snapshots through the GUI, including progress notifications to provide user feedback during the loading process.\n\n---\n\n## Changes\n\n### Commit 1: interfaces: expose UTXO snapshot functionality (loading/activate) in node interface\n\n- Added a new virtual method `snapshot` to the node interface for loading UTXO snapshots from a path.\n- Added `snapshot.h` to `src/interfaces` defining the Snapshot interface; `activate()` returns `util::Result<const CBlockIndex*>` to   carry either the base block index on success or a descriptive error message on failure, matching the shape of `ChainstateManager::ActivateSnapshot()`.\n- Added a `getMetadata` accessor so callers can read snapshot metadata populated during activation without re-parsing the file.\n- Added `SnapshotImpl` in src/node/interfaces.cpp: opens the snapshot file, parses metadata, and forwards to `ChainstateManager::ActivateSnapshot()`, propagating any error as util::Error{...}.\n\nThis change enhances the user's ability to load UTXO snapshots through the GUI and/or RPC.\n\n### Commit 2: `notifications: Implement snapshot load progress notifications`\n\n- Added a new signal `SnapshotLoadProgress` for snapshot load progress in the UI interface.\n- Updated the notifications interface to include a method for reporting snapshot loading progress.\n- Enhanced the `ChainstateManager` to report progress during snapshot loading.\n- Implemented the necessary handler in the kernel notifications to relay progress updates.\n\nThis change improves user feedback during the snapshot loading process.\n\n### Commit 3: `rpc: refactor loadtxoutset to use snapshot interface`\n\n- Updated the `loadtxoutset` RPC to call the new snapshot interface instead of directly working with chainstate internals. File opening, metadata parsing, and activation now all happen inside `interfaces::Snapshot::activate()` rather than being split between the RPC handler and the interface.\n- Removed the redundant pre-parse block in the RPC handler; its file-open and metadata-parse work duplicated what activate() already performs.\n- Collapsed the RPC error handling to a single `RPC_INTERNAL_ERROR` built from `util::ErrorString(activation_result).original`, using the `\"Unable to load UTXO snapshot: %s. (%s)\"` format established in #30267 / #30395.\n- Read `coins_loaded` from `snapshot->getMetadata()` after `activate()` populates it.\n- Updated `feature_assumeutxo.py` to assert on the unified error code for file-open and metadata-parse failures (message substrings unchanged).\nImproves modularity by consolidating snapshot handling through the interface layer.\n---\n\n## Technical Details\n\nThe implementation includes:\n\n- **UI Interface Enhancement**\n  Added `SnapshotLoadProgress` signal to `CClientUIInterface` with corresponding signal declaration and implementation.\n\n- **Node Interface**\n  Added `loadSnapshot` virtual method to the node interface with implementation in `interfaces.cpp`.\n\n- **Progress Notifications**\n  Implemented `snapshotLoadProgress` method in `KernelNotifications` class to relay progress updates to the UI.\n\n- **Base Interface**\n  Added `snapshotLoadProgress` virtual method to the kernel notifications interface.\n\n---\n\n## Benefits\n\n- **User Experience**\n  Provides real-time feedback during UTXO snapshot loading operations.\n\n- **GUI Integration**\n  Enables loading UTXO snapshots directly through the Bitcoin Core GUI.\n\n- **Progress Tracking**\n  Users can monitor the progress of snapshot loading operations.\n\n- **Consistent Interface**\n  Follows the existing pattern for progress notifications in the codebase.\n\n## Testing\n\n- **Daemon** build and launch `bitcoind` then with `bitcoin-cli` load a snapshot using:\n```bash\n./bitcoin-cli -rpcclienttimeout=0 -signet loadtxoutset /path/to/utxo-snapsshot.dat\n```\n- **QT Widgets**: build and run [this](https://github.com/bitcoin-core/gui/pull/870) draft PR in legacy gui repo\n- **QML** version: for a modern look build and run [this](https://github.com/bitcoin-core/gui-qml/pull/488) PR in the newly updated gui-qml repo",
 "commits": [
  {
   "sha": "1d4552b8549b450b449f02c72c603735adb3b3fa",
   "date": "2026-08-27T15:15:23Z",
   "message": "interfaces: expose UTXO snapshot functionality (loading/activate) in node interface\n\n- Added a new virtual method `snapshot` to the node interface for loading UTXO snapshots.\n- Added `snapshot.h` to src/interfaces defining the Snapshot interface. `activate()`\n  returns `util::Result<const CBlockIndex*>` to carry either the base block index\n  on success or a descriptive error message on failure, matching the shape of\n  `ChainstateManager::ActivateSnapshot()`.\n- Added a `getMetadata` accessor so callers can read snapshot metadata populated\n  during activation without re-parsing the file.\n- Added `SnapshotImpl` in src/node/interfaces.cpp: opens the snapshot file,\n  parses metadata, and forwards to `ChainstateManager::ActivateSnapshot()`,\n  propagating any error as `util::Error{...}`.\n\nThis change enhances the user ability to load utxo snapshots through the GUI and/or RPC."
  },
  {
   "sha": "3c362b1843599adba5d39d9e502592aa0b535156",
   "date": "2026-08-27T15:16:51Z",
   "message": "notifications: Implement snapshot load progress notifications\n\n- Added a new signal for snapshot load progress in the UI interface.\n- Updated the notifications interface to include a method for reporting snapshot loading progress.\n- Enhanced the ChainstateManager to report progress during snapshot loading.\n- Implemented the necessary handler in the kernel notifications to relay progress updates.\n\nThis change improves user feedback during the snapshot loading process."
  },
  {
   "sha": "c765d9fa113f032c0f6fa54369e3add1a7edcb38",
   "date": "2026-08-27T15:16:51Z",
   "message": "rpc: Refactor loadtxoutset to utilize new node interface for UTXO snapshot loading\n\n- Updated the loadtxoutset function to use the new node interface for loading\n  UTXO snapshots. File opening, metadata parsing, and activation now all happen\n  inside `interfaces::Snapshot::activate()` rather than being split between the\n  RPC handler and the interface.\n- Replaced direct file handling with snapshot activation through the node\n  interface. The previous pre-parse block in the RPC handler was redundant\n  with the equivalent work already performed inside `activate()`.\n- Collapsed the RPC error handling to a single `RPC_INTERNAL_ERROR` built from\n  `util::ErrorString(activation_result).original`, matching the convention\n  established in #30267 / #30395.\n- Enhanced the result object to correctly reference metadata from the snapshot\n  via `snapshot->getMetadata()`.\n- Updated `feature_assumeutxo.py` to assert on the unified error code for\n  file-open and metadata-parse failures.\n\nThis change streamlines the UTXO snapshot loading process and leverages the new interface capabilities."
  }
 ],
 "timeline": [
  {
   "t": "2025-08-01T18:41:49Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "I plan to test this soon(tm)."
  },
  {
   "t": "2025-08-01T20:54:07Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "[quoted text omitted]\n\nThanks @Sjors !"
  },
  {
   "t": "2025-08-01T22:00:16Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/interfaces/node.h",
   "commit": "668f98edb7a218e23100aa1a6adf6841cd281a41",
   "in_reply_to": null,
   "text": "In commit \"interfaces: expose UTXO snapshot loading in node interface\" (de11e3b89f8aba9a90a3419086807e5fee0f941d)\n\nNote with #10102 if the GUI & node are running in separate processes, it could be a awkward for the gui process to create an AutoFile object and pass it to the node like this. Technically it could probably work: the AutoFile could be passed as a file descriptor or a (path, position) tuple. But it doesn't seem like a clean separation of responsibilities if the GUI process is reading the beginning of the snapshot file and the node process is reading the rest of the file.\n\nProbably current interface is ok, but it might be more ideal if node provided a more generic `loadSnapshot` method and the GUI didn't directly access the file:\n\n```c++\nclass Node\n{\n    // ...\n    std::unique_ptr<Snapshot> loadSnapshot(const fs::path& path) = 0;\n    // ...\n};\n\nclass Snapshot\n{\npublic:\n    virtual ~Snapshot() = default;\n    node::SnapshotMetadata getMetadata() = 0;\n    bool activate() = 0;\n};\n```"
  },
  {
   "t": "2025-08-01T23:35:18Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/interfaces/node.h",
   "commit": "668f98edb7a218e23100aa1a6adf6841cd281a41",
   "in_reply_to": 2248934018,
   "text": "Thanks for the review... will update soon addressing this"
  },
  {
   "t": "2025-08-04T16:15:06Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "e79c50cea2096e4d4bf018d2672b94d8c2bc959a"
  },
  {
   "t": "2025-08-04T16:24:04Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/interfaces/node.h",
   "commit": "668f98edb7a218e23100aa1a6adf6841cd281a41",
   "in_reply_to": 2248934018,
   "text": "with [e79c50c](https://github.com/bitcoin/bitcoin/commit/e79c50cea2096e4d4bf018d2672b94d8c2bc959a) updated the `node.h` and added `snapshot.h` to the `/interfaces`.\nAlso updated `interfaces.cpp` with a `SnapshotImpl` class to process the path and extracts the metada and activate the snapshot.\n@ryanofsky let me know if that's what you had in mind?"
  },
  {
   "t": "2025-08-04T16:46:19Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/interfaces/node.h",
   "commit": "668f98edb7a218e23100aa1a6adf6841cd281a41",
   "in_reply_to": 2248934018,
   "text": "re: https://github.com/bitcoin/bitcoin/pull/33117#discussion_r2249012242\n\nThanks! I think b464f388197c5c31937d309d817d38c4b4849a91 is an improvement over previous de11e3b89f8aba9a90a3419086807e5fee0f941d because it passes an `fs::path` argument from the GUI to the node instead of an `AutoFile` file argument. This is nice because it lets node be fully responsible for parsing the snapshot file instead of relying on the GUI.\n\nOne comment on b464f388197c5c31937d309d817d38c4b4849a91 is that it looks like the Snapshot class is not actually necessary in its current form. The reason I suggested adding a Snapshot class above was that I thought GUI wanted to display SnapshotMetadata information before activating the snapshot, and a Snapshot class could provide separate getMetadata() and activate() methods to allow that. But since the Snapshot class only has a single activate() method in b464f388197c5c31937d309d817d38c4b4849a91, it looks like the class is unnecessary, and you could just have a plain `Node::activateSnapshot(fs::path)` method that returns bool instead of a Snapshot.\n\nAny approach is fine though, so you should choose whatever seems to make the most sense."
  },
  {
   "t": "2025-08-05T14:37:23Z",
   "kind": "comment",
   "who": "pinheadmz",
   "assoc": "MEMBER",
   "text": "concept ACK, tested the mainnet snapshot load with the QML gui branch built on top of this"
  },
  {
   "t": "2025-08-06T13:09:56Z",
   "kind": "comment",
   "who": "fanquake",
   "assoc": "MEMBER",
   "text": "https://github.com/bitcoin/bitcoin/actions/runs/16728433539/job/47504424705?pr=33117#step:10:445:\n```bash\nD:\\a\\bitcoin\\bitcoin\\src\\node\\interfaces.cpp(115,40): error C2220: the following warning is treated as an error [D:\\a\\bitcoin\\bitcoin\\build\\src\\bitcoin_node.vcxproj]\nD:\\a\\bitcoin\\bitcoin\\src\\node\\interfaces.cpp(115,40): warning C4101: 'e': unreferenced local variable [D:\\a\\bitcoin\\bitcoin\\build\\src\\bitcoin_node.vcxproj]\n```"
  },
  {
   "t": "2025-08-06T14:57:36Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "8bc4035570acfe512c756c6de30d6440d322d514"
  },
  {
   "t": "2025-08-06T15:23:44Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/interfaces/node.h",
   "commit": "668f98edb7a218e23100aa1a6adf6841cd281a41",
   "in_reply_to": 2248934018,
   "text": "Thanks for taking a look!\nRE:\n\n[quoted text omitted]\nI took some time to test various scenarios downstream in the `gui-qml` project. While we aren't directly utilizing the snapshot data at the moment, I believe your initial instincts about introducing a `Snapshot` class were well-founded. This abstraction will become increasingly valuable as we begin to expose the dump/generate snapshot functionalities trough the GUI."
  },
  {
   "t": "2025-08-07T16:48:53Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "with [8bc4035](https://github.com/bitcoin/bitcoin/commit/8bc4035570acfe512c756c6de30d6440d322d514) it has been rebased and the fuzzing CI error has been addressed"
  },
  {
   "t": "2025-09-08T07:52:58Z",
   "kind": "review_comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "path": "src/node/interfaces.cpp",
   "commit": "668f98edb7a218e23100aa1a6adf6841cd281a41",
   "in_reply_to": null,
   "text": "In 3c8b578836dd0d8438a8aac81a1166df84811562 _interfaces: expose UTXO snapshot loading in node interface_: a good way to add test coverage to this new interface would be to use it in the `loadtxoutset` RPC.\n\nFor an example, see the various uses of `EnsureMining(node);`"
  },
  {
   "t": "2025-09-08T07:57:03Z",
   "kind": "review",
   "who": "Sjors",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "8bc4035570acfe512c756c6de30d6440d322d514",
   "text": "At first glance this looks very reasonable. I also tested it in the (current) GUI with https://github.com/bitcoin-core/gui/pull/870\n\nI had a similar concern as @ryanofsky about how to go about passing the snapshot file (path) over the interface. The current approach in 3c8b578836dd0d8438a8aac81a1166df84811562 is the same as how we handle wallet backups (`restoreWallet`), so probably fine?"
  },
  {
   "t": "2025-09-08T09:54:01Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "Approach ACK"
  },
  {
   "t": "2025-09-08T16:31:52Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/node/interfaces.cpp",
   "commit": "668f98edb7a218e23100aa1a6adf6841cd281a41",
   "in_reply_to": 2329435219,
   "text": "Thanks @Sjors for providing feedback and suggesting to add test coverage via the RPC...\n\nLooking into it now and will update shortly"
  },
  {
   "t": "2025-09-15T16:28:17Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "30d9bdb77324d234d4aacd155075b4dfc00930c7"
  },
  {
   "t": "2025-09-15T16:34:12Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "With [30d9bdb](https://github.com/bitcoin/bitcoin/commit/30d9bdb77324d234d4aacd155075b4dfc00930c7), the `loadtxoutset` RPC command has been refactored to use the snapshot interface, as suggested by @Sjors. Additionally, the interface now includes `getMetadata` and `getActivationResult` methods to ensure parity with the legacy RPC command."
  },
  {
   "t": "2025-09-15T16:36:12Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/node/interfaces.cpp",
   "commit": "668f98edb7a218e23100aa1a6adf6841cd281a41",
   "in_reply_to": 2329435219,
   "text": "[quoted text omitted]\n\nrefactored `loadtxoutset` to utilize the new `snapshot` interface..."
  },
  {
   "t": "2025-09-15T22:02:41Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "94d68d12a6c19060a4c2447a414f51049906f965"
  },
  {
   "t": "2025-09-15T22:13:23Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "with [94d68d1](https://github.com/bitcoin/bitcoin/commit/94d68d12a6c19060a4c2447a414f51049906f965) RPC Error handling has been restored through the interface"
  },
  {
   "t": "2025-09-16T14:35:44Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "668f98edb7a218e23100aa1a6adf6841cd281a41"
  },
  {
   "t": "2025-11-19T18:24:06Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "36ae2effba30f6806a6171fa6a8018fde5215302"
  },
  {
   "t": "2025-11-19T18:25:41Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "with [36ae2ef](https://github.com/bitcoin/bitcoin/commit/36ae2effba30f6806a6171fa6a8018fde5215302) rebased over master.\n\nNo changes to commits..."
  },
  {
   "t": "2025-11-19T23:22:51Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "d0c32c28e59d3076100bf4c12d94f8b2d4060943"
  },
  {
   "t": "2025-11-19T23:24:02Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "with [d0c32c2](https://github.com/bitcoin/bitcoin/commit/d0c32c28e59d3076100bf4c12d94f8b2d4060943) fixed RPC command issue that surfaced after rebase"
  },
  {
   "t": "2026-01-20T19:23:44Z",
   "kind": "review_comment",
   "who": "pinheadmz",
   "assoc": "MEMBER",
   "path": "src/validation.cpp",
   "commit": "d0c32c28e59d3076100bf4c12d94f8b2d4060943",
   "in_reply_to": null,
   "text": "e8aa3a6d43760ffd76c247211f769624a48c8828\n\nThis will fire 100 million times during a mainnet snapshot load. Is that overkill? The log messages for example are reduced by 100x at least."
  },
  {
   "t": "2026-01-20T20:32:08Z",
   "kind": "review",
   "who": "pinheadmz",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "d0c32c28e59d3076100bf4c12d94f8b2d4060943",
   "text": "code review ACK at  d0c32c28e5\n\nThe new interface and signal handlers are fairly straight-forward and follow existing patterns. Consuming the new interface in the `loadtxoutset` RPC ensures it is covered by tests. Corecheck indicates some of the failure cases are not covered by tests, I want to look at that a little closer.\n\nI also plan on going through the flow with both GUIs as well. I think this is an important feature to expose to GUI users, and this is the right way to get there.\n\nOnly one question below so far"
  },
  {
   "t": "2026-01-26T22:18:27Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/validation.cpp",
   "commit": "d0c32c28e59d3076100bf4c12d94f8b2d4060943",
   "in_reply_to": 2709768975,
   "text": "Thanks for reviewing the code... Looking into it now... Will respond shortly. Got some ideas, testing them downstream first ([qt](https://github.com/bitcoin-core/gui/pull/870) and [gui-qml](https://github.com/bitcoin-core/gui-qml/pull/488))"
  },
  {
   "t": "2026-02-25T18:14:34Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "8c932ff59f58ee2f39a58cbeeaf8c16722c8c272"
  },
  {
   "t": "2026-02-25T18:19:26Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/validation.cpp",
   "commit": "d0c32c28e59d3076100bf4c12d94f8b2d4060943",
   "in_reply_to": 2709768975,
   "text": "with [8c932ff](https://github.com/bitcoin/bitcoin/commit/8c932ff59f58ee2f39a58cbeeaf8c16722c8c272) addressed the snapshot load progress notification to batch progress updates for every 100,000 coins processed (and upon completion).\n\nIt was tested downstream in the [qt](https://github.com/bitcoin-core/gui/pull/870) and [qml](https://github.com/bitcoin-core/gui-qml/pull/488))"
  },
  {
   "t": "2026-02-25T18:20:39Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "With [8c932ff](https://github.com/bitcoin/bitcoin/commit/8c932ff59f58ee2f39a58cbeeaf8c16722c8c272) addressed @pinheadmz comment about the loading progress notifications also it has been rebased over master"
  },
  {
   "t": "2026-03-31T16:28:56Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "34e536d42529ac6f4b70b1802ce709282de2e28a"
  },
  {
   "t": "2026-03-31T16:30:55Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "with [34e536d](https://github.com/bitcoin/bitcoin/commit/34e536d42529ac6f4b70b1802ce709282de2e28a) rebased over master"
  },
  {
   "t": "2026-04-09T19:34:41Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "9dbfdf81caff7cab40db94be9553601eacffd63c"
  },
  {
   "t": "2026-04-09T19:36:56Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "with [9dbfdf8](https://github.com/bitcoin/bitcoin/commit/9dbfdf81caff7cab40db94be9553601eacffd63c) it has been rebased over master"
  },
  {
   "t": "2026-04-10T17:22:12Z",
   "kind": "review_comment",
   "who": "pinheadmz",
   "assoc": "MEMBER",
   "path": "src/interfaces/snapshot.h",
   "commit": "740add96ec6149174d69b05cab1088dd7f7dc776",
   "in_reply_to": null,
   "text": "740add96ec6149174d69b05cab1088dd7f7dc776\n\nnit: can remove the year\n`Copyright (c) The Bitcoin Core developers`"
  },
  {
   "t": "2026-04-10T17:29:00Z",
   "kind": "review_comment",
   "who": "pinheadmz",
   "assoc": "MEMBER",
   "path": "src/node/interfaces.cpp",
   "commit": "9dab30ad3d82567e60a18d7a657f0420d604b04f",
   "in_reply_to": null,
   "text": "740add96ec6149174d69b05cab1088dd7f7dc776\n\nSince `m_activation_result` is already an optional I think you can shortcut the logic here?\n\n```cpp\nstd::optional<const CBlockIndex*> getActivationResult() const override\n{\n    return m_activation_result;\n}\n```"
  },
  {
   "t": "2026-04-10T17:42:51Z",
   "kind": "review_comment",
   "who": "pinheadmz",
   "assoc": "MEMBER",
   "path": "src/rpc/blockchain.cpp",
   "commit": "9dbfdf81caff7cab40db94be9553601eacffd63c",
   "in_reply_to": null,
   "text": "9dbfdf81caff7cab40db94be9553601eacffd63c\n\nSeems a little awkward to parse error strings for the sake of RPC errors. I think the generic one you have below on L3431 is fine, and if you want to include the failed path in the error message, it could happen over in `class SnapshotImpl` where the strings are set."
  },
  {
   "t": "2026-04-10T17:44:09Z",
   "kind": "review_comment",
   "who": "pinheadmz",
   "assoc": "MEMBER",
   "path": "src/rpc/blockchain.cpp",
   "commit": "9dbfdf81caff7cab40db94be9553601eacffd63c",
   "in_reply_to": null,
   "text": "9dbfdf81caff7cab40db94be9553601eacffd63c\n\nWould this ever throw? Probably don't need the try/catch"
  },
  {
   "t": "2026-04-10T17:49:09Z",
   "kind": "review_comment",
   "who": "pinheadmz",
   "assoc": "MEMBER",
   "path": "src/rpc/blockchain.cpp",
   "commit": "9dbfdf81caff7cab40db94be9553601eacffd63c",
   "in_reply_to": null,
   "text": "9dbfdf81caff7cab40db94be9553601eacffd63c\n\nThe snapshot is activated (or not) up on line 3419. Will this call to `getActivationResult()` ever be useful after that?"
  },
  {
   "t": "2026-04-10T17:50:05Z",
   "kind": "review",
   "who": "pinheadmz",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "9dbfdf81caff7cab40db94be9553601eacffd63c",
   "text": "code review 9dbfdf81ca\n\nh/t Claude !"
  },
  {
   "t": "2026-04-13T18:57:35Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "9dab30ad3d82567e60a18d7a657f0420d604b04f"
  },
  {
   "t": "2026-04-13T19:11:03Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "with [9dab30a](https://github.com/bitcoin/bitcoin/commit/9dab30ad3d82567e60a18d7a657f0420d604b04f) addressed @pinheadmz comments. Thanks for reviewing!"
  },
  {
   "t": "2026-04-17T19:31:50Z",
   "kind": "review_comment",
   "who": "pinheadmz",
   "assoc": "MEMBER",
   "path": "src/rpc/blockchain.cpp",
   "commit": "9dab30ad3d82567e60a18d7a657f0420d604b04f",
   "in_reply_to": null,
   "text": "I don't understand whats happening here. If the file can't be opened for reading, or metadata can't be parsed, won't that come up in `activate()` on line 3433?"
  },
  {
   "t": "2026-04-21T18:37:49Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "328fef6bae4007cb3903c6d2b5653f91c9bf14be"
  },
  {
   "t": "2026-04-21T18:41:28Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/rpc/blockchain.cpp",
   "commit": "9dab30ad3d82567e60a18d7a657f0420d604b04f",
   "in_reply_to": 3102797827,
   "text": "[quoted text omitted]\n\nThanks for reviewing @pinheadmz and good catch! This led me to revise the approach with the help of Claude.\n\nYou are correct activate() already opens the file and parses metadata internally, so doing it again here was redundant. The only reason these specific RPC_INVALID_PARAMETER / RPC_DESERIALIZATION_ERROR codes were being produced at the RPC layer was to retrofit finer error classification on top of the old bool activate() signature."
  },
  {
   "t": "2026-04-21T18:56:29Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "with [328fef6](https://github.com/bitcoin/bitcoin/commit/328fef6bae4007cb3903c6d2b5653f91c9bf14be) revisited the approach since @pinheadmz exposed redundancy that was already addressed by #30267 and later tighten up with #30395\n\nChainstateManager::ActivateSnapshot still returns util::Result<CBlockIndex*> on master today, but my original approach on this branch's interfaces::Snapshot wrapper was unwrapping that and reducing it back to a bool + getLastError() + getActivationResult() triad, which is why I ended up reintroducing the pre-parse block just to recover error classification.\n\nHere are the new changes introduced:\n\n7406a3efa1cd8b86e621f0af63ea41fbd94b83ff interfaces: expose UTXO snapshot functionality ...\n\ninterfaces::Snapshot::activate() now returns util::Result<const CBlockIndex*> directly, carrying either the snapshot base block index on success or a descriptive error message on failure.\n\ngetActivationResult() and getLastError() are gone \u2014 the result carries both. SnapshotImpl correspondingly loses its m_activation_result / m_last_error members and just forwards ChainstateManager::ActivateSnapshot's result.\n\n328fef6bae4007cb3903c6d2b5653f91c9bf14be rpc: Refactor loadtxoutset ...\n\nThe pre-parse block is deleted. The RPC handler calls activate() once and surfaces any failure via a single RPC_INTERNAL_ERROR with util::ErrorString(activation_result).original, using the same \"Unable to load UTXO snapshot: %s. (%s)\" format merged in #30395.\n\ncoins_loaded is now read from snapshot->getMetadata() after activate() populates it.\n\nfeature_assumeutxo.py is updated in the same commit: since assert_raises_rpc_error is substring-based, only the error codes for file-open (-8 \u2192 -32603) and metadata-parse (-22 \u2192 -32603) had to change; the message assertions still match unchanged."
  },
  {
   "t": "2026-06-01T14:11:30Z",
   "kind": "comment",
   "who": "fanquake",
   "assoc": "MEMBER",
   "text": "Are you still working on this? You should try and respond to review comments inline, so it's clear what has been done/responded to, and what hasn't."
  },
  {
   "t": "2026-06-02T17:18:55Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "af0c25311f084217e43502dd8f7081b7a77ab44a"
  },
  {
   "t": "2026-06-02T17:23:49Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "[quoted text omitted]\n\nYes! Still working on it with [af0c253](https://github.com/bitcoin/bitcoin/commit/af0c25311f084217e43502dd8f7081b7a77ab44a) it has been rebased over master.\n\nWill take some time to add comments inline like you suggested @fanquake"
  },
  {
   "t": "2026-06-02T19:33:41Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/node/interfaces.cpp",
   "commit": "9dab30ad3d82567e60a18d7a657f0420d604b04f",
   "in_reply_to": 3065797335,
   "text": "Addressed in a later refactor([328fef6](https://github.com/bitcoin/bitcoin/commit/328fef6bae4007cb3903c6d2b5653f91c9bf14be)): removed getActivationResult() and the m_activation_result member. activate() now returns util::Result<const CBlockIndex*>, so callers get success/failure and the block index from one call without a separate optional getter."
  },
  {
   "t": "2026-06-02T19:34:56Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/interfaces/snapshot.h",
   "commit": "740add96ec6149174d69b05cab1088dd7f7dc776",
   "in_reply_to": 3065769018,
   "text": "Done..."
  },
  {
   "t": "2026-06-02T19:41:31Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/validation.cpp",
   "commit": "d0c32c28e59d3076100bf4c12d94f8b2d4060943",
   "in_reply_to": 2709768975,
   "text": "Still the case on af0c253"
  },
  {
   "t": "2026-06-02T19:42:32Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/rpc/blockchain.cpp",
   "commit": "9dbfdf81caff7cab40db94be9553601eacffd63c",
   "in_reply_to": 3065863278,
   "text": "Fixed in af0c253: dropped getLastError() and string matching. loadtxoutset only calls activate() and returns a single RPC_INTERNAL_ERROR with util::ErrorString(activation_result).original (same pattern as #30267 / #30395). Path-specific messages come from SnapshotImpl::activate()."
  },
  {
   "t": "2026-06-02T19:43:11Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/rpc/blockchain.cpp",
   "commit": "9dbfdf81caff7cab40db94be9553601eacffd63c",
   "in_reply_to": 3065891952,
   "text": "Agreed! Removed in af0c253. getMetadata() is used directly after a successful activate(); no try/catch around it."
  },
  {
   "t": "2026-06-02T19:43:49Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/rpc/blockchain.cpp",
   "commit": "9dab30ad3d82567e60a18d7a657f0420d604b04f",
   "in_reply_to": 3102797827,
   "text": "Agreed! Removed in af0c253. activate() returns util::Result<const CBlockIndex*>; the RPC uses that result directly and no longer has getActivationResult() or m_activation_result."
  },
  {
   "t": "2026-06-02T19:45:26Z",
   "kind": "review_comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "path": "src/rpc/blockchain.cpp",
   "commit": "9dbfdf81caff7cab40db94be9553601eacffd63c",
   "in_reply_to": 3065868879,
   "text": "Yes! That duplication is gone in af0c253. File open, metadata parse, and activation all live in SnapshotImpl::activate(). The RPC only does snapshot(path) \u2192 activate() \u2192 build the result from getMetadata() on success."
  },
  {
   "t": "2026-06-10T16:47:57Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "8c435b5a000cfd0016c09bda5e14043f4127a0ab"
  },
  {
   "t": "2026-08-10T20:25:34Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "@D33r-Gee can you rebase this?"
  },
  {
   "t": "2026-08-11T16:04:43Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "[quoted text omitted]\n\nYep... Will do so this week..."
  },
  {
   "t": "2026-08-11T17:25:35Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "5142e2e8fe1c22c6bcc095854b80afc389ead55a"
  },
  {
   "t": "2026-08-11T21:32:35Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "with [5142e2e](https://github.com/bitcoin/bitcoin/commit/5142e2e8fe1c22c6bcc095854b80afc389ead55a) it has been rebased over master.\n\nThanks @sedited for the nudge :)"
  },
  {
   "t": "2026-08-21T22:27:23Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "486e6d72000f90eb2431d026dc639a7b3169872c"
  },
  {
   "t": "2026-08-21T22:29:52Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "With [486e6d7](https://github.com/bitcoin/bitcoin/commit/486e6d72000f90eb2431d026dc639a7b3169872c) it has been rebased over master"
  },
  {
   "t": "2026-08-27T15:27:55Z",
   "kind": "force_push",
   "who": "D33r-Gee",
   "commit": "c765d9fa113f032c0f6fa54369e3add1a7edcb38"
  },
  {
   "t": "2026-08-27T15:29:49Z",
   "kind": "comment",
   "who": "D33r-Gee",
   "assoc": "NONE",
   "text": "Updated with [c765d9f](https://github.com/bitcoin/bitcoin/commit/c765d9fa113f032c0f6fa54369e3add1a7edcb38) it has been rebased over master"
  }
 ],
 "labels_log": [
  {
   "t": "2025-08-01T15:31:49Z",
   "action": "labeled",
   "label": "interfaces",
   "who": "DrahtBot"
  },
  {
   "t": "2025-10-24T18:59:45Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-11-19T18:55:09Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2025-12-15T15:34:14Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2025-12-16T19:51:43Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-30T22:16:14Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-03-31T17:41:17Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-04-09T09:18:16Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-04-09T20:39:51Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-22T04:17:38Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-02T17:58:49Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-05T16:28:33Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-14T17:06:46Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-11T19:01:39Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-17T10:00:58Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-21T08:43:05Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-22T00:00:48Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-27T14:01:34Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-27T16:15:07Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-01T12:57:20Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-01T13:26:16Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-09T16:36:26Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2025-12-16T17:59:49Z",
   "kind": "closed",
   "who": "DrahtBot"
  },
  {
   "t": "2025-12-16T17:59:54Z",
   "kind": "reopened",
   "who": "DrahtBot"
  }
 ],
 "text_chars": 19565,
 "text_tokens_estimate": 4891,
 "changed_paths": [
  "src/interfaces/node.h",
  "src/interfaces/snapshot.h",
  "src/kernel/notifications_interface.h",
  "src/node/interface_ui.h",
  "src/node/interfaces.cpp",
  "src/node/kernel_notifications.cpp",
  "src/node/kernel_notifications.h",
  "src/rpc/blockchain.cpp",
  "src/validation.cpp",
  "test/functional/feature_assumeutxo.py"
 ],
 "files": [
  {
   "path": "src/interfaces/node.h",
   "add": 9,
   "del": 0
  },
  {
   "path": "src/interfaces/snapshot.h",
   "add": 36,
   "del": 0
  },
  {
   "path": "src/kernel/notifications_interface.h",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/node/interface_ui.h",
   "add": 3,
   "del": 0
  },
  {
   "path": "src/node/interfaces.cpp",
   "add": 55,
   "del": 0
  },
  {
   "path": "src/node/kernel_notifications.cpp",
   "add": 5,
   "del": 0
  },
  {
   "path": "src/node/kernel_notifications.h",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/rpc/blockchain.cpp",
   "add": 10,
   "del": 19
  },
  {
   "path": "src/validation.cpp",
   "add": 6,
   "del": 0
  },
  {
   "path": "test/functional/feature_assumeutxo.py",
   "add": 2,
   "del": 2
  }
 ],
 "test_lines": 4,
 "git": {
  "head": "c765d9fa113f032c0f6fa54369e3add1a7edcb38",
  "head_matches_backup": true,
  "base": "204256c73f28286a05370361e2bc7a2f74aa4754",
  "commits": [
   {
    "sha": "1d4552b854",
    "subject": "interfaces: expose UTXO snapshot functionality (loading/activate) in node interface",
    "files": 3,
    "add": 92,
    "del": 0
   },
   {
    "sha": "3c362b1843",
    "subject": "notifications: Implement snapshot load progress notifications",
    "files": 7,
    "add": 25,
    "del": 0
   },
   {
    "sha": "c765d9fa11",
    "subject": "rpc: Refactor loadtxoutset to utilize new node interface for UTXO snapshot loading",
    "files": 2,
    "add": 12,
    "del": 21
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "e9bf6dd7591dfde8",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}