{
 "number": 36477,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/36477",
 "title": "private broadcast: show finished transactions in getprivatebroadcastinfo",
 "author": "vasild",
 "author_association": "MEMBER",
 "created_at": "2026-10-08T15:16:42Z",
 "updated_at": "2026-10-29T16:46:43Z",
 "description_hash": "3c47282dae340abd",
 "age_days": 24,
 "draft": false,
 "labels": [
  "Needs rebase",
  "Private Broadcast"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
 "head_ref": "pb_show_concluded",
 "head_repo": "vasild/bitcoin",
 "head_history": [
  {
   "t": "2026-10-08T15:17:51Z",
   "sha": "bce73a17fd2754f5fad9248bdcd13b3bad0ae023"
  },
  {
   "t": "2026-10-22T13:31:44Z",
   "sha": "0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f"
  },
  {
   "t": "2026-10-23T15:00:02Z",
   "sha": "295c961c1f156bdbbddfa0f961751d5aa371a62b"
  }
 ],
 "additions": 197,
 "deletions": 71,
 "changed_files": 8,
 "commit_count": 1,
 "size_bucket": "M",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "optout21",
      "url": "https://github.com/bitcoin/bitcoin/pull/36477#issuecomment-6343001721"
     }
    ]
   },
   "conflicts": []
  }
 },
 "acks_parsed": {
  "optout21": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-10-22T14:17:37Z",
   "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": [
   "frankomosh",
   "optout21"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-10-23T15:04:02Z",
  "last_reviewer_activity": "2026-10-28T12:11:43Z",
  "last_reviewer": "optout21",
  "author_silent_days": 9,
  "waiting_on_author_days": 4,
  "days_since_update": 3
 },
 "refs": {
  "mentioned": [
   34707,
   36607
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 34707,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "net: keep finished private broadcast txs in memory"
   },
   {
    "number": 36607,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "private broadcast: Extra guard against unintended non-private broadcast of private transactions"
   }
  ],
  "conflicts": []
 },
 "stack": {
  "shares_commits_with": [
   36607
  ],
  "based_on": [],
  "base_for": [
   36607
  ]
 },
 "review_paths": [
  "src/private_broadcast.cpp",
  "src/private_broadcast.h",
  "src/rpc/mempool.cpp",
  "src/test/fuzz/private_broadcast.cpp"
 ],
 "body": "For finished transactions, this allows the inspection of when and to whom the transaction was sent as well as when/if it was echoed from the network.",
 "commits": [
  {
   "sha": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "date": "2026-10-23T14:58:45Z",
   "message": "private broadcast: show finished transactions in getprivatebroadcastinfo\n\nFor finished transactions, this allows the inspection of when and to\nwhom the transaction was sent as well as when/if it was echoed from\nthe network.\n\nCo-authored-by: Vasil Dimov <vd@FreeBSD.org>"
  }
 ],
 "timeline": [
  {
   "t": "2026-10-08T15:17:51Z",
   "kind": "force_push",
   "who": "vasild",
   "commit": "bce73a17fd2754f5fad9248bdcd13b3bad0ae023",
   "id": "push:bce73a17fd2754f5fad9248bdcd13b3bad0ae023"
  },
  {
   "t": "2026-10-19T18:42:09Z",
   "kind": "review_comment",
   "who": "frankomosh",
   "assoc": "CONTRIBUTOR",
   "path": "src/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": null,
   "text": "A tx that used all its send attempts, but never came back from the network, can no longer be sent again. Now `Add()` can only restarts a tx that is resolved. But `GetStale()` skips such a tx, so nothing marks it resolved.\n\nAre we getting rid of the 'retry' feature..?",
   "id": "rc:4317490758",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4317490758",
   "hash": "b1f915f67ed033a6",
   "edited": "2026-10-19T18:51:17Z"
  },
  {
   "t": "2026-10-19T18:44:34Z",
   "kind": "review_comment",
   "who": "frankomosh",
   "assoc": "CONTRIBUTOR",
   "path": "src/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": null,
   "text": "If another peer sends us the same tx later, this line replaces the saved peer and time. So `received_by_us` may not show the first peer that sent it back.\n\nShould we keep the first one?",
   "id": "rc:4317514180",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4317514180",
   "hash": "ccf4a58be2525828",
   "edited": "2026-10-19T18:48:38Z"
  },
  {
   "t": "2026-10-19T18:48:38Z",
   "kind": "review",
   "who": "frankomosh",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "bce73a17fd2754f5fad9248bdcd13b3bad0ae023",
   "text": "I guess this is a continuation of #34707. Could you share what was added or left out compared to it?",
   "id": "r:5576092928",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#pullrequestreview-5576092928",
   "hash": "c4e8505d0c422338",
   "edited": null
  },
  {
   "t": "2026-10-22T13:19:48Z",
   "kind": "review_comment",
   "who": "vasild",
   "assoc": "MEMBER",
   "path": "src/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": 4317490758,
   "text": "No, that was not intentional. Fixed. Please double check again, this has become non-trivial.",
   "id": "rc:4348811647",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4348811647",
   "hash": "05d6eaba41ea0768",
   "edited": null
  },
  {
   "t": "2026-10-22T13:23:16Z",
   "kind": "review_comment",
   "who": "vasild",
   "assoc": "MEMBER",
   "path": "src/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": 4317514180,
   "text": "Right, changed it to only set `received_by_us` if it is not set.",
   "id": "rc:4348848801",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4348848801",
   "hash": "f220a5d1a2ee43ff",
   "edited": null
  },
  {
   "t": "2026-10-22T13:31:44Z",
   "kind": "force_push",
   "who": "vasild",
   "commit": "0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f",
   "id": "push:0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f"
  },
  {
   "t": "2026-10-22T13:32:41Z",
   "kind": "comment",
   "who": "vasild",
   "assoc": "MEMBER",
   "text": "`bce73a17fd2754f5fad9248bdcd13b3bad0ae023...0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f`: rebase and address suggestions from @frankomosh and https://review.fish.foo/traces/36477-bce73a17fd2754f5fad9248bdcd13b3bad0ae023-991-2.html\n\nPS\n[quoted text omitted]\n\nI am unsure. Better review this one as a fresh new unrelated one.",
   "id": "c:6342040389",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#issuecomment-6342040389",
   "hash": "8ed3d21ce598b309",
   "edited": "2026-10-22T13:35:26Z"
  },
  {
   "t": "2026-10-22T14:17:37Z",
   "kind": "comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "text": "Concept ACK\nKeeping info about completed transaction is useful for the user.\nThis info may be useful for the feature implementation as well (e.g. see #36607 for a proposal how to refuse non-private broadcast of private transactions).",
   "id": "c:6343001721",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#issuecomment-6343001721",
   "hash": "6bed8b4e8ff6cd67",
   "edited": null
  },
  {
   "t": "2026-10-22T14:31:39Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/rpc/mempool.cpp",
   "commit": "0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f",
   "in_reply_to": null,
   "text": "[quoted text omitted]\n\nMinor inaccuracy: echoed transaction may still have `attempts_remaining > 0` initially. Maybe the text should list the stored categories: transactions being actively sent, sent but not echoed back, and echoed back.",
   "id": "rc:4349623306",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4349623306",
   "hash": "8d330ee272f997eb",
   "edited": "2026-10-22T14:41:39Z"
  },
  {
   "t": "2026-10-22T14:33:01Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/rpc/mempool.cpp",
   "commit": "0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f",
   "in_reply_to": null,
   "text": "[quoted text omitted]\n\nThis should also be updated.",
   "id": "rc:4349638314",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4349638314",
   "hash": "7a5225d3c3ed0ccf",
   "edited": "2026-10-22T14:41:39Z"
  },
  {
   "t": "2026-10-22T14:40:03Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": 4317490758,
   "text": "Related, what happens when a previously-finished transaction is requested to be private-broadcast again?\n\n- `Add()` sees it finished, and clears `received_by_us` and `resolved`\n- It is sent out again (to 3 peers)\n- It never gets re-added to our mempool, as it already there. `MarkResolved` is not called again.\n- The transaction may be taken as failed\n- Final state reported in RPC: `attempts_remaining` 0 and no `received_by_us`\n\nIs this intended this way?",
   "id": "rc:4349714404",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4349714404",
   "hash": "e9adecce4acbadaf",
   "edited": "2026-10-22T14:41:39Z"
  },
  {
   "t": "2026-10-22T14:41:39Z",
   "kind": "review",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f",
   "text": "Performed a review pass (0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f), looks good generally; left some comments.",
   "id": "r:5615886752",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#pullrequestreview-5615886752",
   "hash": "8bd9f558b1ebb5c5",
   "edited": null
  },
  {
   "t": "2026-10-23T14:50:01Z",
   "kind": "review_comment",
   "who": "vasild",
   "assoc": "MEMBER",
   "path": "src/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": 4317490758,
   "text": "[quoted text omitted]\n\nNote that `MarkResolved()` is called after we receive the transaction but before we try to put it in the mempool:\n\nhttps://github.com/bitcoin/bitcoin/blob/df0dc1e2d2059213e49a9f115fd55a9f0119d26c/src/net_processing.cpp#L4734\n\nhttps://github.com/bitcoin/bitcoin/blob/df0dc1e2d2059213e49a9f115fd55a9f0119d26c/src/net_processing.cpp#L4770\n\nSo, it will be marked as resolved if we receive it, even if it wouldn't enter the mempool because it is already there.\n\nBut... would we receive it (a second time)? After the initial receive we would send it to all peers. So all of them know we have it. They wouldn't `INV` it to us anymore and even if they do we wouldn't request it (with `GETDATA`) because we have it in our mempool already.\n\nSo, yes, there is no reliable way to know if the second broadcast succeeded. This is the same in `master` right now. There may be new peers in the meantime that are unaware that we have the transaction and they will `INV` it to us (if it even starts propagating a second time through the network). Something to consider, separately from this PR. I do not think this PR changes the behavior.",
   "id": "rc:4360850145",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4360850145",
   "hash": "aef035716fbaf7cd",
   "edited": null
  },
  {
   "t": "2026-10-23T15:00:02Z",
   "kind": "force_push",
   "who": "vasild",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "id": "push:295c961c1f156bdbbddfa0f961751d5aa371a62b"
  },
  {
   "t": "2026-10-23T15:00:21Z",
   "kind": "comment",
   "who": "vasild",
   "assoc": "MEMBER",
   "text": "`0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f...295c961c1f156bdbbddfa0f961751d5aa371a62b`: address suggestions",
   "id": "c:6367884338",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#issuecomment-6367884338",
   "hash": "fa7320087d94083f",
   "edited": null
  },
  {
   "t": "2026-10-23T15:02:28Z",
   "kind": "review_comment",
   "who": "vasild",
   "assoc": "MEMBER",
   "path": "src/rpc/mempool.cpp",
   "commit": "0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f",
   "in_reply_to": 4349623306,
   "text": "Right. This text is to explain that some transactions will remain (because all others would be removed). Now I think it is not necessary because all will remain, so no need to explain that _some_ particular ones will remain. Dropped the sentence.",
   "id": "rc:4360971360",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4360971360",
   "hash": "8a4358ac2d5ef4b0",
   "edited": "2026-10-23T15:02:29Z"
  },
  {
   "t": "2026-10-23T15:04:02Z",
   "kind": "review_comment",
   "who": "vasild",
   "assoc": "MEMBER",
   "path": "src/rpc/mempool.cpp",
   "commit": "0aa81936cf2d51f55eeaca26fd036ad8d5fdc09f",
   "in_reply_to": 4349638314,
   "text": "Shortened to just:\n\n```\n\"abortprivatebroadcast\",\n\"Abort private broadcast of a transaction and remove it from the queue.\\n\"\n\"This method is only available when running with -privatebroadcast enabled.\\n\",\n```\ngood?",
   "id": "rc:4360987566",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4360987566",
   "hash": "83ec975bf36dc6cd",
   "edited": null
  },
  {
   "t": "2026-10-24T16:35:40Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": 4317490758,
   "text": "True, upon a re-request there new new relay will happen. Other nodes and this node will have the TX already in their mempool. As a result, \"received_by_us\" will never be set, and it will be not possible to decide/observe the success of the second broadcast.\n\nMy point was, that if the TX is already in our mempool, and for some strange reason it is relayed back to us after the re-request, our node will not request GETDATA (because TX is in the mempool), the handler will not be called, and the \"receive\" flags will remain empty.\n\nThe behavior on `master` is the same, except that the \"received_by_us\" flag is a new addition.\n\nI can see these cases:\n\n1. Already in the mempool, and no re-relay happens (the likely case): The \"received_by_us\" stays empty\n2. Already in the mempool, but re-relay happens: The \"received_by_us\" stays empty -- `AlreadyHaveTx` is true, so no GETDATA is sent, no TX arrives, and the TX handler (`MarkResolved`) is never called.\n3. Not in the mempool and re-relay happens: \"received_by_us\" is set.\n\nCase 2. could be argued about, but I think it's fine. The root of the issue is that upon re-request there will be no new relay.\n\nOne idea that we could consider though: upon a re-request don't clean the \"received\" flag if the TX is already in the mempool (persist that info that we have received it previously; and do perform the new sendouts).",
   "id": "rc:4367750443",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4367750443",
   "hash": "2d13fbffb5cb16ed",
   "edited": null
  },
  {
   "t": "2026-10-27T18:57:09Z",
   "kind": "review_comment",
   "who": "frankomosh",
   "assoc": "CONTRIBUTOR",
   "path": "src/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": 4317490758,
   "text": "[quoted text omitted]\n\nLooks good now.\n\nAlso noticed a good side effect: a tx that used all its attempts can now be removed when the queue is full. Before, it blocked the queue.",
   "id": "rc:4392884135",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4392884135",
   "hash": "9c1824a20efb62a7",
   "edited": null
  },
  {
   "t": "2026-10-27T19:03:21Z",
   "kind": "review_comment",
   "who": "frankomosh",
   "assoc": "CONTRIBUTOR",
   "path": "src/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": 4317514180,
   "text": "Checked on 295c961.., looks good.\n\nMaybe later we could add a test for it. For now, removing `&& !state.received_by_us.has_value()`(mutant), and all tests still unnecesarily pass (unit, fuzz and functional).",
   "id": "rc:4392941929",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4392941929",
   "hash": "c3cf7e3573606c19",
   "edited": null
  },
  {
   "t": "2026-10-28T11:59:13Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/private_broadcast.h",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": null,
   "text": "[quoted text omitted]\n\nMinor: Comment doc should be updated.",
   "id": "rc:4400267796",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4400267796",
   "hash": "3950849b8fcca962",
   "edited": "2026-10-28T12:11:43Z"
  },
  {
   "t": "2026-10-28T12:00:50Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/private_broadcast.h",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": null,
   "text": "[quoted text omitted]\n\nNit: \"(0 if exhausted or completed)\"",
   "id": "rc:4400280803",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4400280803",
   "hash": "fb0617ebc139121f",
   "edited": "2026-10-28T12:11:43Z"
  },
  {
   "t": "2026-10-28T12:02:59Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/fuzz/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": null,
   "text": "[quoted text omitted]\n\nNit: The \"Trimmed by Remove() and Add() cleanup\" part is not fully correct now.",
   "id": "rc:4400299601",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4400299601",
   "hash": "44946d23b57c3ff3",
   "edited": "2026-10-28T12:11:43Z"
  },
  {
   "t": "2026-10-28T12:07:06Z",
   "kind": "review_comment",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "path": "src/private_broadcast.cpp",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "in_reply_to": null,
   "text": "[quoted text omitted]\n\nNit: the expression `state.planned_sends >= m_max_send_attempts` appears 4 times, maybe it could be put into a helper method (e.g. `NoMoreRetries()`).",
   "id": "rc:4400334888",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4400334888",
   "hash": "6e91b160c22ccadd",
   "edited": "2026-10-28T12:11:43Z"
  },
  {
   "t": "2026-10-28T12:11:43Z",
   "kind": "review",
   "who": "optout21",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "text": "Reviewed again, left some nits. I'm happy to revisit soon!\nFriendly reminder [one previous question](https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4367750443) of mine has not been fully addressed yet.",
   "id": "r:5682220784",
   "url": "https://github.com/bitcoin/bitcoin/pull/36477#pullrequestreview-5682220784",
   "hash": "a1cc01751b0c98bd",
   "edited": null
  }
 ],
 "labels_log": [
  {
   "t": "2026-10-08T15:16:46Z",
   "action": "labeled",
   "label": "Private Broadcast",
   "who": "DrahtBot"
  },
  {
   "t": "2026-10-08T15:19:19Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-10-08T17:09:07Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-10-29T16:46:42Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 6701,
 "text_tokens_estimate": 1675,
 "changed_paths": [
  "doc/release-notes-36477.md",
  "src/net_processing.cpp",
  "src/private_broadcast.cpp",
  "src/private_broadcast.h",
  "src/rpc/mempool.cpp",
  "src/test/fuzz/private_broadcast.cpp",
  "src/test/private_broadcast_tests.cpp",
  "test/functional/p2p_private_broadcast.py"
 ],
 "files": [
  {
   "path": "doc/release-notes-36477.md",
   "add": 11,
   "del": 0
  },
  {
   "path": "src/net_processing.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/private_broadcast.cpp",
   "add": 50,
   "del": 18
  },
  {
   "path": "src/private_broadcast.h",
   "add": 31,
   "del": 17
  },
  {
   "path": "src/rpc/mempool.cpp",
   "add": 14,
   "del": 5
  },
  {
   "path": "src/test/fuzz/private_broadcast.cpp",
   "add": 68,
   "del": 20
  },
  {
   "path": "src/test/private_broadcast_tests.cpp",
   "add": 15,
   "del": 7
  },
  {
   "path": "test/functional/p2p_private_broadcast.py",
   "add": 7,
   "del": 3
  }
 ],
 "test_lines": 120,
 "git": {
  "head": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
  "head_matches_backup": true,
  "base": "f655a8df755330911c6c109c8b1d04ef5dd4ea09",
  "patch_id": "53d294bc1c904a5b",
  "commits": [
   {
    "sha": "295c961c1f",
    "subject": "private broadcast: show finished transactions in getprivatebroadcastinfo",
    "files": 8,
    "add": 197,
    "del": 71
   }
  ],
  "patch_truncated": false
 },
 "patch_id": "53d294bc1c904a5b",
 "input_hash": "fc6deff65aab4c68",
 "extracted_at": "2026-11-02T01:09:49+00:00"
}