{
 "number": 35916,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35916",
 "title": "fuzz: improve ipc fuzz coverage",
 "author": "enirox001",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-08-06T13:16:39Z",
 "updated_at": "2026-09-16T16:01:27Z",
 "age_days": 42,
 "draft": false,
 "labels": [
  "Fuzzing"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "84e54a419e55bcec04fd46c2241f72646de9b155",
 "head_ref": "08-26-fuzz-ipc-coverage",
 "head_repo": "enirox001/bitcoin",
 "head_history": [
  {
   "t": "2026-08-26T11:32:09Z",
   "sha": "85a5464cea7561450f2543452617cbc2894b0f5c"
  },
  {
   "t": "2026-08-26T12:33:52Z",
   "sha": "82bed574e47f0468d20b98b382a75aff2eefa57b"
  },
  {
   "t": "2026-09-14T09:51:04Z",
   "sha": "a37b99d8dbcce0e112652757b3b20be46208d419"
  },
  {
   "t": "2026-09-14T10:26:11Z",
   "sha": "1ea3507869869a93c136714d841fa5dd8788e8e0"
  },
  {
   "t": "2026-09-16T15:58:32Z",
   "sha": "84e54a419e55bcec04fd46c2241f72646de9b155"
  }
 ],
 "additions": 292,
 "deletions": 13,
 "changed_files": 3,
 "commit_count": 4,
 "size_bucket": "M",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "stale_ack": [
     {
      "login": "jeanpablojp",
      "url": "https://github.com/bitcoin/bitcoin/pull/35916#pullrequestreview-4944146103"
     }
    ]
   },
   "conflicts": [
    {
     "number": 32387,
     "title": "ipc: add windows support",
     "author": "ryanofsky"
    }
   ]
  }
 },
 "acks_parsed": {},
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 0,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "Eunovo",
   "jeanpablojp"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-09-16T16:01:26Z",
  "last_reviewer_activity": "2026-09-15T09:57:44Z",
  "last_reviewer": "Eunovo",
  "author_silent_days": 1,
  "waiting_on_author_days": 0,
  "days_since_update": 1
 },
 "refs": {
  "mentioned": [
   23015,
   35118
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 35118,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-07-02",
    "title": "fuzz: add ipc round-trip fuzz target"
   },
   {
    "number": 23015,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "RFC: Add multiprocess fuzz target"
   }
  ],
  "conflicts": [
   32387
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/ipc/test/fuzz/ipc.cpp"
 ],
 "body": "This PR follows up on #35118 and continues the IPC fuzzing work proposed in #23015.\n\nThe initial ipc fuzz target exercised normal calls through a libmultiprocess client and server. This PR extends the target with\n\n - Server side assertions that verify arguments arrive unchanged (https://github.com/bitcoin/bitcoin/pull/35118#issuecomment-4452992198 and https://github.com/bitcoin/bitcoin/pull/35118#pullrequestreview-4539477599)\n - A callback call that exercises ipc communication in both directions.\n - Raw capnp requests containing arbitrary transaction and `UniValue` payloads, which are deserialized by a normal libmultiprocess server.\n  - Raw capnp responses containing arbitrary transaction and `UniValue` payloads, which are deserialized by a normal libmultiprocess client.\n\nThe raw request and response cases allow the fuzz target to exercise deserialization with data that was not first produced by libmultiprocess serialization.\n\nThe ipc setup and callback handling closely follow the existing [`libmultiprocess` tests](https://github.com/bitcoin/bitcoin/blob/master/src/ipc/libmultiprocess/test/mp/test/test.cpp), particularly their use of `EventLoop`, `ProxyClient`, `ProxyServer`, two-way pipes, and `initThreadMap`.\n\nThe transaction and UniValue payload cases exercise the serialization hooks defined in [`common-types.h`](https://github.com/bitcoin/bitcoin/blob/master/src/ipc/capnp/common-types.h).\n\nThese files may provide useful background when reviewing the changes.\n\nGenerated [coverage report](https://enirox001.github.io/coverage/ipc/) after fuzzing the IPC target for a while using the qa-assets corpus.",
 "commits": [
  {
   "sha": "d650d09a0232ca047d97c1966a9a04bab04e195f",
   "date": "2026-09-14T09:44:43Z",
   "message": "fuzz: assert IPC arguments on server side\n\nKeep a reference to the IPC fuzz implementation so fuzz inputs can be compared\ndirectly with values deserialized by the proxy server.\n\nThis ensures serialization errors are detected on the client to server path instead\nof potentially being hidden by the return trip."
  },
  {
   "sha": "c74757bed3b6d22112e1165c22726551840b3e6e",
   "date": "2026-09-14T09:45:00Z",
   "message": "fuzz: exercise IPC callback\n\nAdd a callback interface to the IPC fuzz target so requests exercise communication\nfrom the server back to the client.\n\nCheck the callback argument and return value on both sides."
  },
  {
   "sha": "59cd6e3ff7b0459c1ff2b26ee11c209c43066b04",
   "date": "2026-09-16T15:31:52Z",
   "message": "fuzz: send malformed IPC request payloads\n\nUse the underlying capnp client to send arbitrary transaction data and JSON text to the\nlibmultiprocess server.\n\nAccept normal transaction deserialization failures while surfacing unexpected IPC errors."
  },
  {
   "sha": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "date": "2026-09-16T15:31:52Z",
   "message": "fuzz: return malformed IPC response payloads\n\nConnect a normal libmultiprocess client to a manual capnp server.\n\nReturn arbitrary transaction data and json text to exercise client side\ndeserialization."
  }
 ],
 "timeline": [
  {
   "t": "2026-08-15T15:40:56Z",
   "kind": "review",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "bd24122dfbfbaded49ef551c01184b4b5b48e27f",
   "text": "tACK bd24122dfbfbaded49ef551c01184b4b5b48e27f\n\nAll green, and it matches the follow-up #35118 asked for."
  },
  {
   "t": "2026-08-15T15:40:57Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "in_reply_to": null,
   "text": "Took me a bit to see why sendTransactionPayload swallows FAILED while sendUniValuePayload treats any kj error as fatal. That's correct, but you only get it by reading the hooks. A one-line comment would have helped, feel free to ignore.\n\n```suggestion\n                    // UniValue deserialization never throws (read() failure is ignored), so any kj error is unexpected.\n                    done.set_exception(std::make_exception_ptr(\n```"
  },
  {
   "t": "2026-08-26T11:32:09Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "85a5464cea7561450f2543452617cbc2894b0f5c"
  },
  {
   "t": "2026-08-26T11:33:30Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "in_reply_to": 3789672122,
   "text": "Yes, I agree that this can be clarified a bit more, added the suggested comment to clarify why any KJ error is unexpected here. Thanks"
  },
  {
   "t": "2026-08-26T12:33:52Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "82bed574e47f0468d20b98b382a75aff2eefa57b"
  },
  {
   "t": "2026-08-28T07:57:25Z",
   "kind": "comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "text": "See the generated [coverage report](https://enirox001.github.io/coverage/ipc/) after fuzzing the IPC target for a while using the qa-assets corpus.\n\nAlso included in the pr description"
  },
  {
   "t": "2026-09-14T09:51:04Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "a37b99d8dbcce0e112652757b3b20be46208d419"
  },
  {
   "t": "2026-09-14T10:26:11Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "1ea3507869869a93c136714d841fa5dd8788e8e0"
  },
  {
   "t": "2026-09-15T09:34:45Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35916/commits/1ea3507869869a93c136714d841fa5dd8788e8e0:\n\nUse `ConsumeTransaction` in `src/test/fuzz/util.cpp` to create a random tx from a `FuzzedDataProvider` instead of using a random lenght byte vector."
  },
  {
   "t": "2026-09-15T09:40:35Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35916/commits/1ea3507869869a93c136714d841fa5dd8788e8e0:\n\nMost of the generated data will be invalid JSON; this means the fuzzer will hit the \"invalid JSON received over IPC\" error most of the time.  I think it's much better to construct a valid JSON payload, the same way we construct valid TXs with `ConsumeTransaction`."
  },
  {
   "t": "2026-09-15T09:53:04Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35916/commits/f5db59400b7838beffef3cba34d6fbcf5df9a00c:\n\nYou should use `ConsumeTransaction` from `src/test/fuzz/util.cpp`. Most of the vectors produced will be invalid."
  },
  {
   "t": "2026-09-15T09:53:25Z",
   "kind": "review_comment",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "in_reply_to": null,
   "text": "https://github.com/bitcoin/bitcoin/pull/35916/commits/f5db59400b7838beffef3cba34d6fbcf5df9a00c:\n\nSame as in my previous UniValue comment."
  },
  {
   "t": "2026-09-15T09:57:44Z",
   "kind": "review",
   "who": "Eunovo",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "1ea3507869869a93c136714d841fa5dd8788e8e0",
   "text": "https://github.com/bitcoin/bitcoin/pull/35916/commits/1ea3507869869a93c136714d841fa5dd8788e8e0:\n\nI'm not sure why random bytes are being used for CTransaction and UniValue; the chances of a randomly generated byte vector deserialising to a CTransaction are slim."
  },
  {
   "t": "2026-09-16T15:57:35Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "in_reply_to": 4014137549,
   "text": "We intentionally return arbitrary transaction bytes from the raw server so the client deserialization is exercised with malformed responses.\n\nUsing `ConsumeTransaction` would only generate valid transactions and duplicate the existing passTransaction coverage.\n\nI\u2019ve added a comment clarifying the purpose of this branch."
  },
  {
   "t": "2026-09-16T15:57:37Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "in_reply_to": 4014184111,
   "text": "Invalid json is intentional here because it tests client side rejection of malformed ipc responses.\n\nValid json round trips are covered separately by passUniValue, which parses arbitrary input and proceeds when it is valid.\n\nI\u2019ve added a comment clarifying the distinction."
  },
  {
   "t": "2026-09-16T15:58:32Z",
   "kind": "force_push",
   "who": "enirox001",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155"
  },
  {
   "t": "2026-09-16T15:59:59Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "in_reply_to": 4014287171,
   "text": "Same rationale as https://github.com/bitcoin/bitcoin/pull/35916#discussion_r4028056645: this intentionally bypasses normal serialization to exercise malformed transaction payload handling."
  },
  {
   "t": "2026-09-16T16:01:26Z",
   "kind": "review_comment",
   "who": "enirox001",
   "assoc": "CONTRIBUTOR",
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "commit": "84e54a419e55bcec04fd46c2241f72646de9b155",
   "in_reply_to": 4014290299,
   "text": "Same reason as https://github.com/bitcoin/bitcoin/pull/35916#discussion_r4028056893"
  }
 ],
 "labels_log": [
  {
   "t": "2026-08-06T13:16:43Z",
   "action": "labeled",
   "label": "Fuzzing",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-26T12:34:27Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-26T15:44:22Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-14T08:53:10Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-14T10:24:44Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-14T11:03:06Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-09-14T11:30:25Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  }
 ],
 "state_log": [
  {
   "t": "2026-08-06T13:25:26Z",
   "kind": "renamed",
   "who": "enirox001",
   "from": "fuzz: improve IPC fuzz coverage",
   "to": "fuzz: improve ipc fuzz coverage"
  }
 ],
 "text_chars": 5584,
 "text_tokens_estimate": 1396,
 "changed_paths": [
  "src/ipc/test/fuzz/ipc.cpp",
  "src/ipc/test/fuzz/ipc_fuzz.capnp",
  "src/ipc/test/fuzz/ipc_fuzz.h"
 ],
 "files": [
  {
   "path": "src/ipc/test/fuzz/ipc.cpp",
   "add": 205,
   "del": 7
  },
  {
   "path": "src/ipc/test/fuzz/ipc_fuzz.capnp",
   "add": 9,
   "del": 0
  },
  {
   "path": "src/ipc/test/fuzz/ipc_fuzz.h",
   "add": 78,
   "del": 6
  }
 ],
 "test_lines": 0,
 "git": {
  "head": "84e54a419e55bcec04fd46c2241f72646de9b155",
  "head_matches_backup": true,
  "base": "d25470d992b72b1960729478e677473f5bf860a8",
  "commits": [
   {
    "sha": "d650d09a02",
    "subject": "fuzz: assert IPC arguments on server side",
    "files": 2,
    "add": 62,
    "del": 9
   },
   {
    "sha": "c74757bed3",
    "subject": "fuzz: exercise IPC callback",
    "files": 3,
    "add": 58,
    "del": 0
   },
   {
    "sha": "59cd6e3ff7",
    "subject": "fuzz: send malformed IPC request payloads",
    "files": 3,
    "add": 81,
    "del": 4
   },
   {
    "sha": "84e54a419e",
    "subject": "fuzz: return malformed IPC response payloads",
    "files": 1,
    "add": 92,
    "del": 1
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "30c05fa898b56f74",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}