{
 "number": 35906,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35906",
 "title": "First steps towards a stateless, side-effect free validation library",
 "author": "purpleKarrot",
 "author_association": "MEMBER",
 "created_at": "2026-08-05T18:50:31Z",
 "updated_at": "2026-09-16T17:27:02Z",
 "age_days": 42,
 "draft": false,
 "labels": [],
 "milestone": null,
 "base": "master",
 "head_sha": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
 "head_ref": "validation",
 "head_repo": "purpleKarrot/bitcoin",
 "head_history": [
  {
   "t": "2026-08-07T08:30:17Z",
   "sha": "95635188f2ec4abd8afa0e034f2100f3073df79f"
  },
  {
   "t": "2026-08-11T08:48:20Z",
   "sha": "6b9891ee27d892283d1e9bbd91c08ae9a1087a55"
  },
  {
   "t": "2026-08-20T19:53:01Z",
   "sha": "4d4f0331cf50d9721e28e728df1c9b2573a083a4"
  }
 ],
 "additions": 855,
 "deletions": 37,
 "changed_files": 6,
 "commit_count": 7,
 "size_bucket": "L",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "optout21",
      "url": "https://github.com/bitcoin/bitcoin/pull/35906#pullrequestreview-5129791192"
     }
    ],
    "concept_ack": [
     {
      "login": "josibake",
      "url": "https://github.com/bitcoin/bitcoin/pull/35906#issuecomment-5293252907"
     },
     {
      "login": "yuvicc",
      "url": "https://github.com/bitcoin/bitcoin/pull/35906#issuecomment-5473519576"
     }
    ],
    "stale_ack": [
     {
      "login": "janb84",
      "url": "https://github.com/bitcoin/bitcoin/pull/35906#pullrequestreview-4916125267"
     }
    ]
   },
   "conflicts": [
    {
     "number": 36244,
     "title": "validation, net: Process blocks asynchronously and reduce cs_main contention",
     "author": "w0xlt"
    },
    {
     "number": 36167,
     "title": "[RFC] Enable `-Wunused`",
     "author": "fanquake"
    },
    {
     "number": 35570,
     "title": "refactor: Change some validation.cpp methods to return BlockValidationState",
     "author": "optout21"
    },
    {
     "number": 35557,
     "title": "kernel, validation: Add btck_chainstate_manager_set_clock_time",
     "author": "ryanofsky"
    }
   ]
  }
 },
 "acks_parsed": {
  "josibake": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-08-14T12:24:49Z",
   "stale": false
  },
  "yuvicc": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-08-31T04:00:29Z",
   "stale": false
  },
  "optout21": {
   "kind": "ack",
   "hash": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "t": "2026-09-07T09:08:32Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 1,
  "stale_ack": 0,
  "concept_ack": 2,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "alexanderwiederin",
   "janb84",
   "josibake",
   "maflcko",
   "optout21",
   "yuvicc"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-08-20T19:53:01Z",
  "last_reviewer_activity": "2026-09-07T09:08:32Z",
  "last_reviewer": "optout21",
  "author_silent_days": 27,
  "waiting_on_author_days": 10,
  "days_since_update": 0
 },
 "refs": {
  "mentioned": [
   35904
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 35904,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Factoring out a stateless, side-effect free validation library"
   }
  ],
  "conflicts": [
   36244,
   36167,
   35570,
   35557
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/test/validation_check_block_tests.cpp",
  "src/test/validation_check_header_tests.cpp",
  "src/validation.cpp",
  "src/validation.h"
 ],
 "body": "This implements the following actions from #35904:\n\n1. **Expose the validation interface**\n\n   Make the existing `CheckBlockHeader`, `ContextualCheckBlockHeader`, and `ContextualCheckBlock` functions part of the public validation interface by declaring them in `validation.h`.\n\n2. **Interface Segregation: Remove dependency on `ChainstateManager`**\n\n   `ContextualCheck*` functions need a  `ChainstateManager` only to access the\n  consensus parameters. Pass `Consensus::Params` instead and access them at the call site.\n\n3. **Make environmental dependencies explicit**\n\n   Pass the validation time explicitly to `ContextualCheckBlockHeader` instead of reading the system clock internally.",
 "commits": [
  {
   "sha": "3d000d1d58e19aad00af3faa360efbe83c6d12fa",
   "date": "2026-08-20T19:24:53Z",
   "message": "Make validation functions accessible\n\nMake the existing `CheckBlockHeader`, `ContextualCheckBlockHeader`, and\n`ContextualCheckBlock` functions part of the public validation interface\nby declaring them in `validation.h`."
  },
  {
   "sha": "2f704427d9c4c83824ebe74d83b4ee97c209c172",
   "date": "2026-08-20T19:38:41Z",
   "message": "Make `ContextualCheck*` not depend on `ChainstateManager`\n\n`ContextualCheck*` functions need a `ChainstateManager` only to access\nthe consensus parameters. Pass `Consensus::Params` instead and access\nthem at the call site."
  },
  {
   "sha": "da437c50d4ca042dbda1ec7eb25a0d3e148e6288",
   "date": "2026-08-20T19:42:35Z",
   "message": "Make `ContextualCheckHeader` not depend on system time\n\nPass the validation time explicitly to `ContextualCheckBlockHeader`\ninstead of reading the system clock internally."
  },
  {
   "sha": "e1143e39142becbfc43f6eb313786f02730c3723",
   "date": "2026-08-20T19:42:43Z",
   "message": "validation: Add unit tests for `CheckBlockHeader`"
  },
  {
   "sha": "e167e61663362b444add2ab9514590750c5a81d6",
   "date": "2026-08-20T19:42:44Z",
   "message": "validation: Add unit tests for `ContextualCheckBlockHeader`"
  },
  {
   "sha": "c135dfde1195c26fec7449f7f072af655bee76a0",
   "date": "2026-08-20T19:42:45Z",
   "message": "validation: Add unit tests for `CheckBlock`"
  },
  {
   "sha": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "date": "2026-08-20T19:42:46Z",
   "message": "validation: Add unit tests for `ContextualCheckBlock`"
  }
 ],
 "timeline": [
  {
   "t": "2026-08-06T06:54:10Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/validation.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": null,
   "text": "This conflicts with https://github.com/bitcoin/bitcoin/pull/35557, which is an alternative to https://github.com/bitcoin/bitcoin/pull/35496.\n\nNo opinion on the merge order, but I think it would be good if the authors of all three alternatives provided reviews on each pull request, so that ideally the same line of code is only changed once."
  },
  {
   "t": "2026-08-06T06:57:11Z",
   "kind": "review_comment",
   "who": "maflcko",
   "assoc": "MEMBER",
   "path": "src/validation.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": null,
   "text": "this partially reverts 78adef17536edef833a0bfca06b61ce28120e486. Maybe that is fine, but if the motivation is better tests, maybe the refactor change would come with better tests included?\n\nE.g. this pull conflicts with https://github.com/bitcoin/bitcoin/pull/34895, which seems to be adding tests."
  },
  {
   "t": "2026-08-07T08:30:17Z",
   "kind": "force_push",
   "who": "purpleKarrot",
   "commit": "95635188f2ec4abd8afa0e034f2100f3073df79f"
  },
  {
   "t": "2026-08-07T11:13:39Z",
   "kind": "review_comment",
   "who": "purpleKarrot",
   "assoc": "MEMBER",
   "path": "src/validation.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": 3726555264,
   "text": "[quoted text omitted]\n\nGood point. Done."
  },
  {
   "t": "2026-08-11T08:48:20Z",
   "kind": "force_push",
   "who": "purpleKarrot",
   "commit": "6b9891ee27d892283d1e9bbd91c08ae9a1087a55"
  },
  {
   "t": "2026-08-12T11:50:16Z",
   "kind": "review",
   "who": "janb84",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "6b9891ee27d892283d1e9bbd91c08ae9a1087a55",
   "text": "t ACK 6b9891ee27d892283d1e9bbd91c08ae9a1087a55\n\nThis PR undertakes three (small) refactors that increase what is practical to test. All three functions were `static` before, so `CheckBlockHeader`, `ContextualCheckBlockHeader` and `ContextualCheckBlock` could only be tested indirectly, by pushing a block through validation (from a unit test or by submitting it over RPC or p2p). With these changes they can be called directly.  (Big improvement IMHO)\n\nPR is part of a bigger refactor to make a side-effect validation library possible."
  },
  {
   "t": "2026-08-14T12:24:49Z",
   "kind": "comment",
   "who": "josibake",
   "assoc": "MEMBER",
   "text": "Concept ACK\n\nLoving the new tests. Will be digging into this more next week, but at first glance the changes seem relatively straightforward. Also very happy to see `ContextualCheckBlockHeader` no longer reading system time."
  },
  {
   "t": "2026-08-20T14:14:00Z",
   "kind": "review_comment",
   "who": "alexanderwiederin",
   "assoc": "MEMBER",
   "path": "src/validation.h",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": null,
   "text": "I would suggest adding something like: `/** Context-dependent validity checks */` for consistency with line 394."
  },
  {
   "t": "2026-08-20T14:15:30Z",
   "kind": "review_comment",
   "who": "alexanderwiederin",
   "assoc": "MEMBER",
   "path": "src/validation.cpp",
   "commit": "1eab32ec19de786396160728ac0b6424197e85de",
   "in_reply_to": null,
   "text": "Should these doc comments move to the header now?"
  },
  {
   "t": "2026-08-20T14:22:40Z",
   "kind": "review_comment",
   "who": "alexanderwiederin",
   "assoc": "MEMBER",
   "path": "src/validation.cpp",
   "commit": "5cf507887c840f5532ba98910681bbbc578dc06e",
   "in_reply_to": null,
   "text": "`params.GetConsensus()` for CheckBlock and `GetConsensus()` for ContectualBlockCheck. Should they be aligned?"
  },
  {
   "t": "2026-08-20T14:34:04Z",
   "kind": "review_comment",
   "who": "alexanderwiederin",
   "assoc": "MEMBER",
   "path": "src/test/validation_check_block_tests.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": null,
   "text": "Any reason we don't use `BOOST_FIXTURE_TEST_SUITE` like the other `validation_*_tests.cpp` do?"
  },
  {
   "t": "2026-08-20T14:35:43Z",
   "kind": "review_comment",
   "who": "alexanderwiederin",
   "assoc": "MEMBER",
   "path": "src/test/validation_check_block_tests.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": null,
   "text": "This test reuses BlockValidationState across CheckBlock calls, the other tests create new ones. Should we make it consistent?"
  },
  {
   "t": "2026-08-20T14:38:30Z",
   "kind": "review_comment",
   "who": "alexanderwiederin",
   "assoc": "MEMBER",
   "path": "src/test/validation_check_header_tests.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": null,
   "text": "What about `BOOST_CHECK_EQUAL`?"
  },
  {
   "t": "2026-08-20T19:43:28Z",
   "kind": "review_comment",
   "who": "purpleKarrot",
   "assoc": "MEMBER",
   "path": "src/validation.h",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": 3822341713,
   "text": "obsolete with the comment below."
  },
  {
   "t": "2026-08-20T19:43:55Z",
   "kind": "review_comment",
   "who": "purpleKarrot",
   "assoc": "MEMBER",
   "path": "src/validation.cpp",
   "commit": "1eab32ec19de786396160728ac0b6424197e85de",
   "in_reply_to": 3822354109,
   "text": "You are right. the docs should be part of the declaration."
  },
  {
   "t": "2026-08-20T19:44:28Z",
   "kind": "review_comment",
   "who": "purpleKarrot",
   "assoc": "MEMBER",
   "path": "src/validation.cpp",
   "commit": "5cf507887c840f5532ba98910681bbbc578dc06e",
   "in_reply_to": 3822412703,
   "text": "ok."
  },
  {
   "t": "2026-08-20T19:48:53Z",
   "kind": "review_comment",
   "who": "purpleKarrot",
   "assoc": "MEMBER",
   "path": "src/test/validation_check_header_tests.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": 3822544629,
   "text": "Is there an advantage?"
  },
  {
   "t": "2026-08-20T19:50:05Z",
   "kind": "review_comment",
   "who": "purpleKarrot",
   "assoc": "MEMBER",
   "path": "src/test/validation_check_block_tests.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": 3822509465,
   "text": "Since the functions under test are stateless, there is not much test setup that would justify a fixture."
  },
  {
   "t": "2026-08-20T19:52:43Z",
   "kind": "review_comment",
   "who": "purpleKarrot",
   "assoc": "MEMBER",
   "path": "src/test/validation_check_block_tests.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": 3822522415,
   "text": "No strong opinion for this test. I think the state parameter is a smell anyway and it should (and will) become a return type in the long run, which will solve this."
  },
  {
   "t": "2026-08-20T19:53:01Z",
   "kind": "force_push",
   "who": "purpleKarrot",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4"
  },
  {
   "t": "2026-08-20T23:27:49Z",
   "kind": "review_comment",
   "who": "alexanderwiederin",
   "assoc": "MEMBER",
   "path": "src/test/validation_check_block_tests.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": 3822509465,
   "text": "Make sense - thank you!"
  },
  {
   "t": "2026-08-20T23:28:28Z",
   "kind": "review_comment",
   "who": "alexanderwiederin",
   "assoc": "MEMBER",
   "path": "src/test/validation_check_header_tests.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": 3822544629,
   "text": "I think the error messages are better, but not worth touching again for this."
  },
  {
   "t": "2026-08-31T04:00:29Z",
   "kind": "comment",
   "who": "yuvicc",
   "assoc": "CONTRIBUTOR",
   "text": "Concept ACK"
  },
  {
   "t": "2026-09-07T08:39:58Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/validation_check_block_tests.cpp",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "in_reply_to": null,
   "text": "Nit: The test claim could be made stronger, by showing that with `nNonce = 0` and no prior check the result is invalid (I know that this combination accidentally is checked in another test, but for completeness it could be included here as well)."
  },
  {
   "t": "2026-09-07T09:08:32Z",
   "kind": "review",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
   "text": "ACK 4d4f0331cf50d9721e28e728df1c9b2573a083a4\n\nThis change reduces complexity around the `ContextualCheckBlock` and `ContextualCheckBlockHeader` methods, and adds tests (for `CheckBlock`, `ContextualCheckBlock`, `CheckBlockHeader` and `ContextualCheckBlockHeader`).\nThe two `Contextual...` methods take only consensus parameters instead of chainstate manager, as only those are needed. The `ContextualCheckBlockHeader` method takes the current clock vale as parameter, and does not retrieve it internally. The new tests drive the methods into various error cases, by using relatively simple input data combinations (this is enabled by the changes).\n\nSome minor comments: (one additional raised in-line)\n\n- It's not mentioned that the methods are exposed so that the tests can use them. This fact may be mentioned in the relevant commit and in the PR description.\n- Inconsistencies with the prefixes in the commit messages: non-test code commits are not prefixed, test-only commits have \"validation:\" prefix. I would expect the non-test commits to have \"validation:\" prefix, and test-only commits have \"test:\" or \"validation:\" or both."
  }
 ],
 "labels_log": [],
 "state_log": [],
 "text_chars": 5435,
 "text_tokens_estimate": 1358,
 "changed_paths": [
  "src/deploymentstatus.h",
  "src/test/CMakeLists.txt",
  "src/test/validation_check_block_tests.cpp",
  "src/test/validation_check_header_tests.cpp",
  "src/validation.cpp",
  "src/validation.h"
 ],
 "files": [
  {
   "path": "src/deploymentstatus.h",
   "add": 6,
   "del": 0
  },
  {
   "path": "src/test/CMakeLists.txt",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/test/validation_check_block_tests.cpp",
   "add": 462,
   "del": 0
  },
  {
   "path": "src/test/validation_check_header_tests.cpp",
   "add": 345,
   "del": 0
  },
  {
   "path": "src/validation.cpp",
   "add": 15,
   "del": 37
  },
  {
   "path": "src/validation.h",
   "add": 25,
   "del": 0
  }
 ],
 "test_lines": 809,
 "git": {
  "head": "4d4f0331cf50d9721e28e728df1c9b2573a083a4",
  "head_matches_backup": true,
  "base": "02306cc915caf506c225d8517fd9e460640fccb6",
  "commits": [
   {
    "sha": "3d000d1d58",
    "subject": "Make validation functions accessible",
    "files": 2,
    "add": 28,
    "del": 22
   },
   {
    "sha": "2f704427d9",
    "subject": "Make `ContextualCheck*` not depend on `ChainstateManager`",
    "files": 3,
    "add": 21,
    "del": 18
   },
   {
    "sha": "da437c50d4",
    "subject": "Make `ContextualCheckHeader` not depend on system time",
    "files": 2,
    "add": 5,
    "del": 5
   },
   {
    "sha": "e1143e3914",
    "subject": "validation: Add unit tests for `CheckBlockHeader`",
    "files": 2,
    "add": 49,
    "del": 0
   },
   {
    "sha": "e167e61663",
    "subject": "validation: Add unit tests for `ContextualCheckBlockHeader`",
    "files": 1,
    "add": 297,
    "del": 0
   },
   {
    "sha": "c135dfde11",
    "subject": "validation: Add unit tests for `CheckBlock`",
    "files": 2,
    "add": 291,
    "del": 0
   },
   {
    "sha": "4d4f0331cf",
    "subject": "validation: Add unit tests for `ContextualCheckBlock`",
    "files": 1,
    "add": 172,
    "del": 0
   }
  ],
  "patch_truncated": true
 },
 "input_hash": "210f5879db958735",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}