{
 "number": 36073,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/36073",
 "title": "fuzz: Add musig harness",
 "author": "nervana21",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-08-25T08:02:49Z",
 "updated_at": "2026-09-08T23:00:18Z",
 "age_days": 23,
 "draft": false,
 "labels": [
  "Fuzzing"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "13956bfd64c737d60aa870b16357507c5f97a42e",
 "head_ref": "add-musig-harness",
 "head_repo": "nervana21/bitcoin",
 "head_history": [
  {
   "t": "2026-09-08T22:45:47Z",
   "sha": "13956bfd64c737d60aa870b16357507c5f97a42e"
  }
 ],
 "additions": 211,
 "deletions": 0,
 "changed_files": 2,
 "commit_count": 1,
 "size_bucket": "M",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "jeanpablojp",
      "url": "https://github.com/bitcoin/bitcoin/pull/36073#pullrequestreview-5141721593"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "jeanpablojp": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-09-08T12:35:01Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 1,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "jeanpablojp"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-09-08T22:58:48Z",
  "last_reviewer_activity": "2026-09-08T12:35:01Z",
  "last_reviewer": "jeanpablojp",
  "author_silent_days": 8,
  "waiting_on_author_days": 0,
  "days_since_update": 8
 },
 "refs": {
  "mentioned": [
   35422
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 35422,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "musig: Require generated secnonce for partial sig"
   }
  ],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/test/fuzz/CMakeLists.txt",
  "src/test/fuzz/musig.cpp"
 ],
 "body": "This PR adds a fuzz target for `src/musig`. Previously, the module APIs had no dedicated harness, so fail paths were underexercised.\n\nIt covers:\n\n- `MuSig2AggregatePubkeys`\n- `MuSig2AggregatePubkeys` (with key aggregation cache and optional expected aggregate)\n- `CreateMuSig2SyntheticXpub`\n- `MuSig2SessionID`\n- Signing-shaped path:\n  - `CreateMuSig2Nonce`\n  - `CreateMuSig2PartialSig` with the generated secnonce\n  - `CreateMuSig2AggregateSig`",
 "commits": [
  {
   "sha": "13956bfd64c737d60aa870b16357507c5f97a42e",
   "date": "2026-09-08T22:31:39Z",
   "message": "fuzz: Add musig harness"
  }
 ],
 "timeline": [
  {
   "t": "2026-08-25T08:03:19Z",
   "kind": "comment",
   "who": "nervana21",
   "assoc": "CONTRIBUTOR",
   "text": "Coverage: https://nervana21.github.io/coverage/musig/\nllvm-cov on 2bea78212c1047671ea93b93d345e0aea9042a69 (includes PR35422)."
  },
  {
   "t": "2026-09-08T12:35:01Z",
   "kind": "review",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "da584ef92c1c83e00eaece27c84c6abc490e53fd",
   "text": "Concept ACK.\n\nThe four signing functions in the module have no unit test today, only the `wallet_musig.py` functional test, so the harness covers ground that was empty.\n\nOne thing about the never-generated secnonce arm. I built the target at this head and ran it against random input. The target aborts on 8 of 1000 files, with `[libsecp256k1] illegal argument: secp256k1_memcmp_var(&secnonce->data[0], secp256k1_musig_secnonce_magic, 4) == 0`. Dropping just that arm makes the same files pass clean.\n\nThe 60 second CI run ends at `lim: 8`, and 2000 inputs of up to 8 bytes did not abort the target once. oss-fuzz picks its targets out of the binary itself, so this target goes in with the next oss-fuzz build after the merge.\n\nWould it be worth moving that arm into #35422, where it gets the guard that makes it meaningful, and letting this harness go in on its own?"
  },
  {
   "t": "2026-09-08T12:35:01Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/fuzz/musig.cpp",
   "commit": "13956bfd64c737d60aa870b16357507c5f97a42e",
   "in_reply_to": null,
   "text": "These bytes are almost never a valid pair of nonce points, so a session with more than one participant almost always stops before signing.\n\nInstrumenting `CreateMuSig2PartialSig` and dropping the secnonce arm so the run survives, a 300 second libFuzzer run made 98213 calls, 75903 of them single-participant. 230 of the 6135 two-participant calls returned a signature, and none of the 16175 with three or more. `CreateMuSig2AggregateSig` never returned a signature.\n\nGiving each participant a key from the fuzz input and a nonce from `CreateMuSig2Nonce`, and feeding the partial sigs back into the aggregation instead of fresh `ConsumeUInt256` values, plain random inputs gave 400 partial sigs and 145 aggregate signatures over one to five participants. Worth going that way and keeping the raw bytes as a separate case, so the parse failure stays reachable?"
  },
  {
   "t": "2026-09-08T12:35:01Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/fuzz/musig.cpp",
   "commit": "da584ef92c1c83e00eaece27c84c6abc490e53fd",
   "in_reply_to": null,
   "text": "This `ser` only exists when `expected` has a value, and then it comes from the aggregate pubkey, which is always 33 bytes. Could the check go?"
  },
  {
   "t": "2026-09-08T12:35:01Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/fuzz/CMakeLists.txt",
   "commit": "da584ef92c1c83e00eaece27c84c6abc490e53fd",
   "in_reply_to": null,
   "text": "nit: the list is almost entirely alphabetical, so `musig.cpp` would go after `multiplication_overflow.cpp`."
  },
  {
   "t": "2026-09-08T13:00:06Z",
   "kind": "review_comment",
   "who": "nervana21",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/fuzz/CMakeLists.txt",
   "commit": "da584ef92c1c83e00eaece27c84c6abc490e53fd",
   "in_reply_to": 3957935794,
   "text": "Done."
  },
  {
   "t": "2026-09-08T14:26:50Z",
   "kind": "review_comment",
   "who": "nervana21",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/fuzz/musig.cpp",
   "commit": "da584ef92c1c83e00eaece27c84c6abc490e53fd",
   "in_reply_to": 3957935789,
   "text": "Done."
  },
  {
   "t": "2026-09-08T22:40:18Z",
   "kind": "review_comment",
   "who": "nervana21",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/fuzz/musig.cpp",
   "commit": "13956bfd64c737d60aa870b16357507c5f97a42e",
   "in_reply_to": 3957935776,
   "text": "Ahh, makes sense, thanks! I think I've understood and taken your suggestions. Please let me know what you think."
  },
  {
   "t": "2026-09-08T22:41:52Z",
   "kind": "comment",
   "who": "nervana21",
   "assoc": "CONTRIBUTOR",
   "text": "[quoted text omitted]\n\nYes, I think this is a better approach. I've dropped that call from this harness."
  },
  {
   "t": "2026-09-08T22:45:47Z",
   "kind": "force_push",
   "who": "nervana21",
   "commit": "13956bfd64c737d60aa870b16357507c5f97a42e"
  },
  {
   "t": "2026-09-08T22:58:48Z",
   "kind": "comment",
   "who": "nervana21",
   "assoc": "CONTRIBUTOR",
   "text": "_**Updates**_:\n\n* Addressed @jeanpablojp's [feedback](https://github.com/bitcoin/bitcoin/pull/36073#pullrequestreview-5141721593)\n\n* Addressed @jeanpablojp's [feedback](https://github.com/bitcoin/bitcoin/pull/36073#discussion_r3957935776).\nAlso in the raw bytes branch, moved the tweak list to before `CreateMuSig2Nonce` to match the ordering of the newly added arm.\n\n* Addressed @jeanpablojp's [feedback](https://github.com/bitcoin/bitcoin/pull/36073#discussion_r3957935789)\n\n* Addressed @jeanpablojp's [feedback](https://github.com/bitcoin/bitcoin/pull/36073#discussion_r3957935794)"
  }
 ],
 "labels_log": [
  {
   "t": "2026-08-25T08:02:53Z",
   "action": "labeled",
   "label": "Fuzzing",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 3413,
 "text_tokens_estimate": 853,
 "changed_paths": [
  "src/test/fuzz/CMakeLists.txt",
  "src/test/fuzz/musig.cpp"
 ],
 "files": [
  {
   "path": "src/test/fuzz/CMakeLists.txt",
   "add": 1,
   "del": 0
  },
  {
   "path": "src/test/fuzz/musig.cpp",
   "add": 210,
   "del": 0
  }
 ],
 "test_lines": 211,
 "git": {
  "head": "13956bfd64c737d60aa870b16357507c5f97a42e",
  "head_matches_backup": true,
  "base": "dc0395c5858a1d55239b82a834e5075cf2069219",
  "commits": [
   {
    "sha": "13956bfd64",
    "subject": "fuzz: Add musig harness",
    "files": 2,
    "add": 211,
    "del": 0
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "5840328a7c6f47c6",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}