{
 "number": 35909,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35909",
 "title": "rest: Allow fetching stale header",
 "author": "davidgumberg",
 "author_association": "MEMBER",
 "created_at": "2026-08-05T22:42:19Z",
 "updated_at": "2026-09-16T18:06:31Z",
 "age_days": 42,
 "draft": false,
 "labels": [
  "RPC/REST/ZMQ"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "bd9d6bc4e98ae2ded3772127d933294c64b744e0",
 "head_ref": "2026-08-05-rest-staleheader",
 "head_repo": "davidgumberg/bitcoin",
 "head_history": [],
 "additions": 134,
 "deletions": 28,
 "changed_files": 6,
 "commit_count": 3,
 "size_bucket": "M",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "jeanpablojp",
      "url": "https://github.com/bitcoin/bitcoin/pull/35909#pullrequestreview-4942370238"
     }
    ],
    "concept_ack": [
     {
      "login": "sedited",
      "url": "https://github.com/bitcoin/bitcoin/pull/35909#issuecomment-5201062145"
     },
     {
      "login": "0xB10C",
      "url": "https://github.com/bitcoin/bitcoin/pull/35909#issuecomment-5702220014"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "sedited": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-08-06T06:14:41Z",
   "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": [
   "0xB10C",
   "jeanpablojp",
   "sedited"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-08-15T02:00:36Z",
  "last_reviewer_activity": "2026-09-16T18:06:27Z",
  "last_reviewer": "0xB10C",
  "author_silent_days": 33,
  "waiting_on_author_days": 0,
  "days_since_update": 0
 },
 "refs": {
  "mentioned": [
   33752,
   35897
  ],
  "depends_on": [],
  "fixes": [
   35897
  ],
  "linked_issues": [
   {
    "number": 35897,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "rest: Allow fetching headers from stale branches"
   }
  ],
  "references": [
   {
    "number": 35897,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "rest: Allow fetching headers from stale branches"
   },
   {
    "number": 33752,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "rest: Query predecessor headers using negative count param"
   }
  ],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "doc/release-notes-reststaleheader.md"
 ],
 "body": "This is one approach that would resolve #35897.\n\nBeing able to request stale block headers is useful for clients that want to learn the ancestors of a blockhash e.g. when following a re-org up and matches the functionality of the getblockheader RPC.\n\nThis branch takes the approach that a user has to set `count=1` and opt-in to non-active-chain blocks with `activechainonly=false`.\n\nAlternative approaches:\n\n### Fetching stale blocks when `count=1` without a new param\n\nHyrum's Law suggests that a client out there relies on the property that `/headers/` returns `[]` for non-active-chain blocks, so this is probably dangerous.\n\n### A separate `/header/` interface\n\nThis is nice because it avoids the parameter matrix, and we can have a REST path that matches the semantics of `getblockheader`, but I am not sure if this is worth the additional implementation complexity, but I could rework towards this approach if others feel strongly.\n\n### Another rest endpoint that supports negative ranges\n\ne.g. see https://github.com/bitcoin/bitcoin/pull/33752\n\n---\n\n_LLM Disclosure: Used as a research tool and rubber ducky while making this PR, but all code and text came from some indeterminate place inside my body._",
 "commits": [
  {
   "sha": "31e38d85429e3dc7be9d66bc10c3b3e27efaaec0",
   "date": "2026-08-05T20:22:31Z",
   "message": "rest: refactor: Extract bool param parsing logic into a helper."
  },
  {
   "sha": "f5c9d8289cf5663b420277702ff2ee5133bc8b7e",
   "date": "2026-08-05T22:40:56Z",
   "message": "rest: /headers/activechainonly=false to allow querying stale blocks."
  },
  {
   "sha": "bd9d6bc4e98ae2ded3772127d933294c64b744e0",
   "date": "2026-08-05T22:40:56Z",
   "message": "doc: Add release note and usage for activechainonly REST param."
  }
 ],
 "timeline": [
  {
   "t": "2026-08-06T06:14:41Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "Concept ACK"
  },
  {
   "t": "2026-08-15T01:44:54Z",
   "kind": "review",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "bd9d6bc4e98ae2ded3772127d933294c64b744e0",
   "text": "tACK bd9d6bc4e98ae2ded3772127d933294c64b744e0\n\nOn the question in the PR description: I'd stick with the parameter because it solves the issue's use case without opening a new endpoint to maintain, and #33752 never got in."
  },
  {
   "t": "2026-08-15T01:44:54Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "doc/release-notes-reststaleheader.md",
   "commit": "bd9d6bc4e98ae2ded3772127d933294c64b744e0",
   "in_reply_to": null,
   "text": "shouldn't this be renamed to `release-notes-35909.md` before merge?"
  },
  {
   "t": "2026-08-15T02:00:36Z",
   "kind": "review_comment",
   "who": "davidgumberg",
   "assoc": "MEMBER",
   "path": "doc/release-notes-reststaleheader.md",
   "commit": "bd9d6bc4e98ae2ded3772127d933294c64b744e0",
   "in_reply_to": 3788158141,
   "text": "That is the pattern used in lots of other PR's, and recommended by the developer notes, but I think as long as the release  note file is uniquely named it's fine, the instructions in developer-notes.md are to guard against things like `release-notes-wallet.md` it seems to me."
  },
  {
   "t": "2026-09-16T18:06:27Z",
   "kind": "comment",
   "who": "0xB10C",
   "assoc": "MEMBER",
   "text": "I was surprised to learn that this isn't possible with the REST interface today! I'm using the `getblockheader` RPC a lot in fork-observer. Concept ACK.\n\n[quoted text omitted]\nREST interface versioning would also be an option, but out of scope for this PR. It also came up in https://github.com/bitcoin/bitcoin/pull/32540#issuecomment-5667569856 recently.\n\n[quoted text omitted]\nYeah, I feel this might even be a little cleaner. `/rest/headerS` with `count=1` and `activechainonly=false` feels like introducing more REST API weirdness?"
  }
 ],
 "labels_log": [
  {
   "t": "2026-08-05T22:42:22Z",
   "action": "labeled",
   "label": "RPC/REST/ZMQ",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 2557,
 "text_tokens_estimate": 639,
 "changed_paths": [
  "doc/REST-interface.md",
  "doc/release-notes-reststaleheader.md",
  "src/rest.cpp",
  "src/rest.h",
  "src/test/rest_tests.cpp",
  "test/functional/interface_rest.py"
 ],
 "files": [
  {
   "path": "doc/REST-interface.md",
   "add": 7,
   "del": 2
  },
  {
   "path": "doc/release-notes-reststaleheader.md",
   "add": 5,
   "del": 0
  },
  {
   "path": "src/rest.cpp",
   "add": 59,
   "del": 25
  },
  {
   "path": "src/rest.h",
   "add": 5,
   "del": 0
  },
  {
   "path": "src/test/rest_tests.cpp",
   "add": 44,
   "del": 0
  },
  {
   "path": "test/functional/interface_rest.py",
   "add": 14,
   "del": 1
  }
 ],
 "test_lines": 59,
 "git": {
  "head": "bd9d6bc4e98ae2ded3772127d933294c64b744e0",
  "head_matches_backup": true,
  "base": "c4fbd3c72114e3466329ec6f4b0f0a4b7ebce3b1",
  "commits": [
   {
    "sha": "31e38d8542",
    "subject": "rest: refactor: Extract bool param parsing logic into a helper.",
    "files": 3,
    "add": 85,
    "del": 18
   },
   {
    "sha": "f5c9d8289c",
    "subject": "rest: /headers/activechainonly=false to allow querying stale blocks.",
    "files": 3,
    "add": 39,
    "del": 10
   },
   {
    "sha": "bd9d6bc4e9",
    "subject": "doc: Add release note and usage for activechainonly REST param.",
    "files": 2,
    "add": 12,
    "del": 2
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "e47a0ebd7e52bef6",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}