{
 "number": 35561,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35561",
 "title": "net: move some CNodeState fields to Peer",
 "author": "Crypt-iQ",
 "author_association": "MEMBER",
 "created_at": "2026-06-18T11:03:43Z",
 "updated_at": "2026-09-14T15:51:41Z",
 "age_days": 91,
 "draft": false,
 "labels": [
  "P2P",
  "Needs rebase"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde",
 "head_ref": "06082026/cnodestate",
 "head_repo": "Crypt-iQ/bitcoin",
 "head_history": [
  {
   "t": "2026-08-26T00:15:36Z",
   "sha": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde"
  }
 ],
 "additions": 42,
 "deletions": 42,
 "changed_files": 4,
 "commit_count": 3,
 "size_bucket": "S",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "w0xlt",
      "url": "https://github.com/bitcoin/bitcoin/pull/35561#pullrequestreview-5146951356"
     }
    ],
    "concept_ack": [
     {
      "login": "davidgumberg",
      "url": "https://github.com/bitcoin/bitcoin/pull/35561#issuecomment-4747307175"
     },
     {
      "login": "mzumsande",
      "url": "https://github.com/bitcoin/bitcoin/pull/35561#pullrequestreview-4938314585"
     }
    ],
    "stale_ack": [
     {
      "login": "dergoegge",
      "url": "https://github.com/bitcoin/bitcoin/pull/35561#pullrequestreview-4600905548"
     }
    ]
   },
   "conflicts": [
    {
     "number": 35940,
     "title": "net: allow selecting BIP152 high-bandwidth peers with `-addnode`",
     "author": "w0xlt"
    },
    {
     "number": 35591,
     "title": "[DO NOT MERGE] Erlay: bandwidth-efficient transaction relay protocol (Full implementation)",
     "author": "sr-gi"
    },
    {
     "number": 35558,
     "title": "p2p: Prefill compact blocks",
     "author": "davidgumberg"
    },
    {
     "number": 35522,
     "title": "refactor: Extract per-message helpers from SendMessages() (move-only)",
     "author": "pablomartin4btc"
    },
    {
     "number": 34743,
     "title": "p2p: don't disconnect manual peers for block stalling",
     "author": "willcl-ark"
    }
   ]
  }
 },
 "acks_parsed": {
  "davidgumberg": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-06-19T00:47:44Z",
   "stale": false
  },
  "dergoegge": {
   "kind": "ack",
   "hash": "765f65971aa4fc6c7c0bdf971b4cdc771a5a296e",
   "t": "2026-06-30T13:48:46Z",
   "stale": true
  },
  "mzumsande": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-08-14T17:02:09Z",
   "stale": false
  },
  "w0xlt": {
   "kind": "ack",
   "hash": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde",
   "t": "2026-09-08T21:00:25Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 1,
  "stale_ack": 1,
  "concept_ack": 2,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "davidgumberg",
   "dergoegge",
   "mzumsande",
   "w0xlt"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-08-26T11:16:15Z",
  "last_reviewer_activity": "2026-09-08T21:00:25Z",
  "last_reviewer": "w0xlt",
  "author_silent_days": 22,
  "waiting_on_author_days": 8,
  "days_since_update": 3
 },
 "refs": {
  "mentioned": [
   32606
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 32606,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-07-06",
    "title": "p2p: Drop unsolicited CMPCTBLOCK from non-HB peer and when blocksonly"
   }
  ],
  "conflicts": [
   35940,
   35591,
   35558,
   35522,
   34743
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/net_processing.cpp"
 ],
 "body": "The first commit moves m_requested_hb_cmpctblocks and m_provides_cmpctblocks from CNodeState to Peer and also makes the two fields atomic.\n\nThe second commit moves fPreferredDownload to Peer and makes it atomic. Since m_num_preferred_download_peers is a counter based on this field, it can also be atomic. This also lets us drop cs_main usage in a few places. I found this commit harder to reason about, specifically whether the asserts in FinalizeNode were still safe for m_num_preferred_download_peers if another thread could modify the value before/after the `m_num_preferred_download_peers -= peer->fPreferredDownload` line and trigger the assert. Afaict, these asserts are still safe because ProcessMessage cannot run for the same peer as the peer being cleaned up in FinalizeNode. I am also happy to drop this second commit or explain my reasoning in more detail.\n\nFor reference:\n\n- m_requested_hb_cmpctblocks can be accessed from:\n  - NewPoWValidBlock (read)    (b-msghand, http, ipc? threads)\n  - ProcessMessage     (write)   (b-msghand)\n  - SendMessages        (read)    (b-msghand)\n\n- m_provides_cmpctblocks can be accessed from:\n  - MaybeSetPeerAsAnnouncingHeaderAndIDs (read)  (b-msghand, http, ipc?)\n  - HeadersDirectFetchBlocks             (read)  (b-msghand)\n  - ProcessMessage                       (write) (b-msghand)\n\n- fPreferredDownload can be accessed from:\n  - ProcessMessage (read/write) (b-msghand)\n  - SendMessages (read) (b-msghand)\n  - FinalizeNode (read) (bitcoind, b-net)\n\n- m_num_preferred_download_peers can be accessed from:\n  - ProcessMessage (write) (b-msghand)\n  - SendMessages (read) (b-msghand)\n  - FinalizeNode (read/write) (bitcoind, b-net)",
 "commits": [
  {
   "sha": "1648713efe8aa29f292d7c52f720393892633300",
   "date": "2026-08-25T19:59:04Z",
   "message": "net: move cmpctblocks fields from CNodeState to Peer\n\nBoth m_requested_hb_cmpctblocks & m_provides_cmpctblocks were\nprotected by cs_main which is unnecessary. Instead convert them\nto std::atomic<bool> as Mutex is not needed. This way we don't\nneed to worry about potential lock inversion in the future or\nthread safety annotations. Also, add a negative annotation to\nNewPoWValidBlock for m_peer_mutex since it now acquires it."
  },
  {
   "sha": "8e523ca270d025c30c05d842fca3582b5cae9786",
   "date": "2026-08-25T19:59:04Z",
   "message": "net: move fPreferredDownload to Peer, make atomic\n\nAlso make the m_num_preferred_download_peers counter atomic and add\nan assert in FinalizeNode. The asserts for m_num_preferred_download_peers\nin FinalizeNode are still safe even without cs_main locking because of\nthe implicit guarantee that ProcessMessage may not run for a peer\nat the same time as FinalizeNode. This has the nice benefit of being\nable to remove cs_main usage in some places."
  },
  {
   "sha": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde",
   "date": "2026-08-25T19:59:04Z",
   "message": "scripted-diff: rename fPreferredDownload to m_preferred_download\n\n-BEGIN VERIFY SCRIPT-\n\n sed -i \"s/fPreferredDownload/m_preferred_download/g\" $( git grep -l fPreferredDownload )\n\n-END VERIFY SCRIPT-"
  }
 ],
 "timeline": [
  {
   "t": "2026-06-19T00:47:44Z",
   "kind": "comment",
   "who": "davidgumberg",
   "assoc": "MEMBER",
   "text": "Concept ACK, Reviewed to https://github.com/bitcoin/bitcoin/pull/35561/changes/0954ae669683a3179a362dd47cb6176cda914eb2.\n\nLess `cs_main` is good, locks are scary, and can hurt performance, and are unnecessary for all of these fields. I need to review https://github.com/bitcoin/bitcoin/pull/35561/commits/765f65971aa4fc6c7c0bdf971b4cdc771a5a296e carefully."
  },
  {
   "t": "2026-06-22T21:00:12Z",
   "kind": "review_comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "path": "src/net_processing.cpp",
   "commit": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde",
   "in_reply_to": null,
   "text": "This scoping can be removed now that the lock is gone, will fix the next time I push up."
  },
  {
   "t": "2026-06-30T13:48:02Z",
   "kind": "review_comment",
   "who": "dergoegge",
   "assoc": "MEMBER",
   "path": "src/net_processing.cpp",
   "commit": "765f65971aa4fc6c7c0bdf971b4cdc771a5a296e",
   "in_reply_to": null,
   "text": "nit: could scripted diff this to `m_preferred_download`"
  },
  {
   "t": "2026-06-30T13:48:46Z",
   "kind": "review",
   "who": "dergoegge",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "765f65971aa4fc6c7c0bdf971b4cdc771a5a296e",
   "text": "Code review ACK 765f65971aa4fc6c7c0bdf971b4cdc771a5a296e\n\nThe changes themselves look fine/safe to me but I think it might be useful to provide more motivation for this change.\n\nThe `m_num_preferred_download_peers` change also seems correct to me, but I found the previous version with a shared lock (i.e. `cs_main`) a little easier to reason about wrt \"at anytime `m_num_preferred_download_peers` reflects the number of `CNodeState`s with `fPreferredDownload` equals true\"."
  },
  {
   "t": "2026-07-02T15:54:20Z",
   "kind": "comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI started doing this to see how complicated the change would be to remove CNodeState and the cs_main locking it requires, I have more branches that move some of the other fields. I think tracking multiple states (CNodeState & Peer) is more confusing to reason about than just having one state and I think? it's been a goal to reduce the scope of cs_main (i.e. https://github.com/bitcoin/bitcoin/issues/27502). I have a private branch that removes some other fields, though there are some gotchas with locking.\n\n[quoted text omitted]\nSame. I think in this specific case, it's possible to replace the atomic with a smaller lock than cs_main. However, I don't think this is true of some other fields due to potential deadlock warnings that I haven't figured out how to fix. I think a smaller lock would be clearer than having two atomics here, open to changing it."
  },
  {
   "t": "2026-08-14T14:41:24Z",
   "kind": "review_comment",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "path": "src/net_processing.cpp",
   "commit": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde",
   "in_reply_to": null,
   "text": "should `NewPoWValidBlock` get a `!m_peer_mutex` annotation, now that we call `GetPeerRef` from it? I think it may be missed by the compiler due to the lambda it is used in."
  },
  {
   "t": "2026-08-14T17:02:09Z",
   "kind": "review",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "765f65971aa4fc6c7c0bdf971b4cdc771a5a296e",
   "text": "Concept ACK\n\n[quoted text omitted]\nto be fair, we do have the same pattern with `m_wtxid_relay` / `m_wtxid_relay_peers` which are also two atomics, so no strong opinion."
  },
  {
   "t": "2026-08-15T16:00:41Z",
   "kind": "review_comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "path": "src/net_processing.cpp",
   "commit": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde",
   "in_reply_to": 3784688243,
   "text": "It is indeed missed by the compiler because of the lambda. Should the annotation be added if the compiler silently skips it?"
  },
  {
   "t": "2026-08-17T12:32:43Z",
   "kind": "review_comment",
   "who": "mzumsande",
   "assoc": "MEMBER",
   "path": "src/net_processing.cpp",
   "commit": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde",
   "in_reply_to": 3784688243,
   "text": "I'd say yes, since it would be incorrect to call the function with `m_peer_mutex` held, and I don't think the compiler would complain about something it may see as a \"false positive\"."
  },
  {
   "t": "2026-08-26T00:15:36Z",
   "kind": "force_push",
   "who": "Crypt-iQ",
   "commit": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde"
  },
  {
   "t": "2026-08-26T11:15:24Z",
   "kind": "comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "text": "765f659 to 3861ab4: rebased since #32606 added another callsite using `m_provides_cmpctblocks`. Also added a commit for scripted diff. CI failures are https://github.com/bitcoin/bitcoin/pull/36088."
  },
  {
   "t": "2026-08-26T11:15:51Z",
   "kind": "review_comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "path": "src/net_processing.cpp",
   "commit": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde",
   "in_reply_to": 3784688243,
   "text": "added in 1648713efe8aa29f292d7c52f720393892633300"
  },
  {
   "t": "2026-08-26T11:16:15Z",
   "kind": "review_comment",
   "who": "Crypt-iQ",
   "assoc": "MEMBER",
   "path": "src/net_processing.cpp",
   "commit": "765f65971aa4fc6c7c0bdf971b4cdc771a5a296e",
   "in_reply_to": 3499215516,
   "text": "added in 3861ab49ec77674356ddf3fc1bd090b4b25c2fde"
  },
  {
   "t": "2026-09-08T21:00:25Z",
   "kind": "review",
   "who": "w0xlt",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde",
   "text": "ACK 3861ab49ec77674356ddf3fc1bd090b4b25c2fde"
  }
 ],
 "labels_log": [
  {
   "t": "2026-06-18T11:03:46Z",
   "action": "labeled",
   "label": "P2P",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-26T01:44:23Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-26T15:42:56Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-14T15:51:40Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 5648,
 "text_tokens_estimate": 1412,
 "changed_paths": [
  "src/net_processing.cpp",
  "src/node/txdownloadman_impl.cpp",
  "test/functional/test_framework/test_framework.py",
  "test/functional/wallet_listsinceblock.py"
 ],
 "files": [
  {
   "path": "src/net_processing.cpp",
   "add": 39,
   "del": 39
  },
  {
   "path": "src/node/txdownloadman_impl.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "test/functional/test_framework/test_framework.py",
   "add": 1,
   "del": 1
  },
  {
   "path": "test/functional/wallet_listsinceblock.py",
   "add": 1,
   "del": 1
  }
 ],
 "test_lines": 4,
 "git": {
  "head": "3861ab49ec77674356ddf3fc1bd090b4b25c2fde",
  "head_matches_backup": true,
  "base": "794a753958a7d4c03d6deadd6740d32d9bd6dbb5",
  "commits": [
   {
    "sha": "1648713efe",
    "subject": "net: move cmpctblocks fields from CNodeState to Peer",
    "files": 1,
    "add": 21,
    "del": 23
   },
   {
    "sha": "8e523ca270",
    "subject": "net: move fPreferredDownload to Peer, make atomic",
    "files": 1,
    "add": 18,
    "del": 16
   },
   {
    "sha": "3861ab49ec",
    "subject": "scripted-diff: rename fPreferredDownload to m_preferred_download",
    "files": 4,
    "add": 10,
    "del": 10
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "2803e75d510e2099",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}