{
 "number": 35642,
 "input_hash": "332512762efab0d5",
 "model": "ledger",
 "prompt_hash": null,
 "created": "2026-10-26T01:21:21+00:00",
 "result": {
  "summary": "Computes headers presync DoS-protection parameters (commitment period and redownload buffer size) at runtime in C++ whenever a headers sync starts, replacing static precomputed parameters stored in chainparams. Adds a closed-form optimization and bisection search algorithm in headerssync, stores the minimum chainwork height in chainparams consensus parameters, removes the offline python generation script, and adds fuzz and unit test suites.",
  "problem": "Release maintainers had to manually run an offline Python script during each release and estimate the software's active lifespan to precompute static sync parameters. Hardcoded parameters degrade from optimality as time advances, the old python model had a bug overlooking attackers stopping mid-batch, and sizing parameters statically or once at startup risked skewing memory limits if the system clock was corrected after boot.",
  "card": "This pull request calculates headers presync DoS-protection parameters (commitment period and redownload buffer size) at runtime whenever a headers sync starts, removing static precomputed values from chainparams. This eliminates an error-prone release step where maintainers had to predict the release's lifespan using an offline script, while automatically adapting memory bounds as real time progresses. The offline Python tool is deleted and replaced with a closed-form C++ optimization algorithm, backed by unit tests verifying against brute-force search optima and dedicated fuzz targets. No dependencies.",
  "evidence": [
   "PR description: 'Less work for maintainers that need to occasionally run the current contrib/devtools/headerssync-params.py script. Less room for mistakes in that process. Automatically adapts based on time (as opposed to needing to predict the lifetime of the software).'",
   "Commit 3ddc510850: 'The old Python code did that, but actually got it (slightly) wrong by missing the fact that attackers are capable of strategically deciding to stop the attack in the middle of a batch (found by darosior).'",
   "Commit 990b3fa6d0: 'A node which starts up with a badly wrong clock and has it corrected before syncing would otherwise use a period sized for a much shorter chain than a peer can then feed it, inflating that bound (by a factor 50 for a clock which starts out before genesis).'"
  ],
  "scope_notes": "Implements mathematical optimization and continuous relaxation bisection in src/headerssync.cpp alongside extensive brute-force and fuzz testing.",
  "changed_since_previous": "Parameters are now recomputed on demand each time a headers sync begins in PeerManagerImpl::TryLowWorkHeadersSync rather than once at node startup, protecting against subsequent clock adjustments, and exhaustive brute-force verification was added to the test suite.",
  "thread": {
   "last_event_at": "2026-10-25T06:12:42Z",
   "events": 119,
   "head_sha": "0316d0dc9ec6a1abbe84489c44a47a2dd94c79ee",
   "schema_floor": 2,
   "schema": 2
  },
  "waiting_on": [
   {
    "at": "2026-10-24",
    "id": "rc:4367161562",
    "on": "reviewer",
    "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4367161562",
    "what": "hodlinator to follow up on author's answers regarding parallel bandwidth and fractional attack_headers"
   }
  ],
  "risk": {
   "level": "medium",
   "touches": [
    "p2p"
   ],
   "why": "Incorrectly computed parameters could degrade node DoS resistance against malicious peer headers chains or cause unexpected memory growth during headers sync."
  },
  "discussion": {
   "author_status": "last statement processed 2026-10-25",
   "open_concerns": [],
   "resolved_concerns": [
    "ajtowns: whether NodeClock::now() influencing the parameters causes an anonymity break (answered by sipa 2026-07-02)",
    "shuv-amp: presync height can exceed INT_MAX and overflow on long timewarp chains (fixed by sipa 2026-08-14)",
    "shuv-amp: ComputeHeadersSyncParams() hangs indefinitely for small minchainwork heights and short timespans (fixed by sipa 2026-08-19)",
    "darosior: move the HeadersSyncParams definition from chainparams to the headersync module (fixed by sipa 2026-10-08)",
    "darosior: avoid square root indirection by using gamma and memory_factor directly (accepted by darosior 2026-09-18)",
    "darosior: the parameter search underestimates attack rate by assuming attackers cannot abort mid-batch (fixed by sipa 2026-09-15)",
    "darosior: asks whether Step 2 is still useful under the new approach and suggests dropping or simplifying it (accepted by darosior 2026-09-18)",
    "hodlinator: avoid magic number 81 by computing sizeof(CBlockHeader) or improving the docstring (fixed by sipa 2026-10-20)",
    "l0rinc: asks why Assume is used rather than Assert for preconditions, and whether zero inputs could cause division by zero or infinity-to-integer conversion in production (accepted by l0rinc 2026-10-09)",
    "l0rinc: the floating-point bisection loop can infinite-loop due to x87 excess precision (fixed by sipa 2026-10-08)",
    "l0rinc: move HeadersSyncParams and return the struct directly from ComputeHeadersSyncParams instead of std::pair (fixed by sipa 2026-10-08)",
    "l0rinc: drop the headers_sync_params test override and use the existing fixed fuzz clocks (fixed by sipa 2026-10-08)",
    "l0rinc: track only fail_buf while growing the search range and derive succ_buf at the end (fixed by sipa 2026-10-08)",
    "l0rinc: simplify the remainder calculation using the modulo operator (fixed by sipa 2026-10-08)",
    "l0rinc: drop the unnecessary BasicTestingSetup fixture in headerssync_tests (fixed by sipa 2026-10-08)",
    "l0rinc: keep the COMPACT_HEADER_SIZE assertion in the test rather than the implementation (answered by sipa 2026-10-08)",
    "l0rinc: separate expected headers from probability calculation in attack_rate (fixed by sipa 2026-10-08)",
    "l0rinc: explore whether restricting the buffer to whole commitment periods could eliminate both searches (answered by sipa 2026-10-08)",
    "l0rinc: precompute std::log2(attack_headers) once in the lambda capture (fixed by sipa 2026-10-08)",
    "l0rinc: describe the timespan parameter as genesis-to-now to match its caller (fixed by sipa 2026-10-09)",
    "l0rinc: use std::midpoint for bisection midpoint calculations in both searches (fixed by sipa 2026-10-09)",
    "l0rinc: asks whether a slightly less memory-efficient result within the model could be worth a simpler calculation, preserving the same security bound (answered by sipa 2026-10-09)",
    "l0rinc: refresh comments after search rewrite to explain clamp bounds and real-valued formulas (fixed by sipa 2026-10-09)",
    "l0rinc: report the failing period at boundary failure and initialize best memory to maximum in brute force test (answered by sipa 2026-10-09)",
    "l0rinc: encapsulate legal period bounds in the search so Step 2 can use its two candidates directly (fixed by sipa 2026-10-09)",
    "l0rinc: defer the headers sync parameter calculation until after clock checks to prevent inflated commitment allowance if the startup clock was wrong (accepted by l0rinc 2026-10-20)",
    "hodlinator: reduce duplication with the header comments by referring to them, boiling down, or merging (fixed by sipa 2026-10-20)",
    "hodlinator: include the code for generating and filtering test record values (fixed by sipa 2026-10-20)",
    "l0rinc: validate expected test record values against the attack-rate formula (fixed by sipa 2026-10-21)",
    "l0rinc: update release-process.md and description to state parameters are computed at runtime when headers sync begins (fixed by sipa 2026-10-21)",
    "l0rinc: move test vector generator script from comments to contrib/testgen/ (accepted by l0rinc 2026-10-21)",
    "hodlinator: clarify comment on timewarp chains minimizing difficulty to allow faster hashing (answered by sipa 2026-10-24)",
    "hodlinator: asks why attackers' bandwidth is modeled jointly rather than allowing multiple peers to send headers in parallel (answered by sipa 2026-10-24)",
    "hodlinator: asks how fractional attack_headers (< 1) should be interpreted and whether zero attack headers are accepted (answered by sipa 2026-10-24)"
   ]
  },
  "reviewability": {
   "state": "Ready",
   "label": "Ready",
   "reason": "Nothing known that would invalidate a review now."
  },
  "agreement": {
   "state": "Strong",
   "summary": "Strong: substantive support, no open objection (darosior, l0rinc, l0rinc, fametrano)",
   "reason": "Added fametrano's Tested ACK (c:6394267241). All claims remain settled with no pending action.",
   "evidence": [
    "sedited: Concept ACK \u2014 no reason given",
    "ajtowns: Approach ACK \u2014 Approach ACK ; needs rebase if wanted for 32.0 I guess?",
    "darosior: Concept ACK \u2014 no reason given",
    "fjahr: Concept ACK \u2014 no reason given",
    "darosior: ACK \u2014 reviewed calculation from scratch; the latest approach is easier to grasp and the looser upper bound is the right tradeoff",
    "darosior: ACK \u2014 re-ACK 0e473d175224746c13678db5106f9d4ab1086b9d",
    "darosior: ACK \u2014 re-ACK 9f7bcfe8747",
    "l0rinc: Concept ACK \u2014 calculating the parameters at startup from elapsed time since genesis, instead of predicting the release's lifetime",
    "l0rinc: ACK \u2014 Only had time for a quick pass and left a few questions. I'll review more carefully later.",
    "l0rinc: ACK \u2014 The clock correction case still seems worth addressing here or in a follow-up, but isn't blocking for me, it's not systemic.",
    "hodlinator: Concept ACK \u2014 Will see if I find time to dig into the math.",
    "l0rinc: Tested ACK \u2014 parameters are computed whenever a headers sync starts, addressing clock-correction concern, and test-vector generation script is included",
    "l0rinc: ACK \u2014 reACK 0316d0dc9ec6a1abbe84489c44a47a2dd94c79ee",
    "l0rinc: Tested ACK \u2014 Lightly tested diff re-ACK 0457cec22a273eba31e92950bd485bf72c864ab0",
    "fametrano: Tested ACK \u2014 verified the functions return the exact optimum across chains, heights, and dates; ran unit and p2p tests and compared parameters against a Python port and brute-force search"
   ],
   "objections": [
    {
     "reviewer": "ajtowns",
     "association": "MEMBER",
     "type": "question",
     "kind": "safety",
     "harm": "",
     "request": "",
     "question": "whether NodeClock::now() influencing the parameters causes an anonymity break",
     "text": "whether NodeClock::now() influencing the parameters causes an anonymity break",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author showed parameters change only roughly every 22 days and quantizing would not gain much",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:3514568670",
      "rc:3514828065"
     ],
     "evidence": "2026-07-02: 'Is there any anonymity breaking via `NodeClock::now()` influencing these parameters?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r3514402726",
     "id": "rc:3514402726",
     "at": "2026-07-02",
     "status_at": "2026-07-02",
     "status_by": "sipa",
     "resolution_evidence": "2026-07-02: sipa: 'It looks like the output parameters only change roughly every 22 days. I don't think quantizing further gains us much'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "shuv-amp",
     "association": "CONTRIBUTOR",
     "type": "objection",
     "kind": "correctness",
     "harm": "presync height can exceed INT_MAX and overflow on long timewarp chains",
     "request": "",
     "question": "",
     "text": "presync height can exceed INT_MAX and overflow on long timewarp chains",
     "clears_with": "change",
     "blocking": true,
     "status": "fixed",
     "status_note": "author added a commit to use int64_t",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "c:5296342342"
     ],
     "evidence": "2026-08-12: 'For the long timewarp chains you mention, the presync height can exceed `INT_MAX` and overflow.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#issuecomment-5269371252",
     "id": "c:5269371252",
     "at": "2026-08-12",
     "status_at": "2026-08-14",
     "status_by": "sipa",
     "resolution_evidence": "2026-08-14: sipa: 'That's mostly independent of this PR, but added a commit to address that.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "shuv-amp",
     "association": "CONTRIBUTOR",
     "type": "objection",
     "kind": "correctness",
     "harm": "ComputeHeadersSyncParams() hangs indefinitely for small minchainwork heights and short timespans",
     "request": "",
     "question": "",
     "text": "ComputeHeadersSyncParams() hangs indefinitely for small minchainwork heights and short timespans",
     "clears_with": "change",
     "blocking": true,
     "status": "fixed",
     "status_note": "fixed with bounded loop iterations and assumptions",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "c:5346650795",
      "c:5357592309"
     ],
     "evidence": "2026-08-14: 'ComputeHeadersSyncParams() doesn't terminate for a small minchainwork_headers combined with a short timespan'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#issuecomment-5297347941",
     "id": "c:5297347941",
     "at": "2026-08-14",
     "status_at": "2026-08-19",
     "status_by": "sipa",
     "resolution_evidence": "2026-08-19: sipa: 'Fixed, and added some extra `Assume()`s in the code.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "darosior",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "move the HeadersSyncParams definition from chainparams to the headersync module",
     "question": "",
     "text": "move the HeadersSyncParams definition from chainparams to the headersync module",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "moved to headerssync.h in a later commit",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4223054953"
     ],
     "evidence": "2026-09-04: 'The `HeadersSyncParams` definition can now be moved from chainparams to the headersync module.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#issuecomment-5546533833",
     "id": "c:5546533833",
     "at": "2026-09-04",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'Done, in a later commit.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "darosior",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "approach",
     "harm": "",
     "request": "avoid square root indirection by using gamma and memory_factor directly",
     "question": "",
     "text": "avoid square root indirection by using gamma and memory_factor directly",
     "clears_with": "answer",
     "blocking": false,
     "status": "accepted",
     "status_note": "superseded when author rewrote the algorithm to drop batch assumptions",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "c:5671114593",
      "c:5685669580"
     ],
     "evidence": "2026-09-14: 'Why is this square root \"indirection\" necessary? Using `gamma = bufsize / period` (intuitively \"bits of security\") and `memory_factor = (max_headers - mcw_headers) / COMPACT_HEADER_SIZE` directly seem'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4009020433",
     "id": "rc:4009020433",
     "at": "2026-09-14",
     "status_at": "2026-09-18",
     "status_by": "darosior",
     "resolution_evidence": "2026-09-18: darosior: 'ACK 526db3911d400b793e5715c0f989f1d3b66ac12e'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "darosior",
     "association": "MEMBER",
     "type": "objection",
     "kind": "correctness",
     "harm": "the parameter search underestimates attack rate by assuming attackers cannot abort mid-batch",
     "request": "",
     "question": "",
     "text": "the parameter search underestimates attack rate by assuming attackers cannot abort mid-batch",
     "clears_with": "change",
     "blocking": true,
     "status": "fixed",
     "status_note": "rewritten with single-header arrival model",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "c:5671114593",
      "c:5685669580"
     ],
     "evidence": "2026-09-14: 'this routine underestimates the rate, because an incomplete batch sent by an attacker may be detected, but will still lead to processing as many headers from the buffer'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4009670918",
     "id": "rc:4009670918",
     "at": "2026-09-14",
     "status_at": "2026-09-15",
     "status_by": "sipa",
     "resolution_evidence": "2026-09-15: sipa: 'Rewritten to take that approach. The commit history is simpler now too'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "darosior",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "usefulness",
     "harm": "",
     "request": "asks whether Step 2 is still useful under the new approach and suggests dropping or simplifying it",
     "question": "",
     "text": "asks whether Step 2 is still useful under the new approach and suggests dropping or simplifying it",
     "clears_with": "answer",
     "blocking": false,
     "status": "accepted",
     "status_note": "author simplified Step 2 to check only floor and ceil of optimal period, which reviewer accepted",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4050560007"
     ],
     "evidence": "2026-09-18: 'Is Step 2 really useful anymore with the new approach?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4048544161",
     "id": "rc:4048544161",
     "at": "2026-09-18",
     "status_at": "2026-09-18",
     "status_by": "darosior",
     "resolution_evidence": "2026-09-18: darosior: 'Neat.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "hodlinator",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "avoid magic number 81 by computing sizeof(CBlockHeader) or improving the docstring",
     "question": "",
     "text": "avoid magic number 81 by computing sizeof(CBlockHeader) or improving the docstring",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author adopted (sizeof(CBlockHeader) + 1) * 8 in NET_HEADER_SIZE",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4323567371",
      "rc:4325989887"
     ],
     "evidence": "2026-10-01: 'Rather than magic numbers, could we use `sizeof(CBlockHeader)` or compute it somehow, or improve the doc-string?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4155828163",
     "id": "rc:4155828163",
     "at": "2026-10-01",
     "status_at": "2026-10-20",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-20: sipa: 'Done.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "question",
     "kind": "safety",
     "harm": "",
     "request": "",
     "question": "asks why Assume is used rather than Assert for preconditions, and whether zero inputs could cause division by zero or infinity-to-integer conversion in production",
     "text": "asks why Assume is used rather than Assert for preconditions, and whether zero inputs could cause division by zero or infinity-to-integer conversion in production",
     "clears_with": "answer",
     "blocking": false,
     "status": "accepted",
     "status_note": "author changed to Assert in code and reviewer accepted",
     "cleared": true,
     "author_replied": false,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [],
     "evidence": "2026-10-08: 'is there a reason to use `Assume` (rather than `Assert`) for these preconditions? Shouldn't these abort in production? It seems to me that zero inputs could theoretically still lead to division by zer'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4214406451",
     "id": "rc:4214406451",
     "at": "2026-10-08",
     "status_at": "2026-10-09",
     "status_by": "l0rinc",
     "resolution_evidence": "2026-10-09: l0rinc: 'Thanks, please resolve'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "objection",
     "kind": "correctness",
     "harm": "the floating-point bisection loop can infinite-loop due to x87 excess precision",
     "request": "",
     "question": "",
     "text": "the floating-point bisection loop can infinite-loop due to x87 excess precision",
     "clears_with": "change",
     "blocking": true,
     "status": "fixed",
     "status_note": "author switched to integer bisection over bufsize",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4223034868",
      "rc:4223043409"
     ],
     "evidence": "2026-10-08: 'Digging further with AI pointed to x87 excess precision: a midpoint can compare between the endpoints, then round back to one when stored, leaving the loop with no progress.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4215432352",
     "id": "rc:4215432352",
     "at": "2026-10-08",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'Fixed, but with a much better alternative: do the bisection over integer `bufsize` values'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "move HeadersSyncParams and return the struct directly from ComputeHeadersSyncParams instead of std::pair",
     "question": "",
     "text": "move HeadersSyncParams and return the struct directly from ComputeHeadersSyncParams instead of std::pair",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "moved HeadersSyncParams to headerssync.h in a later commit",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4223054953"
     ],
     "evidence": "2026-10-08: 'Since we already have a `HeadersSyncParams` type could we move it and use it here as well (as @darosior also hinted I think)?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4215548260",
     "id": "rc:4215548260",
     "at": "2026-10-08",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'Done, in a later commit.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "drop the headers_sync_params test override and use the existing fixed fuzz clocks",
     "question": "",
     "text": "drop the headers_sync_params test override and use the existing fixed fuzz clocks",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author removed the fuzz override and attributed the change",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4223057506"
     ],
     "evidence": "2026-10-08: 'With the rewrite down to about 3 \u00b5s per call and fixed clocks already in these fuzz targets, is the override still worth keeping?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4215563224",
     "id": "rc:4215563224",
     "at": "2026-10-08",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'Done, and attributed.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "approach",
     "harm": "",
     "request": "track only fail_buf while growing the search range and derive succ_buf at the end",
     "question": "",
     "text": "track only fail_buf while growing the search range and derive succ_buf at the end",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author adopted the single-bound growth simplification",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4222945901"
     ],
     "evidence": "2026-10-08: 'Since `fail_buf = 2 * succ_buf + 1` throughout the growth loop, we can grow just `fail_buf` internally and derive `succ_buf` at the end.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4215577524",
     "id": "rc:4215577524",
     "at": "2026-10-08",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'Done.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "style",
     "harm": "",
     "request": "simplify the remainder calculation using the modulo operator",
     "question": "",
     "text": "simplify the remainder calculation using the modulo operator",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author adopted the modulo operator",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4223031132"
     ],
     "evidence": "2026-10-08: 'Unless I'm missing something, this could be simplified to modulo, see https://godbolt.org/z/53PfMqxnj.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4216174276",
     "id": "rc:4216174276",
     "at": "2026-10-08",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'Done.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "drop the unnecessary BasicTestingSetup fixture in headerssync_tests",
     "question": "",
     "text": "drop the unnecessary BasicTestingSetup fixture in headerssync_tests",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author dropped the fixture",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4222944637"
     ],
     "evidence": "2026-10-08: 'Nit: this only tests `ComputeHeadersSyncParamsInner` (which doesn\u2019t need the node setup), could we drop the fixture?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4216190418",
     "id": "rc:4216190418",
     "at": "2026-10-08",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'Done.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "keep the COMPACT_HEADER_SIZE assertion in the test rather than the implementation",
     "question": "",
     "text": "keep the COMPACT_HEADER_SIZE assertion in the test rather than the implementation",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author declined to move the assert to avoid risk of disconnect",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4222970647"
     ],
     "evidence": "2026-10-08: 'Since this assertion protects the test vectors (and since `ComputeHeadersSyncParamsInner` is already very complicated), I\u2019d keep it in the test.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4216211760",
     "id": "rc:4216211760",
     "at": "2026-10-08",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'I didn't take this, as it risks a disconnect between the two'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "style",
     "harm": "",
     "request": "separate expected headers from probability calculation in attack_rate",
     "question": "",
     "text": "separate expected headers from probability calculation in attack_rate",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author adopted the separation",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4223032721"
     ],
     "evidence": "2026-10-08: 'Nit: I find the preceding `2^-K * ...` form easier to follow. Could we separate the expected headers from the probability of passing the first `K` checks here?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4216439505",
     "id": "rc:4216439505",
     "at": "2026-10-08",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'Done.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "approach",
     "harm": "",
     "request": "explore whether restricting the buffer to whole commitment periods could eliminate both searches",
     "question": "",
     "text": "explore whether restricting the buffer to whole commitment periods could eliminate both searches",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author prefers finding the exact optimum and added a comparison commit with a naive search",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4222997179"
     ],
     "evidence": "2026-10-08: 'I wonder whether we need to find the optimum this precisely. If we restricted the buffer to whole commitment periods, we could calculate its size directly, and a logarithmic estimate might replace the'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4216461724",
     "id": "rc:4216461724",
     "at": "2026-10-08",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'I still like the fact that it actually finds *the* optimal solution (within rounding precision) to a well-defined (but w'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "approach",
     "harm": "",
     "request": "precompute std::log2(attack_headers) once in the lambda capture",
     "question": "",
     "text": "precompute std::log2(attack_headers) once in the lambda capture",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author precomputed the logarithm in the capture",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4223034130"
     ],
     "evidence": "2026-10-08: 'Nit: The attack budget stays fixed during this search, so we could calculate its logarithm once in the capture.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4216477737",
     "id": "rc:4216477737",
     "at": "2026-10-08",
     "status_at": "2026-10-08",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-08: sipa: 'Done.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "style",
     "harm": "",
     "request": "describe the timespan parameter as genesis-to-now to match its caller",
     "question": "",
     "text": "describe the timespan parameter as genesis-to-now to match its caller",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author updated the comment description",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4232698022"
     ],
     "evidence": "2026-10-09: 'The caller uses the current time, even when the local tip is still genesis. I\u2019d describe this as genesis-to-now.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4227208074",
     "id": "rc:4227208074",
     "at": "2026-10-09",
     "status_at": "2026-10-09",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-09: sipa: 'Done.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "style",
     "harm": "",
     "request": "use std::midpoint for bisection midpoint calculations in both searches",
     "question": "",
     "text": "use std::midpoint for bisection midpoint calculations in both searches",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author adopted std::midpoint",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4232695689"
     ],
     "evidence": "2026-10-09: 'Now that both searches use integer bounds, we could use `std::midpoint` in both places.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4227225807",
     "id": "rc:4227225807",
     "at": "2026-10-09",
     "status_at": "2026-10-09",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-09: sipa: 'Done. Cool, I didn't know about `std::midpoint`.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "question",
     "kind": "approach",
     "harm": "",
     "request": "",
     "question": "asks whether a slightly less memory-efficient result within the model could be worth a simpler calculation, preserving the same security bound",
     "text": "asks whether a slightly less memory-efficient result within the model could be worth a simpler calculation, preserving the same security bound",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author explained that bufsize has a closed-form formula and further simplifying period search would sacrifice too much accuracy",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4232684141"
     ],
     "evidence": "2026-10-09: 'Could a slightly less memory-efficient result within that model be worth a simpler calculation, while preserving the same security bound?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4227285565",
     "id": "rc:4227285565",
     "at": "2026-10-09",
     "status_at": "2026-10-09",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-09: sipa: 'It turns out that no simplification is needed, since we already have a closed-form function that finds the optimal bufsi'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "style",
     "harm": "",
     "request": "refresh comments after search rewrite to explain clamp bounds and real-valued formulas",
     "question": "",
     "text": "refresh comments after search rewrite to explain clamp bounds and real-valued formulas",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author refreshed comments",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4232697215"
     ],
     "evidence": "2026-10-09: 'With the integer search, a zero height would give Step 2 invalid clamp bounds, so I would update this explanation.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4228134177",
     "id": "rc:4228134177",
     "at": "2026-10-09",
     "status_at": "2026-10-09",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-09: sipa: 'Done.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "report the failing period at boundary failure and initialize best memory to maximum in brute force test",
     "question": "",
     "text": "report the failing period at boundary failure and initialize best memory to maximum in brute force test",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author dropped the test commit because attack_rate was removed entirely",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4232635355"
     ],
     "evidence": "2026-10-09: 'I would find the failing period more useful than a failure count here.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4228169398",
     "id": "rc:4228169398",
     "at": "2026-10-09",
     "status_at": "2026-10-09",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-09: sipa: 'I have dropped this commit, because `attack_rate` is now gone entirely'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "approach",
     "harm": "",
     "request": "encapsulate legal period bounds in the search so Step 2 can use its two candidates directly",
     "question": "",
     "text": "encapsulate legal period bounds in the search so Step 2 can use its two candidates directly",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author encapsulated legal bounds in the search",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4232694024"
     ],
     "evidence": "2026-10-09: 'Would it make sense to encapsulate the bounds on legal periods in the search, so Step 2 can use its two candidates directly?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4228172014",
     "id": "rc:4228172014",
     "at": "2026-10-09",
     "status_at": "2026-10-09",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-09: sipa: 'Done.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "safety",
     "harm": "",
     "request": "defer the headers sync parameter calculation until after clock checks to prevent inflated commitment allowance if the startup clock was wrong",
     "question": "",
     "text": "defer the headers sync parameter calculation until after clock checks to prevent inflated commitment allowance if the startup clock was wrong",
     "clears_with": "answer",
     "blocking": false,
     "status": "accepted",
     "status_note": "author changed calculation to runtime per connection, which reviewer confirmed addressed the clock correction concern",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4326045291"
     ],
     "evidence": "2026-10-10: 'could we defer the estimate after the clock checks?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4237809017",
     "id": "rc:4237809017",
     "at": "2026-10-10",
     "status_at": "2026-10-20",
     "status_by": "l0rinc",
     "resolution_evidence": "2026-10-20: l0rinc: 'addressing my clock-correction concern'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "hodlinator",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "reduce duplication with the header comments by referring to them, boiling down, or merging",
     "question": "",
     "text": "reduce duplication with the header comments by referring to them, boiling down, or merging",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author compacted the comment text",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4326100538"
     ],
     "evidence": "2026-10-13: 'Could we refer to that instead, boil this down further, or merge them?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4257997365",
     "id": "rc:4257997365",
     "at": "2026-10-13",
     "status_at": "2026-10-20",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-20: sipa: 'I've compacted the new text a bit.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "hodlinator",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "include the code for generating and filtering test record values",
     "question": "",
     "text": "include the code for generating and filtering test record values",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author included the generator code in a comment in headerssync_tests.cpp",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4326080748"
     ],
     "evidence": "2026-10-13: 'including the code for generating and filtering would be helpful for the next human needing update the record values'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4258306782",
     "id": "rc:4258306782",
     "at": "2026-10-13",
     "status_at": "2026-10-20",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-20: sipa: 'I've included the code in a comment, so it doesn't affect code coverage stats, but still allows re-running'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "validate expected test record values against the attack-rate formula",
     "question": "",
     "text": "validate expected test record values against the attack-rate formula",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author added optimality checks verifying the test vectors",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4340360561"
     ],
     "evidence": "2026-10-20: 'Could we also validate these expected values against the attack-rate formula?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4330312444",
     "id": "rc:4330312444",
     "at": "2026-10-20",
     "status_at": "2026-10-21",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-21: sipa: 'Done, and went further by implementing more checks to verify optimality of the test vectors.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "update release-process.md and description to state parameters are computed at runtime when headers sync begins",
     "question": "",
     "text": "update release-process.md and description to state parameters are computed at runtime when headers sync begins",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author updated release-process.md",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4341081031"
     ],
     "evidence": "2026-10-20: 'The release-process note and PR description could say that the parameters are computed at runtime whenever a headers sync begins'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4330315941",
     "id": "rc:4330315941",
     "at": "2026-10-20",
     "status_at": "2026-10-21",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-21: sipa: 'Done.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "l0rinc",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "move test vector generator script from comments to contrib/testgen/",
     "question": "",
     "text": "move test vector generator script from comments to contrib/testgen/",
     "clears_with": "answer",
     "blocking": false,
     "status": "accepted",
     "status_note": "author declined to move script and reviewer dropped the suggestion",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4340382471"
     ],
     "evidence": "2026-10-20: 'I'd find this easier to rerun as a script in `contrib/testgen/`, with a reference here.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4330318796",
     "id": "rc:4330318796",
     "at": "2026-10-20",
     "status_at": "2026-10-21",
     "status_by": "l0rinc",
     "resolution_evidence": "2026-10-21: l0rinc: 'Thanks for considering, please resolve the suggestion.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "hodlinator",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "clarify comment on timewarp chains minimizing difficulty to allow faster hashing",
     "question": "",
     "text": "clarify comment on timewarp chains minimizing difficulty to allow faster hashing",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author explained why starting at genesis is optimal for the attack and noted it will be addressed if retouched",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4367060848"
     ],
     "evidence": "2026-10-23: 'nit: Decreasing the difficulty allows even faster hashing?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4359242249",
     "id": "rc:4359242249",
     "at": "2026-10-23",
     "status_at": "2026-10-24",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-24: sipa: 'If they fork off after genesis, indeed, but in this attack scenario... I believe it is always better to start at genesis'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "hodlinator",
     "association": "MEMBER",
     "type": "question",
     "kind": "approach",
     "harm": "",
     "request": "",
     "question": "asks why attackers' bandwidth is modeled jointly rather than allowing multiple peers to send headers in parallel",
     "text": "asks why attackers' bandwidth is modeled jointly rather than allowing multiple peers to send headers in parallel",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author explained that victim network connection and hash rate bound total incoming attacker bandwidth",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4367090817"
     ],
     "evidence": "2026-10-23: 'Why jointly, isn't it more correct that multiple headers sync peers could be sending you these low-difficulty headers in parallel?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4359592481",
     "id": "rc:4359592481",
     "at": "2026-10-23",
     "status_at": "2026-10-24",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-24: sipa: 'their joint bandwidth to the victim is what matters, not their individual bandwidth'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "hodlinator",
     "association": "MEMBER",
     "type": "question",
     "kind": "approach",
     "harm": "",
     "request": "",
     "question": "asks how fractional attack_headers (< 1) should be interpreted and whether zero attack headers are accepted",
     "text": "asks how fractional attack_headers (< 1) should be interpreted and whether zero attack headers are accepted",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author clarified the value represents expected headers accepted per attack attempt",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4367161562"
     ],
     "evidence": "2026-10-23: 'Does that mean zero attack headers are accepted? Or do we round it up to only 1 attack header? Would it be possible to better explain this in the comment?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#discussion_r4359745705",
     "id": "rc:4359745705",
     "at": "2026-10-23",
     "status_at": "2026-10-24",
     "status_by": "sipa",
     "resolution_evidence": "2026-10-24: sipa: 'The number is correct, in expectation. We permit 0.00003478 headers to be accepted per attack.'",
     "pin": null,
     "from_schema": 2
    }
   ],
   "support": [
    {
     "reviewer": "sedited",
     "reason": "no reason given",
     "substantive": false,
     "verdict": "Concept ACK",
     "id": "c:5069107232",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#issuecomment-5069107232",
     "at": "2026-07-24",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "ajtowns",
     "reason": "Approach ACK ; needs rebase if wanted for 32.0 I guess?",
     "substantive": false,
     "verdict": "Approach ACK",
     "id": "c:5205781986",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#issuecomment-5205781986",
     "at": "2026-08-06",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "darosior",
     "reason": "no reason given",
     "substantive": false,
     "verdict": "Concept ACK",
     "id": "c:5207404954",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#issuecomment-5207404954",
     "at": "2026-08-06",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "fjahr",
     "reason": "no reason given",
     "substantive": false,
     "verdict": "Concept ACK",
     "id": "c:5367998461",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#issuecomment-5367998461",
     "at": "2026-08-21",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "darosior",
     "reason": "reviewed calculation from scratch; the latest approach is easier to grasp and the looser upper bound is the right tradeoff",
     "substantive": true,
     "verdict": "ACK",
     "id": "r:5250047249",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#pullrequestreview-5250047249",
     "at": "2026-09-18",
     "association": "MEMBER",
     "evidence": "read",
     "areas": []
    },
    {
     "reviewer": "darosior",
     "reason": "re-ACK 0e473d175224746c13678db5106f9d4ab1086b9d",
     "substantive": false,
     "verdict": "ACK",
     "id": "r:5252721431",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#pullrequestreview-5252721431",
     "at": "2026-09-18",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "darosior",
     "reason": "re-ACK 9f7bcfe8747",
     "substantive": false,
     "verdict": "ACK",
     "id": "r:5368176826",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#pullrequestreview-5368176826",
     "at": "2026-09-30",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "l0rinc",
     "reason": "calculating the parameters at startup from elapsed time since genesis, instead of predicting the release's lifetime",
     "substantive": true,
     "verdict": "Concept ACK",
     "id": "r:5412352111",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#pullrequestreview-5412352111",
     "at": "2026-10-08",
     "association": "MEMBER",
     "evidence": "read",
     "areas": []
    },
    {
     "reviewer": "l0rinc",
     "reason": "Only had time for a quick pass and left a few questions. I'll review more carefully later.",
     "substantive": false,
     "verdict": "ACK",
     "id": "r:5466423724",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#pullrequestreview-5466423724",
     "at": "2026-10-09",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "l0rinc",
     "reason": "The clock correction case still seems worth addressing here or in a follow-up, but isn't blocking for me, it's not systemic.",
     "substantive": false,
     "verdict": "ACK",
     "id": "r:5476952469",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#pullrequestreview-5476952469",
     "at": "2026-10-10",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "hodlinator",
     "reason": "Will see if I find time to dig into the math.",
     "substantive": false,
     "verdict": "Concept ACK",
     "id": "r:5379510928",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#pullrequestreview-5379510928",
     "at": "2026-10-13",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "l0rinc",
     "reason": "parameters are computed whenever a headers sync starts, addressing clock-correction concern, and test-vector generation script is included",
     "substantive": true,
     "verdict": "Tested ACK",
     "id": "r:5591041144",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#pullrequestreview-5591041144",
     "at": "2026-10-20",
     "association": "MEMBER",
     "evidence": "both",
     "areas": []
    },
    {
     "reviewer": "l0rinc",
     "reason": "reACK 0316d0dc9ec6a1abbe84489c44a47a2dd94c79ee",
     "substantive": false,
     "verdict": "ACK",
     "id": "c:6324747295",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#issuecomment-6324747295",
     "at": "2026-10-21",
     "association": "MEMBER",
     "evidence": "none",
     "areas": []
    },
    {
     "reviewer": "l0rinc",
     "reason": "Lightly tested diff re-ACK 0457cec22a273eba31e92950bd485bf72c864ab0",
     "substantive": false,
     "verdict": "Tested ACK",
     "id": "r:5604810367",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#pullrequestreview-5604810367",
     "at": "2026-10-21",
     "association": "MEMBER",
     "evidence": "tested",
     "areas": []
    },
    {
     "reviewer": "fametrano",
     "reason": "verified the functions return the exact optimum across chains, heights, and dates; ran unit and p2p tests and compared parameters against a Python port and brute-force search",
     "substantive": true,
     "verdict": "Tested ACK",
     "id": "c:6394267241",
     "url": "https://github.com/bitcoin/bitcoin/pull/35642#issuecomment-6394267241",
     "at": "2026-10-25",
     "association": "CONTRIBUTOR",
     "evidence": "both",
     "areas": [
      "p2p_headers_sync_with_minchainwork.py",
      "HeadersSyncState"
     ]
    }
   ],
   "participants": [
    {
     "login": "ajtowns",
     "stance": "support",
     "note": "Approach ACK; asked about potential anonymity impact of NodeClock::now()",
     "association": "MEMBER",
     "comments": 2,
     "first": "2026-07-02",
     "last": "2026-08-06"
    },
    {
     "login": "sedited",
     "stance": "support",
     "note": "Concept ACK",
     "association": "MEMBER",
     "comments": 1,
     "first": "2026-07-24",
     "last": "2026-07-24"
    },
    {
     "login": "darosior",
     "stance": "objection",
     "note": "ACK; found mid-batch abort rate underestimation; suggested simplifying Step 2 and moving param struct",
     "association": "MEMBER",
     "comments": 13,
     "first": "2026-08-06",
     "last": "2026-09-30"
    },
    {
     "login": "shuv-amp",
     "stance": "objection",
     "note": "flagged potential int overflow in presync height and solver infinite loops on edge-case inputs",
     "association": "CONTRIBUTOR",
     "comments": 2,
     "first": "2026-08-12",
     "last": "2026-08-14"
    },
    {
     "login": "fjahr",
     "stance": "support",
     "note": "Concept ACK",
     "association": "MEMBER",
     "comments": 1,
     "first": "2026-08-21",
     "last": "2026-08-21"
    },
    {
     "login": "hodlinator",
     "stance": "support",
     "note": "Concept ACK; suggested sizeof(CBlockHeader), doc compaction, testgen inclusion; asked about parallel attack bandwidth and fractional attack_headers",
     "association": "MEMBER",
     "comments": 19,
     "first": "2026-10-01",
     "last": "2026-10-24"
    },
    {
     "login": "l0rinc",
     "stance": "objection",
     "note": "Tested ACK after author addressed clock-correction concern; suggested testgen script placement and attack-rate validation; re-ACKed",
     "association": "MEMBER",
     "comments": 31,
     "first": "2026-10-08",
     "last": "2026-10-21"
    },
    {
     "login": "fametrano",
     "stance": "support",
     "note": "Tested ACK; verified the model optimum across chains, heights, and dates, and confirmed unit and p2p tests pass",
     "association": "CONTRIBUTOR",
     "comments": 1,
     "first": "2026-10-25",
     "last": "2026-10-25"
    }
   ],
   "derivation": "substantive support, no open objection (darosior, l0rinc, l0rinc, fametrano)",
   "model_state": null,
   "corrections": [],
   "notes": "Added fametrano's Tested ACK (c:6394267241). All claims remain settled with no pending action."
  },
  "dependencies": {
   "depends_on": [],
   "enables": []
  },
  "categories": [
   {
    "name": "build",
    "member": false,
    "evidence": "Deleting contrib/devtools/headerssync-params.py and updating release process documentation merely follows the migration of parameter calculation into the node.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 1,
     "leverage": 1,
     "performance": 0,
     "security_stability": 2,
     "user_value": 0
    },
    "rationale": "Not a build category change; removing the release script is a mechanical consequence of moving the logic into runtime C++."
   },
   {
    "name": "docs",
    "member": false,
    "evidence": "Updates doc/release-process.md to remove instructions for the deleted script, which is incidental to the main change.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 1,
     "leverage": 1,
     "performance": 0,
     "security_stability": 2,
     "user_value": 0
    },
    "rationale": "Documentation edits are purely secondary updates reflecting the removal of the offline script."
   },
   {
    "name": "kernel",
    "member": false,
    "evidence": "Changes in src/kernel/chainparams.cpp remove unused static parameters and do not touch the kernel API or external library boundaries.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 1,
     "leverage": 1,
     "performance": 0,
     "security_stability": 2,
     "user_value": 0
    },
    "rationale": "Does not alter the kernel boundary, library interfaces, or validation encapsulation."
   },
   {
    "name": "p2p",
    "member": true,
    "evidence": "Modifies src/headerssync.cpp, src/headerssync.h, and src/net_processing.cpp to dynamically calculate DoS-protection parameters when headers sync starts.",
    "band": "P2",
    "reason_tag": "DoS protection",
    "score": 0.68,
    "factors": {
     "bug_severity": 1,
     "leverage": 1,
     "performance": 0,
     "security_stability": 2,
     "user_value": 0
    },
    "rationale": "Calculates headers presync parameters dynamically at runtime to ensure optimal DoS resistance and memory bounds indefinitely. Hardcoded parameters degraded over time and could inflate peer memory bounds by a factor of 50 if the system clock was corrected after boot, while also resolving an attack model flaw where an attacker halts mid-batch."
   },
   {
    "name": "tests",
    "member": false,
    "evidence": "Added fuzz and unit test suites in src/test/headerssync_tests.cpp and src/test/fuzz/headerssync.cpp specifically exercise p2p headerssync logic rather than test framework machinery.",
    "band": "Unranked",
    "reason_tag": "test coverage",
    "score": 0.0,
    "factors": {
     "bug_severity": 1,
     "leverage": 1,
     "performance": 0,
     "security_stability": 2,
     "user_value": 0
    },
    "rationale": "Tests pin p2p headerssync behavior rather than modifying shared test infrastructure."
   },
   {
    "name": "tools",
    "member": false,
    "evidence": "Removes contrib/devtools/headerssync-params.py because its calculation was moved directly into the node.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 1,
     "leverage": 1,
     "performance": 0,
     "security_stability": 2,
     "user_value": 0
    },
    "rationale": "Deleting obsolete release tooling does not constitute a substantive tool development change."
   },
   {
    "name": "validation",
    "member": false,
    "evidence": "Touches src/consensus/params.h solely to expose the minimum chainwork height for headersync consumption without modifying block or transaction validation logic.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 1,
     "leverage": 1,
     "performance": 0,
     "security_stability": 2,
     "user_value": 0
    },
    "rationale": "Does not change consensus rules, chainstate management, or validation invariants."
   }
  ],
  "confidence": "high",
  "uncertainties": [],
  "needs": []
 },
 "cost_usd": 0.0,
 "source": {
  "record": "2026-10-26T01:21:21+00:00",
  "code": "2026-10-22T01:18:36+00:00",
  "judgments": 7
 }
}