{
 "number": 36670,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/36670",
 "title": "fuzz: check GetStale() returns exactly the stale private broadcast txs",
 "author": "frankomosh",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-10-26T18:38:27Z",
 "updated_at": "2026-10-31T20:19:24Z",
 "description_hash": "4b9792ade84ca114",
 "age_days": 6,
 "draft": false,
 "labels": [
  "Fuzzing",
  "Private Broadcast"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "986cdf27b42df9a2b3942d06d241f634560dee70",
 "head_ref": "2026-10-fuzz-private-broadcast-stale-check",
 "head_repo": "frankomosh/bitcoin",
 "head_history": [],
 "additions": 26,
 "deletions": 0,
 "changed_files": 1,
 "commit_count": 1,
 "size_bucket": "S",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {},
   "conflicts": []
  }
 },
 "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": [
   "andrewtoth",
   "fanquake"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-10-21T04:33:29Z",
  "last_reviewer_activity": "2026-10-31T20:19:24Z",
  "last_reviewer": "andrewtoth",
  "author_silent_days": 11,
  "waiting_on_author_days": 1,
  "days_since_update": 1
 },
 "refs": {
  "mentioned": [],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/test/fuzz/private_broadcast.cpp"
 ],
 "body": "The `private_broadcast` fuzz test checks each tx that `GetStale()` returns. This adds to it by checking that all stale txs are returned.  `ReattemptPrivateBroadcast()` only retries what `GetStale()` returns, and a stale tx left out is never retried.\n\nThis partly came up during review in https://github.com/bitcoin/bitcoin/pull/35129#pullrequestreview-4427536924, and recently also surfaced in https://mutanthub.space/mutants/3752 , where changing `continue` to `break` in `GetStale()` passes all current tests.\n\nThis PR records when each tx is added and when each node confirms it. Then it checks that `GetStale()` returns exactly the expected txs.",
 "commits": [
  {
   "sha": "986cdf27b42df9a2b3942d06d241f634560dee70",
   "date": "2026-10-21T04:33:29Z",
   "message": "fuzz: check GetStale() returns exactly the stale private broadcast txs\n\nCurrently, the private_broadcast harness checks that each transaction\nreturned by GetStale() is known, unresolved and below the attempt cap.\nThis adds onto that by checking the timing rule, and that every stale\ntransaction is returned.\n\nTrack when each transaction is added and when each node confirms\nreception, and check that GetStale() returns exactly the expected set."
  }
 ],
 "timeline": [
  {
   "t": "2026-10-26T19:29:59Z",
   "kind": "comment",
   "who": "fanquake",
   "assoc": "MEMBER",
   "text": "cc @vasild @andrewtoth",
   "id": "c:6425391624",
   "url": "https://github.com/bitcoin/bitcoin/pull/36670#issuecomment-6425391624",
   "hash": "2560e412d2e42fbc",
   "edited": null
  },
  {
   "t": "2026-10-31T20:19:24Z",
   "kind": "review_comment",
   "who": "andrewtoth",
   "assoc": "MEMBER",
   "path": "src/test/fuzz/private_broadcast.cpp",
   "commit": "986cdf27b42df9a2b3942d06d241f634560dee70",
   "in_reply_to": null,
   "text": "We can also assert that stale does not return any duplicates.\n\n```suggestion\n                for (const auto& stale_tx : stale) Assert(expected.erase(stale_tx) == 1);\n```",
   "id": "rc:4433163349",
   "url": "https://github.com/bitcoin/bitcoin/pull/36670#discussion_r4433163349",
   "hash": "a5fd55afedf1c35d",
   "edited": null
  }
 ],
 "labels_log": [
  {
   "t": "2026-10-26T18:38:31Z",
   "action": "labeled",
   "label": "Fuzzing",
   "who": "DrahtBot"
  },
  {
   "t": "2026-10-26T19:29:47Z",
   "action": "labeled",
   "label": "Private Broadcast",
   "who": "fanquake"
  }
 ],
 "state_log": [],
 "text_chars": 1358,
 "text_tokens_estimate": 339,
 "changed_paths": [
  "src/test/fuzz/private_broadcast.cpp"
 ],
 "files": [
  {
   "path": "src/test/fuzz/private_broadcast.cpp",
   "add": 26,
   "del": 0
  }
 ],
 "test_lines": 26,
 "git": {
  "head": "986cdf27b42df9a2b3942d06d241f634560dee70",
  "head_matches_backup": true,
  "base": "4303f3b7f0775cdbbe77faddf142e1e44fa590ca",
  "patch_id": "341c02aba6cf2e48",
  "commits": [
   {
    "sha": "986cdf27b4",
    "subject": "fuzz: check GetStale() returns exactly the stale private broadcast txs",
    "files": 1,
    "add": 26,
    "del": 0
   }
  ],
  "patch_truncated": false
 },
 "patch_id": "341c02aba6cf2e48",
 "input_hash": "048a5bb90706dbd7",
 "extracted_at": "2026-11-02T01:09:49+00:00"
}