{
 "number": 36607,
 "input_hash": "07a3fc4020818340",
 "model": "ledger",
 "prompt_hash": null,
 "created": "2026-10-30T01:12:40+00:00",
 "result": {
  "summary": "Adds a safeguard in PeerManager to prevent transactions tracked in private broadcast storage from being announced over public peer connections. It introduces a TxAnnounceReason parameter to distinguish transaction relay (received from network peers) from local announcement requests (such as RPC submissions, wallet rebroadcasts, and mempool unbroadcast retries). If a non-relay announcement is initiated for a transaction present in private broadcast storage, PeerManager suppresses the broadcast and removes the transaction from the mempool unbroadcast set.",
  "problem": "Transactions broadcast via private broadcast can inadvertently be announced to public peers if re-triggered locally\u2014such as through submitpackage RPC calls, periodic wallet resends after the transaction is echoed back from the network, GUI PSBT broadcasts, or unbroadcast retry timers. Announcing them to public peers exposes the node as the origin and undermines private broadcast protections.",
  "card": "Adds a safeguard in PeerManager to block unintended public announcements of transactions previously sent via private broadcast. Subsystems like submitpackage, periodic wallet rebroadcast, and mempool unbroadcast retries could otherwise announce these transactions across public peer connections, leaking origin identity. PeerManager::InitiateTxBroadcastToAll distinguishes relay from requested announcements, dropping public announcements and clearing unbroadcast retries for transactions tracked in private broadcast storage. It depends on base PR #36477 to keep finished private broadcast records in memory so they can be matched.",
  "evidence": [
   "PR description: 'During the initial phase of private broadcast implementation there were unforeseen instances when a private transaction could get broadcast non-privately (see #35032 #35319 #35410 #36309 #36312 #36277 #36330)... Add a general, extra safeguard: whenever there is a transaction broadcast request, check if the given transaction has been previously broadcast privately, and if so, refuse to broadcast non-privately.'"
  ],
  "scope_notes": "Includes commits and diff from underlying PR #36477, which updates private broadcast queue retention and RPC metadata.",
  "changed_since_previous": "Tests in test/functional/p2p_private_broadcast_then_public.py were split into separate commits for the submitpackage and wallet resend scenarios.",
  "thread": {
   "last_event_at": "2026-10-28T09:40:29Z",
   "events": 4,
   "head_sha": "350a7f37832cba1fc4e453806efd2f4726553968",
   "schema_floor": 2,
   "schema": 2
  },
  "waiting_on": [
   {
    "at": null,
    "id": "",
    "on": "author",
    "url": null,
    "what": "author is keeping PR in draft pending prerequisite #36477"
   }
  ],
  "risk": {
   "level": "medium",
   "touches": [
    "p2p",
    "mempool_policy"
   ],
   "why": "Incorrectly identifying announcement reasons or false matches in private broadcast tracking could silence legitimate transaction broadcasts or mempool relay."
  },
  "discussion": {
   "author_status": "last statement processed 2026-10-28",
   "open_concerns": [],
   "resolved_concerns": [
    "maflcko: Make the test deterministic using syncs if it cares about trickle delay, or set noban_tx_relay globally if it does not (fixed by optout21 2026-10-28)"
   ]
  },
  "reviewability": {
   "state": "Ready",
   "label": "Review #36477 first",
   "reason": "Stacked on #36477; the base PR's changes are included in this diff."
  },
  "agreement": {
   "state": "Crickets",
   "summary": "Crickets: no substantive comment either way",
   "reason": "Initial record for draft PR. maflcko suggested a cleaner approach to fixing a test CI failure, which the author implemented. / Initial record. maflcko suggested setting noban_tx_relay globally to resolve a CI timeout, which author implemented.",
   "evidence": [],
   "objections": [
    {
     "reviewer": "maflcko",
     "association": "MEMBER",
     "type": "suggestion",
     "kind": "approach",
     "harm": "",
     "request": "Make the test deterministic using syncs if it cares about trickle delay, or set noban_tx_relay globally if it does not",
     "question": "",
     "text": "Make the test deterministic using syncs if it cares about trickle delay, or set noban_tx_relay globally if it does not",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author agreed and updated the test to use global noban_tx_relay",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "c:6465630280"
     ],
     "evidence": "2026-10-28: 'either the test here cares about trickle-delay, in which case it would be cleaner to not use `noban` permission and instead make the test deterministic with syncs or so? Or, the test doesn't care about trickle delay, and can just set `noban_tx_relay` globally?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36607#issuecomment-6464447216",
     "id": "c:6464447216",
     "at": "2026-10-28",
     "status_at": "2026-10-28",
     "status_by": "optout21",
     "resolution_evidence": "2026-10-28: optout21: 'This test doesn't care about trickle delay, so disabling it globally is a simpler solution. Changed now.'",
     "pin": null,
     "from_schema": 2
    }
   ],
   "support": [],
   "participants": [
    {
     "login": "maflcko",
     "stance": "neutral",
     "note": "suggested cleaner approaches for the test trickle-delay fix",
     "association": "MEMBER",
     "comments": 1,
     "first": "2026-10-28",
     "last": "2026-10-28"
    }
   ],
   "derivation": "no substantive comment either way",
   "model_state": null,
   "corrections": [],
   "notes": "Initial record for draft PR. maflcko suggested a cleaner approach to fixing a test CI failure, which the author implemented. / Initial record. maflcko suggested setting noban_tx_relay globally to resolve a CI timeout, which author implemented."
  },
  "dependencies": {
   "depends_on": [
    "#36477"
   ],
   "enables": []
  },
  "categories": [
   {
    "name": "docs",
    "member": false,
    "evidence": "Touches only doc/release-notes-36477.md as part of an underlying PR, not documentation as a primary change.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 2,
     "leverage": 0,
     "performance": 0,
     "security_stability": 2,
     "user_value": 1
    },
    "rationale": ""
   },
   {
    "name": "p2p",
    "member": true,
    "evidence": "Has the Private Broadcast label and modifies transaction announcement and relay logic in src/net_processing.cpp and src/private_broadcast.cpp.",
    "band": "P2",
    "reason_tag": "bug fix",
    "score": 0.68,
    "factors": {
     "bug_severity": 2,
     "leverage": 0,
     "performance": 0,
     "security_stability": 2,
     "user_value": 1
    },
    "rationale": "Prevents origin privacy leaks where transactions submitted via private broadcast are inadvertently broadcast to public peers by local re-triggers such as RPC calls, wallet resends, or unbroadcast timers. Protecting privacy of transaction origin is a top priority in p2p, and this adds a comprehensive safeguard against recurring leak vectors identified across earlier PRs (#35032, #35319, #36309)."
   },
   {
    "name": "rpc",
    "member": false,
    "evidence": "Minor edits in src/rpc/mempool.cpp merely reflect underlying private broadcast metadata rather than modifying RPC interfaces or machinery.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 2,
     "leverage": 0,
     "performance": 0,
     "security_stability": 2,
     "user_value": 1
    },
    "rationale": ""
   },
   {
    "name": "tests",
    "member": false,
    "evidence": "Changes to fuzz and functional tests specifically test private broadcast p2p behavior rather than the testing framework itself.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 2,
     "leverage": 0,
     "performance": 0,
     "security_stability": 2,
     "user_value": 1
    },
    "rationale": ""
   }
  ],
  "confidence": "high",
  "uncertainties": [],
  "needs": []
 },
 "cost_usd": 0.0,
 "source": {
  "record": "2026-10-30T01:12:40+00:00",
  "code": "2026-10-30T01:17:00+00:00",
  "judgments": 4
 }
}