{
 "number": 35037,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35037",
 "title": "ipc: support per-address max-connections options on -ipcbind",
 "author": "enirox001",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-04-09T13:44:27Z",
 "updated_at": "2026-09-17T09:13:17Z",
 "age_days": 161,
 "draft": false,
 "labels": [
  "IPC"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
 "head_ref": "04-26-ipcbind-max-connections-draft",
 "head_repo": "enirox001/bitcoin",
 "head_history": [
  {
   "t": "2026-04-09T13:57:04Z",
   "sha": "788107e420b02a10aa2f7ed24f7a74e2da4c092a"
  },
  {
   "t": "2026-04-09T14:19:31Z",
   "sha": "9a30318262a286cd63f45d1c91a6b52f20112c9d"
  },
  {
   "t": "2026-04-09T14:55:22Z",
   "sha": "57a0a293036046798ddfe4409389f7aa73273291"
  },
  {
   "t": "2026-04-20T11:38:44Z",
   "sha": "5bac5f687a8a3dd500c116fedaca4e39af11b351"
  },
  {
   "t": "2026-04-20T11:41:37Z",
   "sha": "c93a812f50be8fed305c225a80163a47636f9594"
  },
  {
   "t": "2026-04-20T11:48:47Z",
   "sha": "7bd2509fbe204265d04d10708e8bf703193bdd0a"
  },
  {
   "t": "2026-04-20T11:54:33Z",
   "sha": "142501831cf26bfb26243dd88c9bd212263bcb89"
  },
  {
   "t": "2026-04-20T12:46:25Z",
   "sha": "f1da993e4e7f3be7e98fff878c091a37103ae062"
  },
  {
   "t": "2026-04-20T13:03:59Z",
   "sha": "2309ca9f2933d3d2a706204b9a31bcf7b418d3fa"
  },
  {
   "t": "2026-04-20T18:31:56Z",
   "sha": "50fba48f2ac3f7d13d43982e80b5b9679b8df3de"
  },
  {
   "t": "2026-04-21T07:45:22Z",
   "sha": "9aa4677a9a5670eb950674c6b1c9d0d3992d7e88"
  },
  {
   "t": "2026-04-21T08:11:07Z",
   "sha": "46c890ca88a1313341ce3d59b9e605ebb4e427f7"
  },
  {
   "t": "2026-04-21T08:17:53Z",
   "sha": "b49abeb2114c48f86efb95aa07d023e9186d7eb5"
  },
  {
   "t": "2026-04-21T08:42:20Z",
   "sha": "2d214431d04e644df78005585ae5937bbbb90261"
  },
  {
   "t": "2026-05-12T13:33:29Z",
   "sha": "f2899ce241fd120637bdd7fb1d78c7096daec36b"
  },
  {
   "t": "2026-05-12T13:43:58Z",
   "sha": "79f631d5d1d9b7ba3c99cd4bf439d5b2e4a55dc7"
  },
  {
   "t": "2026-06-26T11:16:34Z",
   "sha": "5d66053ff08f3d64a81f7bb99462a9a5ce475ada"
  },
  {
   "t": "2026-06-29T13:57:13Z",
   "sha": "f7c7b2335058eaa2dac339400dfcb799b76615f4"
  },
  {
   "t": "2026-06-29T14:20:03Z",
   "sha": "3d74d45a8fd9ded49c32692743234bda3b6d0da1"
  },
  {
   "t": "2026-06-29T14:31:04Z",
   "sha": "15d736f1e07bb78530a7aa52f5a22ef38c322c7c"
  },
  {
   "t": "2026-07-11T06:51:44Z",
   "sha": "3eefe9596b3db2bc2dbdd3cda94053467709903a"
  },
  {
   "t": "2026-07-11T11:29:53Z",
   "sha": "dd316cec6c97d0f2400aaaace8bd8b939987cd84"
  },
  {
   "t": "2026-07-11T11:41:44Z",
   "sha": "df43cb2374f3c42344715e8d3a8dafc68be1a837"
  },
  {
   "t": "2026-07-11T19:38:21Z",
   "sha": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314"
  },
  {
   "t": "2026-07-23T10:39:12Z",
   "sha": "19159980f4ea9f96d230c4fd44a55e024b61c413"
  },
  {
   "t": "2026-07-23T10:43:38Z",
   "sha": "5a7d7e4d4df2e448d50ebcb3d622c6cc1d5d8549"
  },
  {
   "t": "2026-07-23T18:49:32Z",
   "sha": "65214d870d3b4e27889ffc05920291904e637f99"
  },
  {
   "t": "2026-07-31T15:29:26Z",
   "sha": "f4fb7169d2b4f8b292d89971ae378a9ad2c68b37"
  },
  {
   "t": "2026-07-31T15:41:45Z",
   "sha": "b822c1d727d04f783edc09c9cc56085d00daef51"
  },
  {
   "t": "2026-08-03T08:24:11Z",
   "sha": "52bf2492cd93399a86690943fb8551e8edef26b6"
  },
  {
   "t": "2026-08-03T08:37:52Z",
   "sha": "04593a16562606ae81b9d4f585c2359c794937d0"
  },
  {
   "t": "2026-08-15T18:55:33Z",
   "sha": "cd3ae326d24e3cc40154a5a21077cf7e1f9e4e8f"
  },
  {
   "t": "2026-08-15T18:59:23Z",
   "sha": "6ace89e3537ce34cc12e662a6bd618ea78fb66b8"
  },
  {
   "t": "2026-08-15T19:03:49Z",
   "sha": "79442c45f43e661707ec48608d804ac8e9c7332e"
  },
  {
   "t": "2026-08-15T19:12:58Z",
   "sha": "f13aecee44ff69e6bdee5ff4f01c7dfff30587bc"
  },
  {
   "t": "2026-08-15T19:19:29Z",
   "sha": "34177bb2fc784ba3a09d94efefd3cd63776e27b4"
  },
  {
   "t": "2026-08-15T19:29:14Z",
   "sha": "47d7fae5e7350c8492f5fea0ab70bb8148c639b6"
  },
  {
   "t": "2026-08-17T10:20:10Z",
   "sha": "bff77fbfe4b2fde7838361ce20a6dc38e40ac7ae"
  },
  {
   "t": "2026-08-17T10:26:04Z",
   "sha": "5e6b6cfe6c7c1245e2846c8e3cb1a71c145a3778"
  },
  {
   "t": "2026-08-17T10:45:59Z",
   "sha": "f466d0f4bb6b70b4dc534de78b6c2998ab0a6a96"
  },
  {
   "t": "2026-08-26T14:23:49Z",
   "sha": "b9131ff7ffb5a7c938ed64f98b2dec0942310b7c"
  },
  {
   "t": "2026-08-29T07:55:06Z",
   "sha": "70b2988c0900aa4ab0f8491799f27e5b1c8394f7"
  },
  {
   "t": "2026-09-01T10:45:48Z",
   "sha": "05bf362fd35abc7876c9d878866e4a9c2ff84017"
  },
  {
   "t": "2026-09-01T11:05:22Z",
   "sha": "7a839565cae797e87c43dc483066d47c2dffc568"
  },
  {
   "t": "2026-09-11T22:43:52Z",
   "sha": "994aef40f969fc332330a7fbc77fcca4181aef6f"
  },
  {
   "t": "2026-09-11T23:27:42Z",
   "sha": "6f8f23866a92f7c74662429e29688dc060f83bd5"
  },
  {
   "t": "2026-09-12T10:13:57Z",
   "sha": "c88b81d1e4b243e37aec53788a7736486c6affad"
  },
  {
   "t": "2026-09-15T13:30:14Z",
   "sha": "39b1c5a22c845857709d4e95d4205e0901e85b09"
  },
  {
   "t": "2026-09-16T13:51:03Z",
   "sha": "78a1251365ab0dbfa9267c30760566d3b04bcd08"
  }
 ],
 "additions": 406,
 "deletions": 17,
 "changed_files": 12,
 "commit_count": 4,
 "size_bucket": "L",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "Eunovo",
      "url": "https://github.com/bitcoin/bitcoin/pull/35037#issuecomment-5711910239"
     }
    ],
    "concept_ack": [
     {
      "login": "kevkevinpal",
      "url": "https://github.com/bitcoin/bitcoin/pull/35037#issuecomment-4237709309"
     },
     {
      "login": "Sjors",
      "url": "https://github.com/bitcoin/bitcoin/pull/35037#issuecomment-4841714760"
     }
    ],
    "stale_ack": [
     {
      "login": "ryanofsky",
      "url": "https://github.com/bitcoin/bitcoin/pull/35037#pullrequestreview-5144408002"
     },
     {
      "login": "ViniciusCestarii",
      "url": "https://github.com/bitcoin/bitcoin/pull/35037#pullrequestreview-5213583648"
     },
     {
      "login": "xyzconstant",
      "url": "https://github.com/bitcoin/bitcoin/pull/35037#issuecomment-5688030106"
     }
    ]
   },
   "conflicts": [
    {
     "number": 36097,
     "title": "mining: replace interrupt methods with cancellation arguments",
     "author": "xyzconstant"
    },
    {
     "number": 28690,
     "title": "build: Introduce internal kernel library",
     "author": "sedited"
    },
    {
     "number": 17783,
     "title": "common: Disallow calling IsArgSet() on ALLOW_LIST options",
     "author": "ryanofsky"
    },
    {
     "number": 17581,
     "title": "refactor: Remove settings merge reverse precedence code",
     "author": "ryanofsky"
    },
    {
     "number": 17580,
     "title": "refactor: Add ALLOW_LIST flags and enforce usage in CheckArgFlags",
     "author": "ryanofsky"
    },
    {
     "number": 17493,
     "title": "util: Forbid ambiguous multiple assignments in config file",
     "author": "ryanofsky"
    }
   ]
  }
 },
 "acks_parsed": {
  "ryanofsky": {
   "kind": "ack",
   "hash": "7a839565cae797e87c43dc483066d47c2dffc568",
   "t": "2026-09-08T17:30:29Z",
   "stale": true
  },
  "kevkevinpal": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-04-13T15:43:02Z",
   "stale": false
  },
  "ViniciusCestarii": {
   "kind": "ack",
   "hash": "39b1c5a22c845857709d4e95d4205e0901e85b09",
   "t": "2026-09-15T17:32:01Z",
   "stale": true
  },
  "Sjors": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-06-30T09:09:34Z",
   "stale": false
  },
  "xyzconstant": {
   "kind": "ack",
   "hash": "39b1c5a22c845857709d4e95d4205e0901e85b09",
   "t": "2026-09-15T21:01:43Z",
   "stale": true
  },
  "Eunovo": {
   "kind": "ack",
   "hash": null,
   "t": "2026-09-17T09:13:09Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 1,
  "stale_ack": 3,
  "concept_ack": 2,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 4,
  "changes_requested": 0,
  "distinct_reviewers": [
   "Eunovo",
   "Sjors",
   "ViniciusCestarii",
   "fanquake",
   "kevkevinpal",
   "ryanofsky",
   "xyzconstant"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-09-16T13:51:55Z",
  "last_reviewer_activity": "2026-09-17T09:13:09Z",
  "last_reviewer": "Eunovo",
  "author_silent_days": 1,
  "waiting_on_author_days": 0,
  "days_since_update": 0
 },
 "refs": {
  "mentioned": [
   34978
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 34978,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "init: reserve file descriptors for IPC connections"
   }
  ],
  "conflicts": [
   36097,
   28690,
   17783,
   17581,
   17580,
   17493
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "doc/release-notes-35037.md",
  "src/init.cpp",
  "src/interfaces/ipc.h",
  "src/ipc/capnp/protocol.cpp",
  "src/ipc/libmultiprocess/include/mp/proxy-io.h",
  "src/ipc/listen.cpp",
  "src/ipc/test/ipc_test.cpp",
  "src/ipc/test/ipc_tests.cpp",
  "src/ipc/types.h",
  "src/node/ipc_args.h",
  "test/functional/interface_ipc_init.py"
 ],
 "body": "The branch extends `-ipcbind` to accept `,max-connections=<n>` options, for example `-ipcbind=unix:,max-connections=8` or `-ipcbind=unix:/custom/path,max-connections=8`, instead of introducing a separate global `-ipcmaxconnections` option.\n\nThis keeps the connection limit attached to each IPC listener instead of introducing a global `-ipcmaxconnections` option (https://github.com/bitcoin/bitcoin/pull/34978). A global option would not allow different limits for different `-ipcbind` addresses, and the inline option format can be extended in the future with additional options.",
 "commits": [
  {
   "sha": "3d2b65d050962a35b071618a3f32f7a78831e8e3",
   "date": "2026-09-11T23:26:12Z",
   "message": "ipc: add default connection limit for ipcbind listeners\n\nReserve file descriptors for each configured -ipcbind listener and its\ndefault connection slots during initialization. Cap IPC reservations\nconservatively so downstream int-based file descriptor accounting\ncannot overflow.\n\nIntroduce ipc::ListenAddress to keep a listener and its connection limit\ntogether. Pass it through interfaces::Ipc and ipc::Protocol so each IPC\nlistener stops accepting new clients after reaching the cap and resumes\nafter a disconnect."
  },
  {
   "sha": "cc7eb60e6e7a24d092f48d2b7af5a0927ee31c5f",
   "date": "2026-09-12T10:07:15Z",
   "message": "ipc: support per-address max-connections on ipcbind\n\nParse optional max-connections socket options from -ipcbind values\nthrough interfaces::Ipc, returning ipc::ListenAddress values that keep\neach listener address and connection limit together.\n\nUse comma delimited socket options to avoid ambiguity with paths\ncontaining colons, and validate each configured limit before adding it\nto IPC file descriptor reservations."
  },
  {
   "sha": "d59b26e08f483080d8d92622c8a996efb0117a65",
   "date": "2026-09-16T13:50:30Z",
   "message": "ipc: test per-address connection limiting over unix sockets\n\nAdd IPC coverage for local listener capacity over unix sockets.\n\nVerify a listener at capacity resumes accepting after a disconnect, check separate\nlisteners enforce their limits independently, and cover parser and aggregate file\ndescriptor limit boundaries."
  },
  {
   "sha": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "date": "2026-09-16T13:50:37Z",
   "message": "doc: add ipcbind max-connections release note"
  }
 ],
 "timeline": [
  {
   "t": "2026-04-09T13:57:04Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "788107e420b02a10aa2f7ed24f7a74e2da4c092a"
  },
  {
   "t": "2026-04-09T14:19:31Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "9a30318262a286cd63f45d1c91a6b52f20112c9d"
  },
  {
   "t": "2026-04-09T14:40:44Z",
   "kind": "comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "text": "Concept ACK. Looks like suggestions from https://github.com/bitcoin/bitcoin/pull/35036#issuecomment-4214961912 apply here too (sorry, saw that PR first in my inbox).\n\nIMO this is a better alternative to adding a new `-ipcmaxconnections` option like #34978, and I'd prefer this approach but both approaches seem reasonable. Main reason I prefer this approach is IPC is a pretty generic feature, so it seems useful to be able to set different limits for different purposes (like GUIs vs mining clients)."
  },
  {
   "t": "2026-04-09T14:55:22Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "57a0a293036046798ddfe4409389f7aa73273291"
  },
  {
   "t": "2026-04-09T15:50:29Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Thanks for the review @ryanofsky\n\nI pushed updates based on your review here as well\n\n- the bind-address type is now shared\n- parsing moved behind the `interfaces::Ipc` boundary\n- the parser handles trailing socket options\n- `listenAddress()` now takes the bind-address struct directly"
  },
  {
   "t": "2026-04-09T17:21:27Z",
   "kind": "review_comment",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/interface_ipc_init.py",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": null,
   "text": "Same suggestion I made on #34978. It would be good to have a functional test case where max-connections is not specified, to verify the default value is actually applied correctly"
  },
  {
   "t": "2026-04-13T15:43:02Z",
   "kind": "comment",
   "who": "kevkevinpal",
   "assoc": "CONTRIBUTOR",
   "text": "Concept ACK\n\nI agree with Ryanofsky. I think this approach seems more reasonable than https://github.com/bitcoin/bitcoin/pull/34978, even though both can work and both make sense this seems cleaner. I think it makes sense to go with this approach instead of adding the `-ipcmaxconnections` option."
  },
  {
   "t": "2026-04-14T13:02:36Z",
   "kind": "comment",
   "who": "fanquake",
   "assoc": "MEMBER",
   "text": "cc @Sjors"
  },
  {
   "t": "2026-04-20T11:38:44Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "5bac5f687a8a3dd500c116fedaca4e39af11b351"
  },
  {
   "t": "2026-04-20T11:41:37Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "c93a812f50be8fed305c225a80163a47636f9594"
  },
  {
   "t": "2026-04-20T11:48:47Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "7bd2509fbe204265d04d10708e8bf703193bdd0a"
  },
  {
   "t": "2026-04-20T11:49:20Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/interface_ipc_init.py",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": 3059537285,
   "text": "Thanks for the suggestion, applied in the latest push"
  },
  {
   "t": "2026-04-20T11:54:33Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "142501831cf26bfb26243dd88c9bd212263bcb89"
  },
  {
   "t": "2026-04-20T12:46:25Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "f1da993e4e7f3be7e98fff878c091a37103ae062"
  },
  {
   "t": "2026-04-20T13:03:59Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "2309ca9f2933d3d2a706204b9a31bcf7b418d3fa"
  },
  {
   "t": "2026-04-20T18:31:56Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "50fba48f2ac3f7d13d43982e80b5b9679b8df3de"
  },
  {
   "t": "2026-04-21T07:45:22Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "9aa4677a9a5670eb950674c6b1c9d0d3992d7e88"
  },
  {
   "t": "2026-04-21T08:11:07Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "46c890ca88a1313341ce3d59b9e605ebb4e427f7"
  },
  {
   "t": "2026-04-21T08:17:53Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "b49abeb2114c48f86efb95aa07d023e9186d7eb5"
  },
  {
   "t": "2026-04-21T08:42:20Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "2d214431d04e644df78005585ae5937bbbb90261"
  },
  {
   "t": "2026-04-21T09:07:01Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Had a peer review with @Eunovo a few days ago, and I pushed a few follow-up changes to make the branch a bit easier to review:\n\n- Updated ParseBindAddress() to return util::Result, and adjusted the callers/tests accordingly.\n- Extended parser coverage to include 0, large valid values, and negative/overflow cases.\n- Cleaned up the commit structure so the branch is split into a subtree update, per-address integration, and tests.\n- Fixed the IPC limit test by correcting the async lifetime issue that could trigger disconnect errors.\n\nThe remaining subtree lint failure is expected for this draft, since the branch carries the libmultiprocess subtree update ahead of the upstream merge."
  },
  {
   "t": "2026-05-12T13:33:29Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "f2899ce241fd120637bdd7fb1d78c7096daec36b"
  },
  {
   "t": "2026-05-12T13:43:58Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "79f631d5d1d9b7ba3c99cd4bf439d5b2e4a55dc7"
  },
  {
   "t": "2026-06-26T11:16:34Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "5d66053ff08f3d64a81f7bb99462a9a5ce475ada"
  },
  {
   "t": "2026-06-26T11:17:32Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Rebased against master to resolve some merge conflicts. This PR should now be ready for review"
  },
  {
   "t": "2026-06-26T14:28:53Z",
   "kind": "review_comment",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/libmultiprocess/include/mp/proxy-io.h",
   "commit": "b194acc106b50af2a97e5475845b46f31a5d91f3",
   "in_reply_to": null,
   "text": "In `Squashed 'src/ipc/libmultiprocess/' changes from 3edbe8f67c..8511c68f8` b194acc106b50af2a97e5475845b46f31a5d91f3\n\nnit: this mutable keyword is no longer necessary\n\n```suggestion\n        [&loop, &init, state](kj::Own<kj::AsyncIoStream>&& stream) {\n```"
  },
  {
   "t": "2026-06-26T17:32:16Z",
   "kind": "review_comment",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "path": "src/interfaces/ipc.h",
   "commit": "ddfc34b65ab8c38e33eac05794246dab614a7f01",
   "in_reply_to": null,
   "text": "In `ipc: add per-address max-connections parsing and support for -ipcbind` ddfc34b65ab8c38e33eac05794246dab614a7f01\n\nShouldn't the lower bound check be parsed_limit < 1? I can't see why someone would use -ipcbind with max-connections=0 to bind something that doesn't accept any connections.\n\nI believe it would be worth to add an upper bound check too because large values flow into the int FD reservation and overflow it: `-ipcbind=unix::max-connections=200000000000` aborts the node with `Assertion 'min_fd >= 0' failed`.\n\nAlso it'd be worth splitting the range check from the parse check so out-of-range values like -1 and 0 get a specific message (\"max-connections must be at least 1\") and too big values for an int get (\"max-connections must be at most [upper bound]\") instead of a generic \"Invalid max-connections value\"."
  },
  {
   "t": "2026-06-26T19:28:52Z",
   "kind": "review_comment",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "in_reply_to": null,
   "text": "In `ipc: add per-address max-connections parsing and support for -ipcbind` ddfc34b65ab8c38e33eac05794246dab614a7f01\n\nThere could be a test for the error \"Empty socket option\":\n\n```cpp\ncheck_bind(\"unix::max-connections=8,\", \"\", 0, \"Empty socket option\");\n```"
  },
  {
   "t": "2026-06-26T19:43:32Z",
   "kind": "review_comment",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/interface_ipc_init.py",
   "commit": "5d66053ff08f3d64a81f7bb99462a9a5ce475ada",
   "in_reply_to": null,
   "text": "In `ipc: test per-address connection limiting over unix sockets` 5d66053ff08f3d64a81f7bb99462a9a5ce475ada\n\nnit: checking for  \"file descriptors available\" seems unnecessary."
  },
  {
   "t": "2026-06-26T19:49:37Z",
   "kind": "review",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "5d66053ff08f3d64a81f7bb99462a9a5ce475ada",
   "text": "Concept ACK, this is a nice feature. Left a few comments"
  },
  {
   "t": "2026-06-29T13:57:13Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "f7c7b2335058eaa2dac339400dfcb799b76615f4"
  },
  {
   "t": "2026-06-29T14:08:18Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/libmultiprocess/include/mp/proxy-io.h",
   "commit": "b194acc106b50af2a97e5475845b46f31a5d91f3",
   "in_reply_to": 3482032064,
   "text": "Thanks, updated this in the upstream libmultiprocess PR https://github.com/bitcoin-core/libmultiprocess/pull/269 and squashed into this PR."
  },
  {
   "t": "2026-06-29T14:11:33Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/interfaces/ipc.h",
   "commit": "ddfc34b65ab8c38e33eac05794246dab614a7f01",
   "in_reply_to": 3483064497,
   "text": "Yes, looking at this, it isn't proper that the lower bound is 0 and the upper bound is not checked.\n\nChanged this to 1 for the lower bound and added an upper bound check.\n\nAlso, split the range check; this is not only good for the message specificity, but also makes it more readable\n\nThanks"
  },
  {
   "t": "2026-06-29T14:11:40Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "in_reply_to": 3483662291,
   "text": "Done, added"
  },
  {
   "t": "2026-06-29T14:12:13Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/interface_ipc_init.py",
   "commit": "5d66053ff08f3d64a81f7bb99462a9a5ce475ada",
   "in_reply_to": 3483736791,
   "text": "Yes, this is unecessary, i think i added this while testing and forgot to remove it.\n\nRemoved. Thanks"
  },
  {
   "t": "2026-06-29T14:20:03Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "3d74d45a8fd9ded49c32692743234bda3b6d0da1"
  },
  {
   "t": "2026-06-29T14:31:04Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "15d736f1e07bb78530a7aa52f5a22ef38c322c7c"
  },
  {
   "t": "2026-06-29T14:35:21Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Thanks for the review @ViniciusCestarii\n\nMade the changes suggested in the latest push"
  },
  {
   "t": "2026-06-30T09:09:34Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "Concept ACK.\n\nI would be could to explain in the PR description that the alternative, `-ipcmaxconnections`, won't let us set the limit per binding. That itself doesn't seem very useful now, but it might be when we expand IPC functionality. The `-ipcbind=<address>:max-connections=8` option can later be expanded to include a whitelist of interfaces / methods (like `-rpcwhitelist`), unix group name and chmod flags.\n\nIt's bit confusing that the PR description describes this as a \"Follow to https://github.com/bitcoin/bitcoin/pull/34978\", even though it doesn't build on it.\n\nThe subtree update is done incorrectly, which is presumably why the linter fails. I also prefer to do these in separate pull requests, unless changes are exclusively related to the change here, or it's obvious from the PR title that it involves such an update - neither is the case here.\n\nddd2e84346b10877c713bb7d383391c1ce2d860c could be split between introducing a default limit per connection and then the second commit that makes it configurable.\n\n`ParseBindAddress` is rather large. The name implies it's reusable for p2p / rpc bindings , but this PR doesn't do that, and I don't think there's much demand for it. It could still be justified based on the ability to expand it. I don't think the implementation needs to be in the header. Maybe add `node/ipc_args.{h,cpp}`.\n\nThe new default `DEFAULT_MAX_CONNECTIONS` limit (and how to override it) needs a release note."
  },
  {
   "t": "2026-06-30T09:29:32Z",
   "kind": "comment",
   "who": "Sjors",
   "assoc": "MEMBER",
   "text": "Also it looks like the subtree is based on https://github.com/bitcoin-core/libmultiprocess/pull/269, which is still open. So this PR should be draft."
  },
  {
   "t": "2026-07-02T11:52:34Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Thanks for the review @Sjors\n\nI agree with your point regarding the subtree update. I'm moving this to draft pending the merge of the standalone subtree PR. Once that lands, I will rebase this and apply all of your feedback"
  },
  {
   "t": "2026-07-11T06:51:44Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "3eefe9596b3db2bc2dbdd3cda94053467709903a"
  },
  {
   "t": "2026-07-11T11:29:53Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "dd316cec6c97d0f2400aaaace8bd8b939987cd84"
  },
  {
   "t": "2026-07-11T11:41:44Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "df43cb2374f3c42344715e8d3a8dafc68be1a837"
  },
  {
   "t": "2026-07-11T19:38:21Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314"
  },
  {
   "t": "2026-07-11T19:58:52Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Subtree PR adding the max connections PR has been merged and added to core https://github.com/bitcoin/bitcoin/pull/35684"
  },
  {
   "t": "2026-07-11T20:03:41Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\nUpdated the PR description to mention the alternative approach as why this approach was taken instead. Also removed mention of the followup as it does not build on it\n\n[quoted text omitted]\nSplit this to introduce the default limit per connection and another commit that makes it configurable\n\n[quoted text omitted]\nThe name did imply more applications than what it was intended to be used for. I have renamed it to `ParseIpcBindAddress` and moved into into the new `node/ipc_args.{h,cpp}` files\n\n[quoted text omitted]\nAdded the release notes in the latest commit"
  },
  {
   "t": "2026-07-11T20:04:00Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Once again moving this out of draft. Should be ready for review now. Thanks"
  },
  {
   "t": "2026-07-15T21:06:02Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "3b9075a0b67fbf4c6bd4e87579200252b7323565",
   "in_reply_to": null,
   "text": "In commit \"ipc: add default connection limit for ipcbind listeners\" (3b9075a0b67fbf4c6bd4e87579200252b7323565)\n\nI think this would be more readable if the comparison was simplified to `if (ipc_max_connections > MAX_IPC_FDS - ipc_bind)`. Also would consider renaming `ipc_bind` to `ipc_addresses`."
  },
  {
   "t": "2026-07-15T21:42:07Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "b5c72a4c4288c17188f34a689a6fbe578b523768",
   "in_reply_to": null,
   "text": "In commit \"ipc: support per-address max-connections on ipcbind\" (b5c72a4c4288c17188f34a689a6fbe578b523768)\n\nI think it would be good to change the colon to a comma here (`:max-connections=<n>` -> `,max-connections=<n>`) because this should work better with windows paths which include colons (`C:\\Bitcoin\\node.sock`). This would also be more similar to socat syntax."
  },
  {
   "t": "2026-07-15T21:54:27Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/interfaces/ipc.h",
   "commit": "3b9075a0b67fbf4c6bd4e87579200252b7323565",
   "in_reply_to": null,
   "text": "In commit \"ipc: add default connection limit for ipcbind listeners\" (3b9075a0b67fbf4c6bd4e87579200252b7323565)\n\nI think it would be nice if this took an `const node::IpcBindAddress&` so this interface could be future proof if new options are added."
  },
  {
   "t": "2026-07-15T21:59:55Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/node/ipc_args.h",
   "commit": "b5c72a4c4288c17188f34a689a6fbe578b523768",
   "in_reply_to": null,
   "text": "In commit \"ipc: support per-address max-connections on ipcbind\" (b5c72a4c4288c17188f34a689a6fbe578b523768)\n\nI think it probably makes more sense for this to live inside the IPC library than the node library. Would suggest renaming `node::IpcBindAddress` to `ipc::ListenAddress` and defining it inside an `src/ipc/types.h` file for external consumption similar to `src/node/types.h` and `src/wallet/types.h`.\n\nSimilarly, would suggest changing `node::ParseIpcBindAddress` to an `interfaces::Ipc::parseListenAddress` method.\n\nWould also suggest moving `interfaces::Ipc::DEFAULT_MAX_CONNECTIONS` to `ipc::DEFAULT_MAX_CONNECTIONS` in `src/ipc/types.h` using it to initialize the struct field `size_t max_connections{DEFAULT_MAX_CONNECTIONS}`\n\nThese changes would make it easier to add more options in the future without needing to change the `interfaces::Ipc` method signatures, and I think would organize code better."
  },
  {
   "t": "2026-07-15T22:09:16Z",
   "kind": "review",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "text": "Code review c6d2cd8d0c64ad9723f02d05e3924374a5b76314. I plan to review more but this looks like a nicely implemented change. I left a few suggestions below, none are too important or blocking, except I do really think the `:` options separator should be replaced by `,` to avoid problems with windows paths"
  },
  {
   "t": "2026-07-22T19:55:27Z",
   "kind": "review_comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_test.cpp",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "in_reply_to": null,
   "text": "I tried to run C++ tests and missed this suite because it's registered under a new name (`ipc_test`) different from the existing one (`ipc_tests`).  Suggest calling `IpcSocketMaxConnectionsTest` from the existing `ipc_tests` case in `ipc_tests.cpp` instead of adding a near-identically named suite, e.g.:\n\n```diff\ndiff --git a/src/ipc/test/ipc_test.cpp b/src/ipc/test/ipc_test.cpp\nindex b1e49df092..88f27231c2 100644\n--- a/src/ipc/test/ipc_test.cpp\n+++ b/src/ipc/test/ipc_test.cpp\n@@ -235,12 +235,3 @@ void IpcSocketMaxConnectionsTest(const fs::path& datadir)\n     BOOST_CHECK_EQUAL(addr2, address);\n     BOOST_CHECK_EQUAL(echo2, \"echo test 2\");\n }\n-\n-BOOST_FIXTURE_TEST_SUITE(ipc_test, BasicTestingSetup)\n-\n-BOOST_AUTO_TEST_CASE(ipc_socket_limit_test)\n-{\n-    IpcSocketMaxConnectionsTest(m_args.GetDataDirNet());\n-}\n-\n-BOOST_AUTO_TEST_SUITE_END()\ndiff --git a/src/ipc/test/ipc_tests.cpp b/src/ipc/test/ipc_tests.cpp\nindex 45f5f0a28c..3d194d8a7b 100644\n--- a/src/ipc/test/ipc_tests.cpp\n+++ b/src/ipc/test/ipc_tests.cpp\n@@ -17,6 +17,7 @@ BOOST_AUTO_TEST_CASE(ipc_tests)\n     IpcPipeTest();\n     IpcSocketPairTest();\n     IpcSocketTest(m_args.GetDataDirNet());\n+    IpcSocketMaxConnectionsTest(m_args.GetDataDirNet());\n }\n```\n\nThis also makes the `<test/util/setup_common.h>` include above unnecessary."
  },
  {
   "t": "2026-07-22T20:39:34Z",
   "kind": "review_comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "in_reply_to": null,
   "text": "According to Fable 5, this overflow check can be defeated in two ways:\n\n---\n\n_1. size_t underflow lets the aggregate check pass. When ipc_bind + ipc_max_connections lands exactly on MAX_IPC_FDS, the right side becomes 0 - 1 \u2192 SIZE_MAX, so any further entry is accepted and the static_cast<int> below wraps negative:_\n\n```\n./build/bin/bitcoin-node -regtest -ipcbind=unix:/tmp/a.sock:max-connections=2147483646 -ipcbind=unix:/tmp/b.sock:max-connections=2147483646\n...\n2026-07-22T20:29:26Z Reserving -2 file descriptors for IPC (2 listening sockets, -4 accepted connections)\n```\n_The node starts up with min_required_fds reduced by 2 instead of failing with \"Too many IPC file descriptors requested\"._\n\n_2. Even a single entry that passes the check crashes at startup. Keeping the IPC total \u2264 int max is not sufficient, because min_required_fds adds MIN_CORE_FDS + MAX_ADDNODE_CONNECTIONS + nBind on top, so the addition on L1101 overflows int (UB) and dies on an assert instead of a clean InitError:_\n\n```\n./build/bin/bitcoin-node -regtest -ipcbind=unix:/tmp/a.sock:max-connections=2147483646\nutil/fs_helpers.cpp:161 int RaiseFileDescriptorLimit(int): Assertion `min_fd >= 0' failed.\n```\n\n_Both would be solved by making MAX_IPC_FDS conservatively small instead of int max \u2014 even something like 1 << 20 is far beyond any realistic deployment and leaves all the downstream int arithmetic trivially safe \u2014 together with rearranging the check so the subtraction can't go below zero:_\n\n```diff\n-        if (bind->max_connections > MAX_IPC_FDS - ipc_bind - ipc_max_connections - 1) {\n+        if (bind->max_connections + 1 > MAX_IPC_FDS - ipc_bind - ipc_max_connections) {\n```\n\n_(max_connections is parse-capped at 2147483647, so the + 1 cannot overflow.)_\n\n---\n\nI verified the diff locally and:\n\n- Repro 1 now fails with \"Too many IPC file descriptors requested\" and the tests pass.\n- Repro 2 however still hits the assertion. It needs a smaller `MAX_IPC_FDS`, and the parse-level cap in `ParseIpcBindAddress` may want to match the chosen bound so users get the clearer \"max-connections must be at most N\" error at parse time."
  },
  {
   "t": "2026-07-22T21:24:21Z",
   "kind": "review_comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/interface_ipc_init.py",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": null,
   "text": "In commit 2b3c6ddd6cbfbc140eb92f8db6142001ec969d59: _\"ipc: test per-address connection limiting over unix sockets\"_\n\nIt would be great to cover it in functional tests as well:\n\n```diff\ndiff --git a/test/functional/interface_ipc_init.py b/test/functional/interface_ipc_init.py\nindex a2ef23b6aa..551bb43abe 100755\n--- a/test/functional/interface_ipc_init.py\n+++ b/test/functional/interface_ipc_init.py\n@@ -4,7 +4,9 @@\n # file COPYING or http://www.opensource.org/licenses/mit-license.php.\n \"\"\"Test IPC initialization behavior.\"\"\"\n\n+import socket\n import tempfile\n+import time\n from pathlib import Path\n\n from test_framework.test_framework import BitcoinTestFramework\n@@ -54,8 +56,35 @@ class IPCInitTest(BitcoinTestFramework):\n             expected_msg=f\"Error: Invalid -ipcbind address 'unix:{self.ipcbind_path}:max-connections=2147483648': max-connections must be at most 2147483647\",\n         )\n\n+    def test_ipcbind_connection_limiting(self):\n+        self.log.info(\"Test -ipcbind max-connections limiting over the socket\")\n+        node = self.nodes[0]\n+        self.restart_node(0, extra_args=[f\"-ipcbind=unix:{self.ipcbind_path}:max-connections=1\", \"-debug=ipc\"])\n+\n+        def ipc_client():\n+            client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)\n+            client.connect(str(self.ipcbind_path))\n+            return client\n+\n+        # First client takes the only one (max-connections=1) slot.\n+        with node.assert_debug_log([\"IPC server: socket connected.\"], timeout=5):\n+            first = ipc_client()\n+\n+        # Second client tries to connect but should not be accepted while the first one occupies the slot.\n+        with node.assert_debug_log([], unexpected_msgs=[\"IPC server: socket connected.\"]):\n+            second = ipc_client()\n+            time.sleep(0.5)  # give some chance\n+\n+        # The second client must be accepted right after freeing up the slot.\n+        with node.assert_debug_log([\"IPC server: socket disconnected.\", \"IPC server: socket connected.\"], timeout=5):\n+            first.close()\n+\n+        with node.assert_debug_log([\"IPC server: socket disconnected.\"], timeout=5):\n+            second.close()\n+\n     def run_test(self):\n         self.test_ipcbind_max_connections()\n+        self.test_ipcbind_connection_limiting()\n\n if __name__ == '__main__':\n```\n\nPlus, having a per-address case with two addresses, each with its own limits, works well because that's what the commit mentions."
  },
  {
   "t": "2026-07-22T23:27:58Z",
   "kind": "review_comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "in_reply_to": null,
   "text": "\"X accepted connections\" reads like already accepted at startup when it actually means capacity.\n\nMaybe `Reserving %d file descriptors for IPC (%d listening sockets, %d connection slots)` reads more precisely?"
  },
  {
   "t": "2026-07-23T01:01:06Z",
   "kind": "review_comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "in_reply_to": null,
   "text": "With the updates introduced by this PR, it's now very easy to trigger this error, say, by setting a large `max-connections` value:\n\n```\n$ ./build/bin/bitcoin-node -regtest -ipcbind=unix::max-connections=1000\nError: Not enough file descriptors available. 1024 available, 1161 required.\n```\n\nThis message doesn\u2019t indicate that the user's `max-connections` setting is the root of the problem, and understanding the connection between these numbers requires some knowledge of how internal fd accounting works. It might be helpful to explicitly mention the IPC contribution in the message or log the line \"Reserving N file descriptors for IPC\" before the error occurs, so users have better insight into what\u2019s happening."
  },
  {
   "t": "2026-07-23T02:39:14Z",
   "kind": "review",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "text": "Concept ACK. Limiting IPC connections per listener makes sense.\n\nTested manually on macOS and Linux by exercising the limit over the socket with raw and real clients, checking per-address behavior with multiple listeners, and running the new unit and functional tests.\n\nLeft a few comments and suggestions. I'm planning to review the code more deeply, but I can confirm the core feature works as expected."
  },
  {
   "t": "2026-07-23T02:55:15Z",
   "kind": "comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "text": "With the updates in this PR, a single `-ipcbind` value can silently reduce the automatic P2P connection slots to zero.\u00a0For example,\n```\n$ ./build/bin/bitcoin -m node -signet -ipcbind=unix::max-connections=863\nWarning: Reducing -maxconnections from 125 to 0, because of system limitations.\n...\n2026-07-23T00:22:52Z 64 addresses found from DNS seeds\n```\n\nHere, the IPC reservation is deducted from the fd budget before automatic P2P connections are allocated. If `max-connections` is set close to the platform's fd cap, there may be no room left for automatic P2P connections (the exact limit varies by platform).\u00a0The node completes startup and even fetches addresses from DNS seeds, but never makes or accepts peer connections.\u00a0On mainnet, this means it would stop following the chain after that single warning log at startup.\n\nThis (warning-only) behavior when `maxconnections` hits 0 is a pre-existing issue, so I don't think it's a blocker for this PR. A follow-up could make it an `InitError` when the user didn't explicitly set `-maxconnections=0`."
  },
  {
   "t": "2026-07-23T10:39:12Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "19159980f4ea9f96d230c4fd44a55e024b61c413"
  },
  {
   "t": "2026-07-23T10:43:38Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "5a7d7e4d4df2e448d50ebcb3d622c6cc1d5d8549"
  },
  {
   "t": "2026-07-23T11:54:30Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "3b9075a0b67fbf4c6bd4e87579200252b7323565",
   "in_reply_to": 3590741088,
   "text": "Done. I renamed ipc_bind to `ipc_addresses` and simplified the default  limit comparison to use the aggregate connection count in this commit. This changes a bit in the subsequent commit, but this change is nice to have here as well"
  },
  {
   "t": "2026-07-23T11:54:33Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "b5c72a4c4288c17188f34a689a6fbe578b523768",
   "in_reply_to": 3590927396,
   "text": "Addressed. socket options now use a comma separator, updated the PR description as well"
  },
  {
   "t": "2026-07-23T11:54:36Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/interfaces/ipc.h",
   "commit": "3b9075a0b67fbf4c6bd4e87579200252b7323565",
   "in_reply_to": 3590991937,
   "text": "Done, `listenAddress()` now takes a `const ipc::ListenAddress&`,"
  },
  {
   "t": "2026-07-23T11:54:39Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/node/ipc_args.h",
   "commit": "b5c72a4c4288c17188f34a689a6fbe578b523768",
   "in_reply_to": 3591022415,
   "text": "Adddressed the suggestion here. Thanks\n\nI tried a few locations for the parser implementation. Defining the static method in `src/ipc/interfaces.cpp` caused undefined references linker errors\n\nI also tried making parsing a virtual method implemented by the concrete IPC class. That resolved the linker errors but required additional plumbing in the interface and `init.cpp` which seemed too intrusive.\n\nPlacing it in the general `common/interfaces.cpp` implementation linked correctly but felt unrelated to that file\u2019s responsibilities.\n\nI ultimately kept the implementation in a specific `src/ipc/listen.cpp` and compiled that file into `bitcoin_common`, which is available to the init consumers.\n\nI\u2019m open to changing the target or implementation location if there is a cleaner way to keep it in ipc/interfaces.cpp without introducing the linker or interface plumbing issues above"
  },
  {
   "t": "2026-07-23T12:34:27Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_test.cpp",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "in_reply_to": 3633368541,
   "text": "Done thanks. Removed the `ipc_test` so that IpcSocketMaxConnectionsTest() is now called from the existing `ipc_tests` test case,"
  },
  {
   "t": "2026-07-23T12:34:30Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "in_reply_to": 3633643762,
   "text": "Good catch. I agree that using int max here was not very safe because min_required_fds adds other FD reservations afterward.\n\nI took your suggestion and capped IPC connections at 1 << 20, applied the same limit during parsing, and changed the aggregate check to avoid unsigned underflow. I also added boundary and multi-address regression tests"
  },
  {
   "t": "2026-07-23T12:34:32Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "test/functional/interface_ipc_init.py",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": 3633914411,
   "text": "Done. I used your suggested functional test with slight modifications to cover two listeners, verifying that each listener enforces its limit independently and accepts its waiting client after a slot is freed."
  },
  {
   "t": "2026-07-23T12:34:45Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "in_reply_to": 3634609618,
   "text": "Done, changed the log and help text to use \"connection slots\""
  },
  {
   "t": "2026-07-23T12:34:49Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "c6d2cd8d0c64ad9723f02d05e3924374a5b76314",
   "in_reply_to": 3634907642,
   "text": "Done thanks. Made the preceding IPC log clearer by reporting listening sockets and connection slots."
  },
  {
   "t": "2026-07-23T12:39:22Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nI agree with this, and it is worth fixing, but it seems broader than this PR because the warning-only behavior is pre existing and can result from non ipc fd pressure too. I left it unchanged here, btu this would be good for a followup"
  },
  {
   "t": "2026-07-23T12:43:32Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Thanks for the reviews, @ryanofsky and @xyzconstant. I\u2019ve addressed the suggestions and updated the PR description accordingly."
  },
  {
   "t": "2026-07-23T18:33:03Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nChanged the option separator to `,`. Microsoft documents Windows AF_UNIX pathname sockets as using [Win32 filesystem paths](https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/) (https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/), which may contain a drive-letter colon such as C:\\.\n\nLooking more closely, I don\u2019t think an ordinary Windows path would have broken the previous parser. It used `rfind(':')`, followed by this check:\n\n```\nconst std::string_view options_view{address_view.substr(option_pos + 1)};\nif (options_view.empty() || options_view.find_first_of(\"=,\") == std::string_view::npos) {\n    return IpcBindAddress{std::move(address), DEFAULT_MAX_CONNECTIONS};\n}\n```\nFor `unix:C:\\bitcoin\\node.sock`, it would find the C: colon but then preserve the complete address because the remaining text contains no option syntax. For `unix:C:\\bitcoin\\node.sock:max-connections=8`, rfind(':') would select the final colon before max-connections.\n\nSo I agree the colon syntax was ambiguous and fragile, especially if more options are added. Still, I don\u2019t think it would have broken ordinary Windows drive-letter paths with the existing parser."
  },
  {
   "t": "2026-07-23T18:49:32Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "65214d870d3b4e27889ffc05920291904e637f99"
  },
  {
   "t": "2026-07-28T20:48:43Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "21378ce132a94c49d9eb62a0aa14c5b98f533458",
   "in_reply_to": null,
   "text": "In commit \"ipc: support per-address max-connections on ipcbind\" (21378ce132a94c49d9eb62a0aa14c5b98f533458)\n\nSeems a little unexpected to subtract. Also seems like this could be simplified by adding to the totals earlier like:\n\n```c++\nipc_addresses += 1;\nipc_max_connections += listen_address->max_connections;\nif (ipc_addressess + ipc_max_connections > MAX_IPC_FDS) { InitError(...); }\n```"
  },
  {
   "t": "2026-07-28T21:16:56Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/node/ipc_args.h",
   "commit": "b5c72a4c4288c17188f34a689a6fbe578b523768",
   "in_reply_to": 3591022415,
   "text": "re: https://github.com/bitcoin/bitcoin/pull/35037#discussion_r3591022415\n\nThanks, the approach taken seems ok. My suggestion was to make the `Ipc::parseListenAddress` implementation live in the `bitcoin_ipc` library in a virtual method. This would add a small amount of extra plumbing as you mentioned, but I think not very much, and this would match the way other functions of the IPC library (`spawnProcess`, `connectAddress` etc) are exposed to bitcoin core.\n\nThe reason for making these functions virtual is to keep `bitcoind` free of IPC dependencies, and allow IPC code to access libmultiprocess and capnproto functions which are not allowed to be accessed directly by the rest of bitcoin core code.\n\nThe approach taken in 65214d870d3b4e27889ffc05920291904e637f99 is reasonable, but has a a few drawbacks compared to the suggested approach. `parseListenAddress` code is linked into `bitcoin_common` library instead of `bitcoin_ipc` so it can't call other IPC functions or libmultiprocess or capnproto code. Also `parseListenAddress` is linked into bitcoind even though it can never be called by it.\n\nCurrent code is fine. Just wanted to explain rationale behind the suggestion."
  },
  {
   "t": "2026-07-28T21:40:18Z",
   "kind": "review",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "65214d870d3b4e27889ffc05920291904e637f99",
   "text": "Code review ACK 65214d870d3b4e27889ffc05920291904e637f99. Looks great! This fixes a gap in descriptor accounting, and adds a helpful connection limiting feature, and is nicely implemented. I didn't review the tests very closely and plan to look more at them, but all of the non-test changes look good."
  },
  {
   "t": "2026-07-28T21:42:54Z",
   "kind": "comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "text": "re: https://github.com/bitcoin/bitcoin/pull/35037#issuecomment-5062000336\n\nGood point the previous requirement for options to contain `=` characters would have prevented the previous implementation from having problems with windows drive letters in practice. Still I think it's nice that you switched to commas to match socat syntax more, and allow a little more flexibility in the future."
  },
  {
   "t": "2026-07-31T15:29:26Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "f4fb7169d2b4f8b292d89971ae378a9ad2c68b37"
  },
  {
   "t": "2026-07-31T15:30:44Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "21378ce132a94c49d9eb62a0aa14c5b98f533458",
   "in_reply_to": 3669073524,
   "text": "Updated as suggested. The listener and connection totals are now incremented before checking the aggregate. I also updated the comment to reflect that the change"
  },
  {
   "t": "2026-07-31T15:41:45Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "b822c1d727d04f783edc09c9cc56085d00daef51"
  },
  {
   "t": "2026-07-31T15:46:21Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Resolved some rebase conflicts after https://github.com/bitcoin/bitcoin/pull/35084 got merged"
  },
  {
   "t": "2026-08-03T08:24:11Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "52bf2492cd93399a86690943fb8551e8edef26b6"
  },
  {
   "t": "2026-08-03T08:37:52Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "04593a16562606ae81b9d4f585c2359c794937d0"
  },
  {
   "t": "2026-08-03T08:55:10Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Updated the parser to only split the unix socket address when it finds the recognized `,max-connections=` option. Previously, it split on any comma, which broke valid socket paths containing commas.\n\nI also added tests to make sure commas are preserved in paths while `max-connections` is still parsed correctly."
  },
  {
   "t": "2026-08-11T08:37:49Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "70b2988c0900aa4ab0f8491799f27e5b1c8394f7",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/776368e8e44ce780155e89a8f069ad640a1db402:\n\nI don't see why this check could not be done outside the loop when the total `ipc_addresses` and `ipc_max_connections` are known."
  },
  {
   "t": "2026-08-11T08:40:15Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/776368e8e44ce780155e89a8f069ad640a1db402:\n\nLooks like the same addresses from `-ipcbind` are being parsed twice. We should be able to collect the parsed addresses into a vector and use them here."
  },
  {
   "t": "2026-08-11T10:47:43Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "05bf362fd35abc7876c9d878866e4a9c2ff84017",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/ccd27feb6e94f26756872ff22ec6121306912961:\n\nThe current implementation will accept `unix:path,backup.sock=1` as valid when it should fail with `Unknown socket option 'backup.sock'`.\nI think any `,`  in the sock file path should be escaped, so we can reliably match option parameters."
  },
  {
   "t": "2026-08-11T10:48:41Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/ccd27feb6e94f26756872ff22ec6121306912961:\n\n`unix:,max-connections` will not fail with \"Missing value for max-connections option\""
  },
  {
   "t": "2026-08-11T10:50:04Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "04593a16562606ae81b9d4f585c2359c794937d0",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/ccd27feb6e94f26756872ff22ec6121306912961:\n\nUse `BOOST_REQUIRE_MESSAGE(listen_address, util::ErrorString(listen_address).original);` instead to provide the error string for debugging."
  },
  {
   "t": "2026-08-11T10:50:58Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/ccd27feb6e94f26756872ff22ec6121306912961:\n\nAnother useful testcase is `check_listen_address(\"unix:,max-connections=2,max-connections=1\", \"unix:\", 1, \"\");`"
  },
  {
   "t": "2026-08-11T10:58:08Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/listen.cpp",
   "commit": "04593a16562606ae81b9d4f585c2359c794937d0",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/776368e8e44ce780155e89a8f069ad640a1db402:\n\nConsider this diff\n```diff\ndiff --git a/src/ipc/listen.cpp b/src/ipc/listen.cpp\nindex e19b4b79fe..fc2b90b300 100644\n--- a/src/ipc/listen.cpp\n+++ b/src/ipc/listen.cpp\n@@ -59,29 +59,27 @@ util::Result<ipc::ListenAddress> Ipc::parseListenAddress(std::string address)\n         const std::string_view value{\n             equals == std::string_view::npos ? std::string_view{} : option.substr(equals + 1)};\n\n-        if (name == \"max-connections\") {\n-            if (value.empty()) {\n-                return util::Error{Untranslated(\"Missing value for max-connections option\")};\n-            }\n-\n-            int64_t parsed_limit{-1};\n-            const auto [last, ec]{std::from_chars(value.data(), value.data() + value.size(), parsed_limit)};\n-\n-            if (ec != std::errc{} ||\n-                last != value.data() + value.size()) {\n-                return util::Error{Untranslated(\"Invalid max-connections value '\" + std::string{value} + \"'\")};\n-            }\n-            if (parsed_limit < 1) {\n-                return util::Error{Untranslated(\"max-connections must be at least 1\")};\n-            }\n-            if (parsed_limit > static_cast<int64_t>(ipc::MAX_CONNECTIONS)) {\n-                return util::Error{Untranslated(\"max-connections must be at most \" + util::ToString(ipc::MAX_CONNECTIONS))};\n-            }\n-\n-            listen_address.max_connections = static_cast<size_t>(parsed_limit);\n-        } else {\n-            return util::Error{Untranslated(\"Unknown socket option '\" + std::string{name} + \"'\")};\n+        if (name != \"max-connections\") {\n+            return util::Error{Untranslated(strprintf(\"Unknown socket option '%s'\", name))};\n         }\n+        if (value.empty()) {\n+            return util::Error{Untranslated(\"Missing value for max-connections option\")};\n+        }\n+\n+        int64_t parsed_value{-1};\n+        const auto [last, ec]{std::from_chars(value.begin(), value.end(), parsed_value)};\n+\n+        if (ec != std::errc{} || last != value.end()) {\n+            return util::Error{Untranslated(\"Invalid max-connections value '\" + std::string{value} + \"'\")};\n+        }\n+        if (parsed_value < 1) {\n+            return util::Error{Untranslated(\"max-connections must be at least 1\")};\n+        }\n+        if (parsed_value > static_cast<int64_t>(ipc::MAX_CONNECTIONS)) {\n+            return util::Error{Untranslated(\"max-connections must be at most \" + util::ToString(ipc::MAX_CONNECTIONS))};\n+        }\n+\n+        listen_address.max_connections = static_cast<size_t>(parsed_value);\n\n         if (end == std::string_view::npos) break;\n         next = end + 1;\n```"
  },
  {
   "t": "2026-08-11T11:06:31Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/types.h",
   "commit": "04593a16562606ae81b9d4f585c2359c794937d0",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/446ae5ddbd57e3bbbbdfa3133baaa3cb842c5038:\n\nnit: I found the phrase `int-based initialization accounting` confusing. I assume it refers to the code deciding how many FDs to reserve, but it seems like a weird way to describe it. I think just writing `This conservative bound leaves ample room for other file descriptor reservations.` is enough. The term \"int-based min_required_fds\" also used in `src/init.cpp` is also weird."
  },
  {
   "t": "2026-08-15T18:55:33Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "cd3ae326d24e3cc40154a5a21077cf7e1f9e4e8f"
  },
  {
   "t": "2026-08-15T18:59:23Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "6ace89e3537ce34cc12e662a6bd618ea78fb66b8"
  },
  {
   "t": "2026-08-15T19:03:49Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "79442c45f43e661707ec48608d804ac8e9c7332e"
  },
  {
   "t": "2026-08-15T19:12:58Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "f13aecee44ff69e6bdee5ff4f01c7dfff30587bc"
  },
  {
   "t": "2026-08-15T19:19:29Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "34177bb2fc784ba3a09d94efefd3cd63776e27b4"
  },
  {
   "t": "2026-08-15T19:20:27Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "70b2988c0900aa4ab0f8491799f27e5b1c8394f7",
   "in_reply_to": 3756428660,
   "text": "This is a good point. Checking it outside the loop would be simpler.\n\nBut I think it's better to keep it inside so initialization stops as soon as the total goes over the limit and the running totals remain bounded."
  },
  {
   "t": "2026-08-15T19:20:48Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": 3756442719,
   "text": "Parsing once would avoid repeating the work and would let us reuse the same parsed values.\n\nHowever, the two parses happen in separate startup stages. Keeping the values would require adding temporary state and passing it through more paths. Since parsing these short strings is cheap and always gives the same result,\n\nI think parsing twice keeps this change simpler?"
  },
  {
   "t": "2026-08-15T19:29:14Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "47d7fae5e7350c8492f5fea0ab70bb8148c639b6"
  },
  {
   "t": "2026-08-15T19:29:34Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": 3757265762,
   "text": "Thanks. I updated the parser so `unix:,max-connections` is recognized as a supported option without a value and returns the expected `missing-value` error.\n\nI also added a unit test for this change"
  },
  {
   "t": "2026-08-15T19:31:53Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "05bf362fd35abc7876c9d878866e4a9c2ff84017",
   "in_reply_to": 3757259791,
   "text": "I understand the suggestion, escaping commas would help us tell the socket path and options apart.\n\nThe problem is that unix filenames can contain commas and equals signs. This means `unix:path,backup.sock=1` could be a real socket path, not an option. If we require commas to be escaped, paths that worked before this change could stop working.\n\nTo avoid breaking those paths, the options parsing only starts when it finds `,max-connections`. If that text is not present, the whole address, including any commas, is treated as the socket filename.\n\nFor that reason, I would prefer to keep accepting this address as a valid path."
  },
  {
   "t": "2026-08-15T19:32:31Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "04593a16562606ae81b9d4f585c2359c794937d0",
   "in_reply_to": 3757274525,
   "text": "Done, changed this to make debugging failures easier"
  },
  {
   "t": "2026-08-15T19:32:33Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "in_reply_to": 3757280213,
   "text": "Thanks, added the test case"
  },
  {
   "t": "2026-08-15T19:32:38Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/listen.cpp",
   "commit": "04593a16562606ae81b9d4f585c2359c794937d0",
   "in_reply_to": 3757326108,
   "text": "Thanks, this makes the validation flatter and easier to follow. I applied the suggested change."
  },
  {
   "t": "2026-08-15T19:32:44Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/types.h",
   "commit": "04593a16562606ae81b9d4f585c2359c794937d0",
   "in_reply_to": 3757381836,
   "text": "I agreed the wording was more complicated than needed. I simplified both comments to refer directly to leaving room for other file descriptor reservations. Thanks"
  },
  {
   "t": "2026-08-15T19:36:01Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Thanks for the review @Eunovo. Addressed the suggestions in the latest commits"
  },
  {
   "t": "2026-08-17T06:12:15Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": 3756442719,
   "text": "True, it seems the effort required to cache the parsed values is not worth the gain."
  },
  {
   "t": "2026-08-17T06:20:45Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/capnp/protocol.cpp",
   "commit": "47d7fae5e7350c8492f5fea0ab70bb8148c639b6",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/47d7fae5e7350c8492f5fea0ab70bb8148c639b6:\n\nI think this change belongs in a previous commit"
  },
  {
   "t": "2026-08-17T06:22:22Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "doc/release-notes-35037.md",
   "commit": "47d7fae5e7350c8492f5fea0ab70bb8148c639b6",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/47d7fae5e7350c8492f5fea0ab70bb8148c639b6:\n\nProbably best to use a path in the example, like `-ipcbind=unix:/path_to_socket_file.sock,max-connections=8`."
  },
  {
   "t": "2026-08-17T06:33:01Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "47d7fae5e7350c8492f5fea0ab70bb8148c639b6",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/7bc9eb98ff8f6398676e5c074afbd7bcc9652720:\n\nI worry that this error message is not meaningful/useful to the user. Something like:\n`Too many IPC file descriptors requested: <ipc_addresses + ipc_max_connections>  -ipcbind listeners and connection slots exceed the limit of <MAX_IPC_FDS>. Reduce the number of -ipcbind addresses or their max-connections values` is more useful. It tells the user the limit and tells them what to do."
  },
  {
   "t": "2026-08-17T10:20:10Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "bff77fbfe4b2fde7838361ce20a6dc38e40ac7ae"
  },
  {
   "t": "2026-08-17T10:20:51Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/capnp/protocol.cpp",
   "commit": "47d7fae5e7350c8492f5fea0ab70bb8148c639b6",
   "in_reply_to": 3794188829,
   "text": "Yes it is, thanks for spotting this, moved it to 63905de3dc."
  },
  {
   "t": "2026-08-17T10:21:33Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "doc/release-notes-35037.md",
   "commit": "47d7fae5e7350c8492f5fea0ab70bb8148c639b6",
   "in_reply_to": 3794195309,
   "text": "Done, this makes the example clearer. Thanks"
  },
  {
   "t": "2026-08-17T10:22:42Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "47d7fae5e7350c8492f5fea0ab70bb8148c639b6",
   "in_reply_to": 3794239067,
   "text": "I agree this is a bit too concise for am error message. I have updated this as requested to show the requested total and the limit, and to explain how the user can reduce the request."
  },
  {
   "t": "2026-08-17T10:26:04Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "5e6b6cfe6c7c1245e2846c8e3cb1a71c145a3778"
  },
  {
   "t": "2026-08-17T10:45:59Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "f466d0f4bb6b70b4dc534de78b6c2998ab0a6a96"
  },
  {
   "t": "2026-08-19T09:45:56Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "text": "ACK https://github.com/bitcoin/bitcoin/pull/35037/commits/f466d0f4bb6b70b4dc534de78b6c2998ab0a6a96\n\nI'm mostly fine with this PR except for the ',' escape issue mentioned in https://github.com/bitcoin/bitcoin/pull/35037#discussion_r3757259791, but I understand that just checking for  `,max-connections` serves our current needs."
  },
  {
   "t": "2026-08-26T14:23:49Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "b9131ff7ffb5a7c938ed64f98b2dec0942310b7c"
  },
  {
   "t": "2026-08-26T14:25:39Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Rebased on the latest master and resolved the initialization conflict by integrating IPC file descriptor reservations into the updated `total_fds` and `min_required_fds` calculations. force pushed the updated branch"
  },
  {
   "t": "2026-08-28T20:00:30Z",
   "kind": "review_comment",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/types.h",
   "commit": "f3bc4a4862bfa2c72d8605cc113240b8a34512e7",
   "in_reply_to": null,
   "text": "In \"ipc: support per-address max-connections options on -ipcbind\" f3bc4a4862bfa2c72d8605cc113240b8a34512e7\n\nMAX_CONNECTIONS is too high and fails at startup with an error about fd limit. I can't see it having more than 100 connections and I believe a better MAX_CONNECTIONS value would be around 256.\n\nnit: maybe would be better to rename this variable to `MAX_MAX_CONNECTIONS` or `MAX_CONNECTIONS_LIMIT`"
  },
  {
   "t": "2026-08-28T20:07:36Z",
   "kind": "review_comment",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": null,
   "text": "In \"ipc: support per-address max-connections options on -ipcbind\" d2bb6f27dfbcba9dcc3817af16b421fc06f8339f\n\nThis regresses the listener log line:\n\nbefore:\n```\nListening for IPC requests on address unix:/home/vinicius/.bitcoin/regtest/node.sock\n```\n\nafter:\n```\nListening for IPC requests on address unix\n```\n\nIpc::listenAddress was setting the address value to the full path but with these changes it doens't update it anymore and the InitError and LogInfo will print just the arg -ipcbind that was passed."
  },
  {
   "t": "2026-08-28T20:09:41Z",
   "kind": "review",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "b9131ff7ffb5a7c938ed64f98b2dec0942310b7c",
   "text": "Looking good. Added 2 comments."
  },
  {
   "t": "2026-08-29T07:55:06Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "70b2988c0900aa4ab0f8491799f27e5b1c8394f7"
  },
  {
   "t": "2026-08-29T07:56:48Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": 3883706613,
   "text": "Good catch. I missed that `listenAddress` was passing a copy of the address to the bind method The resolved path was therefore discarded, leaving the log and error message with only the original value, such as unix, which is less useful for debugging.\n\nI changed `listenAddress` to update `ListenAddress::address` directly, so the resolved socket path is now available to both the log and bind error message.\n\nA larger change could make `listenAddress` return the resolved address or store the configured and resolved addresses separately. Still, I think updating the existing object is the smallest change that restores the previous behavior.\n\nThanks for spotting this"
  },
  {
   "t": "2026-08-29T07:56:51Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/types.h",
   "commit": "f3bc4a4862bfa2c72d8605cc113240b8a34512e7",
   "in_reply_to": 3883644498,
   "text": "Thanks. I agree that the maximum should be lower and have changed it to 256.\n\nI kept the name because it is already scoped as `ipc::MAX_CONNECTIONS`, and the comment above it explains that it is the maximum accepted limit. I found `MAX_MAX_CONNECTIONS` less clear."
  },
  {
   "t": "2026-08-29T07:58:55Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Addressed comment made by @ViniciusCestarii"
  },
  {
   "t": "2026-08-31T19:57:53Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "05bf362fd35abc7876c9d878866e4a9c2ff84017",
   "in_reply_to": 3757259791,
   "text": "In commit \"ipc: support per-address max-connections on ipcbind\" (63648ac870371e345c944a5c39edd28064eb7660)\n\nre: https://github.com/bitcoin/bitcoin/pull/35037#discussion_r3790097164\n\n[quoted text omitted]\nIMO the previous solution in 21378ce132a of splitting on commas with `address.find(',')` was better than the current one of splitting with `address.find(MAX_CONNECTIONS_OPTION)` because:\n\n- Previous code made it straightforward to support new options, while current code does not seem to generalize.\n- Previous code was consistent in not allowing commas in socket path. Current code allows some commas in paths but not others.\n\nI do think it would be good to allow commas and other special characters in paths, but the reliable way to do that would be to use escaping as Eunovo suggested. It's be easy to support that by calling [`UrlDecode'](https://github.com/bitcoin/bitcoin/blob/fe3c92cfe0da39d7f34ee3e11fee056b141afd0e/src/common/url.h#L11-L15) on the parsed path without having to complicate parsing code. (URL escaping would work better than backslash escaping here because of the backslashes in windows paths.)"
  },
  {
   "t": "2026-08-31T20:16:09Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "63648ac870371e345c944a5c39edd28064eb7660",
   "in_reply_to": null,
   "text": "In commit \"ipc: support per-address max-connections on ipcbind\" (63648ac870371e345c944a5c39edd28064eb7660)\n\nError message might be a little more informative if this check was moved after the loop, otherwise the ipc_addresses and ipc_max_connections values shown are incomplete"
  },
  {
   "t": "2026-08-31T20:29:35Z",
   "kind": "review",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "70b2988c0900aa4ab0f8491799f27e5b1c8394f7",
   "text": "Code review ACK 70b2988c0900aa4ab0f8491799f27e5b1c8394f7. Still looks good! And better now with the feedback from other reviewers avoiding overflows and restoring the detailed listening log line. I do think the previous parsing code was a little better and simpler and I left a suggestion below about escaping commas, but it's not important."
  },
  {
   "t": "2026-09-01T10:45:48Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "05bf362fd35abc7876c9d878866e4a9c2ff84017"
  },
  {
   "t": "2026-09-01T10:45:49Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "05bf362fd35abc7876c9d878866e4a9c2ff84017",
   "in_reply_to": 3757259791,
   "text": "Thanks, this addresses my concern because commas can still be represented in socket paths, while the parser can consistently treat a comma as the start of the options.\n\nUpdated to use the previous solution"
  },
  {
   "t": "2026-09-01T10:46:11Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "63648ac870371e345c944a5c39edd28064eb7660",
   "in_reply_to": 3898013310,
   "text": "That makes sense. I initially kept the check inside the loop so it would stop as soon as the limit was exceeded.\n\nSince the error now reports the requested total, using the complete values is more useful. I moved the check after the loop"
  },
  {
   "t": "2026-09-01T11:05:22Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "7a839565cae797e87c43dc483066d47c2dffc568"
  },
  {
   "t": "2026-09-01T11:35:37Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Thanks for the review @ryanofsky, Addressed the comments in the latest push"
  },
  {
   "t": "2026-09-01T14:04:27Z",
   "kind": "review",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "7a839565cae797e87c43dc483066d47c2dffc568",
   "text": "ACK 7a839565cae797e87c43dc483066d47c2dffc568\n\nnit: the first commit sets MAX_CONNECTIONS and updates the call site and ipc->listenAddress log, but the second commit overrides these changes. I believe instead of overriding it could fit on the first commit."
  },
  {
   "t": "2026-09-08T16:56:47Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/init.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": null,
   "text": "In commit \"ipc: add default connection limit for ipcbind listeners\" (f3bc4a4862bfa2c72d8605cc113240b8a34512e7)\n\nNote: MAX_CONNECTIONS is highest number that's allowed to be specified in a max-connection option for one IPC listening address. It's possible to have one listening address though typical to have one, so makes sense not multiply this to account for multiple listening addresses. This MAX_CONNECTIONS value is also 256 and significantly larger than the default number of connections typically allowed, which is DEFAULT_MAX_CONNECTIONS or 16, so that is another reason not to multiply. The +1 also makes sense to account for the file descriptor used to accept connections."
  },
  {
   "t": "2026-09-08T17:06:04Z",
   "kind": "review_comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "path": "src/ipc/listen.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": null,
   "text": "In commit \"ipc: support per-address max-connections on ipcbind\" (f23800fe6d5c0370a141a011524afa2ee1b63db2)\n\nPlease ignore this comment unless making other updates, but I think this parsing logic could be easier to read and maintain if it was using `SplitString` and `ParseIntOption` helper functions, more like:\n\n```c++\n    const std::string_view address_view{address};\n    const size_t option_pos{address.find(',')};\n    ipc::ListenAddress listen_address{\n        .address = UrlDecode(address_view.substr(0, option_pos)),\n    };\n    if (option_pos != std::string::npos) {\n        for (const std::string& option_str : SplitString(address_view.substr(option_pos + 1), ',')) {\n            const std::string_view name{std::string_view{option_str}.substr(0, eq)};\n            const std::string_view value{eq == std::string::npos ? std::string_view{} : std::string_view{option_str}.substr(eq + 1)};\n\n            if (name == \"max-connections\") {\n                auto parsed{ParseIntOption(name, value, 1, static_cast<int64_t>(ipc::MAX_CONNECTIONS))};\n                if (!parsed) return util::Error{util::ErrorString(parsed)};\n                listen_address.max_connections = static_cast<size_t>(*parsed);\n            } else {\n                return util::Error{Untranslated(strprintf(\"Unknown socket option '%s'\", name))};\n            }\n        }\n    }\n\n    return listen_address;\n```\n\n```c++\n//! Parse an integer option value in [min_val, max_val].\nutil::Result<int64_t> ParseIntOption(std::string_view name, std::string_view value, int64_t min_val, int64_t max_val)\n{\n    if (value.empty()) return util::Error{Untranslated(strprintf(\"Missing value for %s option\", name))};\n    const auto parsed{ToIntegral<int64_t>(value)};\n    if (!parsed) return util::Error{Untranslated(strprintf(\"Invalid %s value '%s'\", name, value))};\n    if (*parsed < min_val) return util::Error{Untranslated(strprintf(\"%s must be at least %d\", name, min_val))};\n    if (*parsed > max_val) return util::Error{Untranslated(strprintf(\"%s must be at most %s\", name, util::ToString(max_val)))};\n    return *parsed;\n}\n```\n\nIt would also make sense to switch to this form if new options are ever added."
  },
  {
   "t": "2026-09-08T17:30:29Z",
   "kind": "review",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "994aef40f969fc332330a7fbc77fcca4181aef6f",
   "text": "Code review ACK 7a839565cae797e87c43dc483066d47c2dffc568. Now supporting URL escaping for unambigous parsing. I did leave another suggestion about parsing below but it is not important, and probably better to leave the PR alone at this point.\n\nI did have one question: a previous comment suggested the new IPC max connections option might reduce P2P connection slots to 0 https://github.com/bitcoin/bitcoin/pull/35037#issuecomment-5058477580 and I wasn't sure if this was still possible in some cases or the new 256 connections ceiling completely prevents it.\n\nI also still think making the parse method virtual https://github.com/bitcoin/bitcoin/pull/35037#discussion_r3669245508 would be a good idea so we are not linking ipc code into the common library, but this can be a followup."
  },
  {
   "t": "2026-09-11T14:35:05Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/listen.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": 3960377830,
   "text": "This is a nice simplification, I did implement this and it preserved the behaviour while still being just a few lines of code, There seems to be little point to the custom parser if `SplitString` and the `ParseIntOption` could do much of the heavy lifting.\n\nI would leave the parser as is for now, but if there is another change needed, or if this code would be touched again, this simplification is very much a good approach for better maintenance"
  },
  {
   "t": "2026-09-11T14:43:14Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nYes, this is still possible with the 256 ceiling. In cases where the ceiling limits the ipc reservation, since it doesn\u2019t guarantee descriptors remain for p2p. the p2p connections can drop to 0. Changing this warning into a startup error could be handled separately, as discussed earlier.\n\n[quoted text omitted]\nI see the benefits of having the parser as a virtual method, I have started working on a possible way to have this as well, but like you said, If this does need to be retouched again, would look into this in a followup"
  },
  {
   "t": "2026-09-11T22:28:25Z",
   "kind": "review_comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/types.h",
   "commit": "f3bc4a4862bfa2c72d8605cc113240b8a34512e7",
   "in_reply_to": 3883644498,
   "text": "@enirox001 FYI in f3bc4a4862bfa2c72d8605cc113240b8a34512e7 this is still `size_t{1} << 20`. It changes to `256` in the next commit, but I think the comment \"This conservative bound\" describes `256` rather than `1 << 20`."
  },
  {
   "t": "2026-09-11T22:43:52Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "994aef40f969fc332330a7fbc77fcca4181aef6f"
  },
  {
   "t": "2026-09-11T22:45:51Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/types.h",
   "commit": "f3bc4a4862bfa2c72d8605cc113240b8a34512e7",
   "in_reply_to": 3883644498,
   "text": "Thanks for bringing this to my attention @xyzconstant, I have properly moved the 256 ceiling into the first commit so it matches the \u201cconservative bound\u201d comment."
  },
  {
   "t": "2026-09-11T23:16:17Z",
   "kind": "review_comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "6c8bcf5dd330c5f51040c3b728bd0df8df54e589",
   "in_reply_to": null,
   "text": "In commit 6c8bcf5dd330c5f51040c3b728bd0df8df54e589 _\"ipc: add default connection limit for ipcbind listeners\"_\n\nnit: The `ipc_addresses + ipc_max_connections` expression appears 3 times in this file. Moving it to a variable called `ipc_fds` could make the code clearer:\n\n```diff\ndiff --git a/src/init.cpp b/src/init.cpp\nindex 82bf7384eb..f64d77f138 100644\n--- a/src/init.cpp\n+++ b/src/init.cpp\n@@ -1087,14 +1087,16 @@ bool AppInitParameterInteraction(const ArgsManager& args)\n     // Maximum number of IPC connections. The multiplication cannot overflow\n     // because ipc_addresses was capped above.\n     const size_t ipc_max_connections{ipc_addresses * ipc::DEFAULT_MAX_CONNECTIONS};\n+    // Actual number of IPC file descriptors to be reserved.\n+    const size_t ipc_fds{ipc_max_connections + ipc_addresses};\n\n-    if (ipc_max_connections > MAX_IPC_FDS - ipc_addresses) {\n+    if (ipc_fds > MAX_IPC_FDS) {\n         return InitError(Untranslated(\"Too many IPC file descriptors requested\"));\n     }\n\n     if (ipc_addresses > 0) {\n         LogInfo(\"Reserving %d file descriptors for IPC (%d listening sockets, %d connection slots)\",\n-                static_cast<int>(ipc_addresses + ipc_max_connections),\n+                static_cast<int>(ipc_fds),\n                 static_cast<int>(ipc_addresses),\n                 static_cast<int>(ipc_max_connections));\n     }\n@@ -1123,12 +1125,12 @@ bool AppInitParameterInteraction(const ArgsManager& args)\n                               num_rpc_bind +\n                               user_rpc_max_connections +\n                               user_p2p_max_connections +\n-                              static_cast<int64_t>(ipc_addresses + ipc_max_connections) +\n+                              static_cast<int64_t>(ipc_fds) +\n                               static_cast<int64_t>(max_private);\n     if (total_fds > std::numeric_limits<int>::max()) {\n         return InitError(Untranslated(\"Too many file descriptors requested. Try lower values for -rpcmaxconnections \"\n                                       \"or -maxconnections, or fewer settings of \"\n-                                      \"-rpcbind, -bind and -whitebind\"));\n+                                      \"-rpcbind, -bind, -whitebind and -ipcbind\"));\n     }\n\n     // Subset of total_fds must also be a safe int\n@@ -1137,7 +1139,7 @@ bool AppInitParameterInteraction(const ArgsManager& args)\n                            num_p2p_bind +\n                            num_rpc_bind +\n                            user_rpc_max_connections +\n-                           static_cast<int>(ipc_addresses + ipc_max_connections);\n+                           static_cast<int>(ipc_fds);\n\n     // Try raising the FD limit to what the user wants (available_fds may be smaller than the requested amount if this fails)\n     available_fds = RaiseFileDescriptorLimit(static_cast<int>(total_fds));\n```\n\nNotice that the diff simplifies the `if (ipc_max_connections > MAX_IPC_FDS - ipc_addresses)` line to `if (ipc_fds > MAX_IPC_FDS)`, and also adds `-ipcbind` to the `InitError` raised during accounting for total file descriptors."
  },
  {
   "t": "2026-09-11T23:27:42Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "6f8f23866a92f7c74662429e29688dc060f83bd5"
  },
  {
   "t": "2026-09-11T23:28:58Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "6c8bcf5dd330c5f51040c3b728bd0df8df54e589",
   "in_reply_to": 3994130966,
   "text": "This is a nice simplification. taken Thanks."
  },
  {
   "t": "2026-09-12T00:11:25Z",
   "kind": "review_comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "f3f05aa853f8fd80c35c1a66beb132693566f294",
   "in_reply_to": null,
   "text": "In commit f3f05aa8 _\"ipc: support per-address max-connections on ipcbind\"_\n\nThis check is already done in `AppInitParameterInteraction`, so this block is unreachable.\n\nA simple `Assert()` should be enough:\n\n```diff\ndiff --git a/src/init.cpp b/src/init.cpp\nindex 67f0d36581..450bc50a01 100644\n--- a/src/init.cpp\n+++ b/src/init.cpp\n@@ -1612,9 +1612,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)\n     if (interfaces::Ipc* ipc = node.init->ipc()) {\n         for (const std::string& configured_address : gArgs.GetArgs(\"-ipcbind\")) {\n             auto listen_address{interfaces::Ipc::parseListenAddress(configured_address)};\n-            if (!listen_address) {\n-                return InitError(Untranslated(strprintf(\"Invalid -ipcbind address '%s': %s\", configured_address, util::ErrorString(listen_address).original)));\n-            }\n+            Assert(listen_address); // already validated in AppInitParameterInteraction\n             try {\n                 ipc->listenAddress(*listen_address);\n             } catch (const std::exception& e) {\n\n```"
  },
  {
   "t": "2026-09-12T01:36:47Z",
   "kind": "comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "text": "Tested ACK 6f8f23866a92f7c74662429e29688dc060f83bd5\n\nThis PR caps the number of simultaneous connections each `-ipcbind` listener accepts. The cap can be configured per address with the `,max-connections=<N>` option.\n\nTested locally using `socat`/`nc` with `max-connections=1` and 2 clients: the first one connected successfully, and the second one waited in the backlog to be accepted once the slot was freed.\n\nI also tested `-ipcbind` with multiple values, not just the happy path, to cover FD accounting, the new `Ipc::parseListenAddress` function, and a few edge cases. In one of these tries, I passed `-ipcbind=unix:/tmp/a.sock,max-connections=1,max-connections=2` which caused the process to silently overwrite the first `max-connections=1` with the last `max-connections=2`. Not a blocker, but it might be worth rejecting duplicates.\n\nAlso, I agree with this https://github.com/bitcoin/bitcoin/pull/35037#discussion_r3669245508 on `Ipc::parseListenAddress` being moved into `bitcoin_ipc` instead of being compiled in `bitcoin_common`.\n\nOverall, the code looks good to me. Good job @enirox001!"
  },
  {
   "t": "2026-09-12T10:13:57Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad"
  },
  {
   "t": "2026-09-12T10:14:08Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/init.cpp",
   "commit": "f3f05aa853f8fd80c35c1a66beb132693566f294",
   "in_reply_to": 3994344907,
   "text": "Taken, thanks"
  },
  {
   "t": "2026-09-14T11:34:54Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/49ee793c3eba2f2eb7acddbae316a3051474cde2:\n\nnit: you can default the expected_error to `\"\"`, and  remove the extra `\"\"` parameter on some of the tests below."
  },
  {
   "t": "2026-09-14T11:35:25Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/49ee793c3eba2f2eb7acddbae316a3051474cde2:\n\nWhy not `BOOST_REQUIRE(listen_address);`?"
  },
  {
   "t": "2026-09-14T11:37:03Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/49ee793c3eba2f2eb7acddbae316a3051474cde2:\n\nnit: This test case doesn't seem to test anything that `check_listen_address(\"unix:,max-connections=1\", \"unix:\", 1, \"\");` doesn't already test."
  },
  {
   "t": "2026-09-14T11:51:45Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "doc/release-notes-35037.md",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/c88b81d1e4b243e37aec53788a7736486c6affad:\n\nnit: Can also specify maximum limit here"
  },
  {
   "t": "2026-09-14T12:00:20Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35037/commits/49ee793c3eba2f2eb7acddbae316a3051474cde2:\n\nnit:\nThese could also be useful test cases:\n`check_listen_address(\"unix:,,max-connections=8\", \"\", 0, \"Empty socket option\");`\n`check_listen_address(\"unix:,max-connections=8,,max-connections=8\", \"\", 0, \"Empty socket option\");`"
  },
  {
   "t": "2026-09-14T12:01:19Z",
   "kind": "review",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "state": "APPROVED",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "text": "ACK https://github.com/bitcoin/bitcoin/pull/35037/commits/c88b81d1e4b243e37aec53788a7736486c6affad:\n\nLGTM, left some nits."
  },
  {
   "t": "2026-09-15T13:30:14Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "39b1c5a22c845857709d4e95d4205e0901e85b09"
  },
  {
   "t": "2026-09-15T13:30:15Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "in_reply_to": 4004727145,
   "text": "Thanks taken"
  },
  {
   "t": "2026-09-15T13:30:18Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "in_reply_to": 4004730361,
   "text": "Added the error check so that it would have an explanation, but I do not think this is necessary since the failure cases checks this exact error check.\n\nRemoved"
  },
  {
   "t": "2026-09-15T13:30:25Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "in_reply_to": 4004740425,
   "text": "Agree, dropped the redundant 256 case. The remaining `max-connections=1 `case still covers successful parsing and overriding the default"
  },
  {
   "t": "2026-09-15T13:30:35Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "doc/release-notes-35037.md",
   "commit": "c88b81d1e4b243e37aec53788a7736486c6affad",
   "in_reply_to": 4004843369,
   "text": "Updated to specify the maximum limit as well"
  },
  {
   "t": "2026-09-15T13:30:38Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/ipc_tests.cpp",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
   "in_reply_to": 4004901790,
   "text": "Taken thanks."
  },
  {
   "t": "2026-09-15T13:31:15Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Addressed nits and suggestions by @Eunovo"
  },
  {
   "t": "2026-09-15T17:32:01Z",
   "kind": "review",
   "who": "ViniciusCestarii",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "39b1c5a22c845857709d4e95d4205e0901e85b09",
   "text": "Re-ACK 39b1c5a22c845857709d4e95d4205e0901e85b09"
  },
  {
   "t": "2026-09-15T21:01:43Z",
   "kind": "comment",
   "who": "xyzconstant",
   "assoc": "CONTRIBUTOR",
   "text": "re-ACK 39b1c5a22c845857709d4e95d4205e0901e85b09\n\nNice changes"
  },
  {
   "t": "2026-09-16T13:51:03Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "78a1251365ab0dbfa9267c30760566d3b04bcd08"
  },
  {
   "t": "2026-09-16T13:51:55Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "Removed a stale comment https://github.com/bitcoin/bitcoin/pull/35037/commits/9be61a9dfc3e97dd98a1a665a65e02f39c4166a1#diff-5768699cb2773eff506c411cdb8ca5c1a5fddc6e4cc82a9cfc64b2c0f4f85e52R286 in the `ipc_tests`"
  },
  {
   "t": "2026-09-17T09:13:09Z",
   "kind": "comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "text": "reACK https://github.com/bitcoin/bitcoin/pull/35037/commits/78a1251365ab0dbfa9267c30760566d3b04bcd08"
  }
 ],
 "labels_log": [
  {
   "t": "2026-04-09T13:58:19Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-22T04:06:49Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-26T11:47:26Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-07T12:28:37Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-11T07:51:42Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-11T20:37:11Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-23T10:44:05Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-23T11:45:49Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-23T11:45:51Z",
   "action": "labeled",
   "label": "IPC",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-29T09:11:16Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-31T15:42:15Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-31T15:55:52Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-31T16:44:59Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-03T08:38:22Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-03T10:05:02Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-15T18:59:56Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-15T20:48:52Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-17T10:26:46Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-18T05:46:09Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-24T09:22:45Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-26T16:04:40Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-01T11:06:03Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-01T13:10:38Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-11T23:28:25Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-12T00:32:37Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-04-09T13:45:21Z",
   "kind": "renamed",
   "who": "enirox001",
   "from": "04 26 ipcbind max connections draft",
   "to": "ipc: support per-address max-connections options on -ipcbind"
  },
  {
   "t": "2026-06-25T13:00:19Z",
   "kind": "ready_for_review",
   "who": "enirox001"
  },
  {
   "t": "2026-06-30T18:54:33Z",
   "kind": "convert_to_draft",
   "who": "DrahtBot"
  },
  {
   "t": "2026-07-11T20:04:25Z",
   "kind": "ready_for_review",
   "who": "enirox001"
  }
 ],
 "text_chars": 50882,
 "text_tokens_estimate": 12720,
 "changed_paths": [
  "doc/release-notes-35037.md",
  "src/CMakeLists.txt",
  "src/init.cpp",
  "src/interfaces/ipc.h",
  "src/ipc/capnp/protocol.cpp",
  "src/ipc/interfaces.cpp",
  "src/ipc/listen.cpp",
  "src/ipc/protocol.h",
  "src/ipc/test/ipc_tests.cpp",
  "src/ipc/types.h",
  "test/functional/interface_ipc_init.py",
  "test/functional/test_runner.py"
 ],
 "files": [
  {
   "path": "doc/release-notes-35037.md",
   "add": 7,
   "del": 0
  },
  {
   "path": "src/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/init.cpp",
   "add": 44,
   "del": 8
  },
  {
   "path": "src/interfaces/ipc.h",
   "add": 11,
   "del": 3
  },
  {
   "path": "src/ipc/capnp/protocol.cpp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/ipc/interfaces.cpp",
   "add": 4,
   "del": 3
  },
  {
   "path": "src/ipc/listen.cpp",
   "add": 91,
   "del": 0
  },
  {
   "path": "src/ipc/protocol.h",
   "add": 3,
   "del": 1
  },
  {
   "path": "src/ipc/test/ipc_tests.cpp",
   "add": 80,
   "del": 0
  },
  {
   "path": "src/ipc/types.h",
   "add": 40,
   "del": 0
  },
  {
   "path": "test/functional/interface_ipc_init.py",
   "add": 122,
   "del": 0
  },
  {
   "path": "test/functional/test_runner.py",
   "add": 1,
   "del": 0
  }
 ],
 "test_lines": 123,
 "git": {
  "head": "78a1251365ab0dbfa9267c30760566d3b04bcd08",
  "head_matches_backup": true,
  "base": "5f45583e4373a84def5af84f3cef79bea69d7840",
  "commits": [
   {
    "sha": "3d2b65d050",
    "subject": "ipc: add default connection limit for ipcbind listeners",
    "files": 6,
    "add": 98,
    "del": 17
   },
   {
    "sha": "cc7eb60e6e",
    "subject": "ipc: support per-address max-connections on ipcbind",
    "files": 4,
    "add": 115,
    "del": 17
   },
   {
    "sha": "d59b26e08f",
    "subject": "ipc: test per-address connection limiting over unix sockets",
    "files": 3,
    "add": 203,
    "del": 0
   },
   {
    "sha": "78a1251365",
    "subject": "doc: add ipcbind max-connections release note",
    "files": 1,
    "add": 7,
    "del": 0
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "a84a690541d6c4d8",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}