{
 "number": 35113,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35113",
 "title": "net: introduce block tracker to retry to download blocks after failure",
 "author": "optout21",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-04-19T09:01:25Z",
 "updated_at": "2026-09-11T01:10:29Z",
 "age_days": 151,
 "draft": true,
 "labels": [
  "P2P",
  "Needs rebase"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "2034c609f3111a874f6d10122e2fbe602bdf1dd9",
 "head_ref": "block-dl",
 "head_repo": "optout21/bitcoin",
 "head_history": [
  {
   "t": "2026-04-21T09:13:37Z",
   "sha": "2034c609f3111a874f6d10122e2fbe602bdf1dd9"
  }
 ],
 "additions": 330,
 "deletions": 10,
 "changed_files": 8,
 "commit_count": 6,
 "size_bucket": "M",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {},
   "conflicts": [
    {
     "number": 35498,
     "title": "net: move cs_main up in FetchBlock to fix rpc assert crash",
     "author": "Crypt-iQ"
    },
    {
     "number": 34565,
     "title": "refactor: extract BlockDownloadManager from PeerManagerImpl",
     "author": "w0xlt"
    },
    {
     "number": 28690,
     "title": "build: Introduce internal kernel library",
     "author": "sedited"
    }
   ]
  }
 },
 "acks_parsed": {},
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 0,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 1,
  "distinct_reviewers": [
   "luke-jr"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-04-30T13:32:04Z",
  "last_reviewer_activity": "2026-04-25T16:32:12Z",
  "last_reviewer": "luke-jr",
  "author_silent_days": 140,
  "waiting_on_author_days": 0,
  "days_since_update": 6
 },
 "refs": {
  "mentioned": [
   27652,
   27837,
   29183
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 27837,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "net: introduce block tracker to retry to download blocks after failure"
   },
   {
    "number": 27652,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Allow getblockfrompeer to use any peer"
   },
   {
    "number": 29183,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "Prune Node Rescan Project Tracking"
   }
  ],
  "conflicts": [
   35498,
   34565,
   28690
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/rpc/blockchain.cpp"
 ],
 "body": "Revival of closed/stale #27837 . The change is taken (as of b18c72cfcd6f27070928bc0ba16db6897960f211) and rebased to current master. Original description follows.\n\nComing from #27652, part of #29183.\n\nThe general idea is to keep track of the user requested blocks so, in\ncase of a bad behaving peer or a network disconnection, they can be\nfetched from another one automatically without any further user interaction.\n\nThis was requested by users because the `getblockfrompeer` RPC command\nlacks the functionality to notify them about block request failures or peer\ndisconnections (which is expected due to the asynchronous nature of the block\nrequests).\n\nCurrently, this new functionality is limited to blocks requested by the\nuser via the 'getblockfrompeer' RPC command.\n\nIn the future, this class could expand its scope and be utilized in the\nregular chain synchronization process. Or, even could be employed in\nspecial procedures like a prune node rescan that uses BIP158 block filters,\nor even into BIP157 itself.",
 "commits": [
  {
   "sha": "ddacb2a667eab12f32b3e88b09ee85b6e9978a29",
   "date": "2026-04-21T09:11:54Z",
   "message": "net: FetchBlock, disallow requesting blocks from network limited peers\n\nThis is in preparation for block tracker.\n\nCo-authored-by: optout <13562139+optout21@users.noreply.github.com>"
  },
  {
   "sha": "1a2b81b1d1917cf1e15fb4f8320c2413d5978df5",
   "date": "2026-04-21T09:12:26Z",
   "message": "net: FetchBlock, disallow requesting block to the same peer multiple times\n\nCo-authored-by: optout <13562139+optout21@users.noreply.github.com>"
  },
  {
   "sha": "80c742584e6b752cdaa30c9aabfcbce8fd657865",
   "date": "2026-04-21T09:12:39Z",
   "message": "net: introduce BlockRequestTracker\n\nCo-authored-by: optout <13562139+optout21@users.noreply.github.com>"
  },
  {
   "sha": "3867d35acbedf7a0989e26894c32ebf9be853534",
   "date": "2026-04-21T09:12:47Z",
   "message": "rpc: getblockfrompeer, connect block tracking mechanism and add coverage\n\nIf the initial block fetching process fails, the p2p layer will be in\ncharge of fetching the block from 'any' connected peer.\nRe-trying to download the block from different peers until it is\nreceived.\n\nCo-authored-by: optout <13562139+optout21@users.noreply.github.com>"
  },
  {
   "sha": "fccf94bd62afc4fc761f2b197595f5d3ebd22a26",
   "date": "2026-04-21T09:12:57Z",
   "message": "rpc: getblockfrompeer, introduce fetch from \"any\" peer functionality\n\nIf no 'peer_id' is provided, 'getblockfrompeer' will delegate\nthe peer selection to the internal block downloading logic.\n\nCo-authored-by: optout <13562139+optout21@users.noreply.github.com>"
  },
  {
   "sha": "2034c609f3111a874f6d10122e2fbe602bdf1dd9",
   "date": "2026-04-21T09:13:03Z",
   "message": "rpc: getblockfrompeer, add one-shot block requests capability\n\nAllowing what we had before, a single block request with no automatic\nretry nor tracking mechanism.\n\nCo-authored-by: optout <13562139+optout21@users.noreply.github.com>"
  }
 ],
 "timeline": [
  {
   "t": "2026-04-21T09:13:37Z",
   "kind": "force_push",
   "who": "optout21",
   "commit": "2034c609f3111a874f6d10122e2fbe602bdf1dd9"
  },
  {
   "t": "2026-04-25T16:29:37Z",
   "kind": "review_comment",
   "who": "luke-jr",
   "assoc": "CONTRIBUTOR",
   "path": "src/rpc/blockchain.cpp",
   "commit": "2034c609f3111a874f6d10122e2fbe602bdf1dd9",
   "in_reply_to": null,
   "text": "Sounds like that's a default of true (not RPCArg::Optional::OMITTED with a description noting it)?"
  },
  {
   "t": "2026-04-25T16:31:09Z",
   "kind": "review_comment",
   "who": "luke-jr",
   "assoc": "CONTRIBUTOR",
   "path": "src/rpc/blockchain.cpp",
   "commit": "2034c609f3111a874f6d10122e2fbe602bdf1dd9",
   "in_reply_to": null,
   "text": "```suggestion\n                        \"If omitted, the node will fetch the block from any available peer. (requires retry=true)\"},\n```\n\n...or fix it to work without retry"
  },
  {
   "t": "2026-04-25T16:31:46Z",
   "kind": "review_comment",
   "who": "luke-jr",
   "assoc": "CONTRIBUTOR",
   "path": "src/rpc/blockchain.cpp",
   "commit": "2034c609f3111a874f6d10122e2fbe602bdf1dd9",
   "in_reply_to": null,
   "text": "Booleans should ideally not be positional parameters, named only (eg, with an options Object)"
  },
  {
   "t": "2026-04-25T16:32:12Z",
   "kind": "review",
   "who": "luke-jr",
   "assoc": "CONTRIBUTOR",
   "state": "CHANGES_REQUESTED",
   "commit": "2034c609f3111a874f6d10122e2fbe602bdf1dd9",
   "text": ""
  },
  {
   "t": "2026-04-28T10:07:14Z",
   "kind": "review",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "2034c609f3111a874f6d10122e2fbe602bdf1dd9",
   "text": "The last commit re-introduces behavior \"what we had before\". I will see how changes could be reordered to avoid removing some behavior and then re-introducing again."
  },
  {
   "t": "2026-04-30T13:32:04Z",
   "kind": "comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "text": "@luke-jr , thanks for the comments on the RPC parameters, I will consider them with upcoming changes."
  }
 ],
 "labels_log": [
  {
   "t": "2026-04-19T09:01:29Z",
   "action": "labeled",
   "label": "P2P",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-14T14:33:37Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 2988,
 "text_tokens_estimate": 747,
 "changed_paths": [
  "src/CMakeLists.txt",
  "src/block_request_tracker.cpp",
  "src/block_request_tracker.h",
  "src/net_processing.cpp",
  "src/net_processing.h",
  "src/rpc/blockchain.cpp",
  "src/rpc/client.cpp",
  "test/functional/rpc_getblockfrompeer.py"
 ],
 "files": [
  {
   "path": "src/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/block_request_tracker.cpp",
   "add": 90,
   "del": 0
  },
  {
   "path": "src/block_request_tracker.h",
   "add": 71,
   "del": 0
  },
  {
   "path": "src/net_processing.cpp",
   "add": 58,
   "del": 5
  },
  {
   "path": "src/net_processing.h",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/rpc/blockchain.cpp",
   "add": 8,
   "del": 3
  },
  {
   "path": "src/rpc/client.cpp",
   "add": 1,
   "del": 0
  },
  {
   "path": "test/functional/rpc_getblockfrompeer.py",
   "add": 99,
   "del": 0
  }
 ],
 "test_lines": 99,
 "git": {
  "head": "2034c609f3111a874f6d10122e2fbe602bdf1dd9",
  "head_matches_backup": true,
  "base": "378e17f7035a8d9913d8faec7c9bad11ea32afbd",
  "commits": [
   {
    "sha": "ddacb2a667",
    "subject": "net: FetchBlock, disallow requesting blocks from network limited peers",
    "files": 2,
    "add": 15,
    "del": 0
   },
   {
    "sha": "1a2b81b1d1",
    "subject": "net: FetchBlock, disallow requesting block to the same peer multiple times",
    "files": 1,
    "add": 0,
    "del": 3
   },
   {
    "sha": "80c742584e",
    "subject": "net: introduce BlockRequestTracker",
    "files": 3,
    "add": 162,
    "del": 0
   },
   {
    "sha": "3867d35acb",
    "subject": "rpc: getblockfrompeer, connect block tracking mechanism and add coverage",
    "files": 2,
    "add": 79,
    "del": 0
   },
   {
    "sha": "fccf94bd62",
    "subject": "rpc: getblockfrompeer, introduce fetch from \"any\" peer functionality",
    "files": 5,
    "add": 36,
    "del": 7
   },
   {
    "sha": "2034c609f3",
    "subject": "rpc: getblockfrompeer, add one-shot block requests capability",
    "files": 5,
    "add": 46,
    "del": 8
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "dd464f0cdcaf3612",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}