{
 "number": 36477,
 "input_hash": "bec66f0a8a6aef12",
 "model": "ledger",
 "prompt_hash": null,
 "created": "2026-10-29T01:23:32+00:00",
 "result": {
  "summary": "Retains completed and echoed private broadcast transactions in memory and exposes them in the getprivatebroadcastinfo RPC output instead of dropping them upon network echo. Adds a received_by_us object to the RPC response containing the peer address and timestamp when a transaction is received back from the network. When the private broadcast storage hits capacity, the oldest finished transaction is evicted to accommodate new entries.",
  "problem": "Previously, privately broadcast transactions were pruned from memory once resolved or echoed back from the network. Operators using private broadcast lost visibility into send history, peer acknowledgment times, and echo reception details as soon as the transaction broadcast finished.",
  "card": "Extends getprivatebroadcastinfo to retain and report finished private broadcast transactions rather than dropping them immediately upon network receipt. Adds a received_by_us field indicating the peer address and timestamp when a transaction is echoed back from the network, and evicts the oldest finished transactions when the queue is full. Solves the lack of post-broadcast observability for operators using private transaction broadcast. No dependencies.",
  "evidence": [
   "PR description: '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.'",
   "Release note: 'The information will now not vanish as soon as the transaction is echoed from the network. In addition getprivatebroadcastinfo returns a received_by_us object for echoed transactions, containing the peer address and time of the reception.'"
  ],
  "scope_notes": "",
  "changed_since_previous": "",
  "thread": {
   "last_event_at": "2026-10-28T12:11:43Z",
   "events": 23,
   "head_sha": "295c961c1f156bdbbddfa0f961751d5aa371a62b",
   "schema_floor": 2,
   "schema": 2
  },
  "waiting_on": [
   {
    "at": "2026-10-28",
    "id": "r:5682220784",
    "on": "author",
    "url": "https://github.com/bitcoin/bitcoin/pull/36477#pullrequestreview-5682220784",
    "what": "response to optout21's suggestion on mempool re-broadcasts"
   },
   {
    "at": "2026-10-27",
    "id": "rc:4392941929",
    "on": "author",
    "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4392941929",
    "what": "response to frankomosh's suggestion to add a test"
   }
  ],
  "risk": {
   "level": "medium",
   "touches": [
    "rpc_api",
    "p2p"
   ],
   "why": "A bug in queue retention or eviction logic could leak memory or misreport private broadcast confirmation status over RPC."
  },
  "discussion": {
   "author_status": "last statement processed 2026-10-28",
   "open_concerns": [
    "optout21: Consider not clearing the received flag upon a re-request if the transaction is already in the mempool",
    "frankomosh: Add a test verifying that received_by_us is not overwritten if already set"
   ],
   "resolved_concerns": [
    "frankomosh: What was added or left out compared to #34707? (answered by vasild 2026-10-22)",
    "frankomosh: A transaction that exhausted send attempts without being echoed cannot be sent again because Add() only restarts resolved transactions but GetStale() skips it (accepted by frankomosh 2026-10-27)",
    "frankomosh: Keep the first peer and time rather than overwriting received_by_us when another peer sends the same transaction later (accepted by frankomosh 2026-10-27)",
    "optout21: List the stored categories in RPC help: transactions being actively sent, sent but not echoed back, and echoed back (fixed by vasild 2026-10-23)",
    "optout21: Update this RPC documentation text as well (fixed by vasild 2026-10-23)",
    "optout21: What happens when a previously-finished transaction is requested to be private-broadcast again, and is it intended that it may end up reported as failed? (accepted by optout21 2026-10-24)"
   ]
  },
  "reviewability": {
   "state": "Ready",
   "label": "Needs rebase",
   "reason": "Conflicts with master; review the logic now, the rebase is mechanical."
  },
  "agreement": {
   "state": "Strong",
   "summary": "Strong: substantive support, no open objection (optout21)",
   "reason": "optout21 reviewed again leaving nits and reminded the author about their open suggestion regarding keeping the received flag for transactions already in the mempool.",
   "evidence": [
    "optout21 (suggestion, approach, must be answered, open): Consider not clearing the received flag upon a re-request if the transaction is already in the mempool",
    "frankomosh (suggestion, maintenance, must be answered, open): Add a test verifying that received_by_us is not overwritten if already set",
    "optout21: Concept ACK \u2014 Keeping info about completed transaction is useful for the user and may be useful for feature implementation"
   ],
   "objections": [
    {
     "reviewer": "frankomosh",
     "association": "CONTRIBUTOR",
     "type": "question",
     "kind": "scope",
     "harm": "",
     "request": "",
     "question": "What was added or left out compared to #34707?",
     "text": "What was added or left out compared to #34707?",
     "clears_with": "answer",
     "blocking": false,
     "status": "answered",
     "status_note": "author replied to review this PR fresh as unrelated",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "c:6342040389"
     ],
     "evidence": "2026-10-19: 'I guess this is a continuation of #34707. Could you share what was added or left out compared to it?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36477#pullrequestreview-5576092928",
     "id": "r:5576092928",
     "at": "2026-10-19",
     "status_at": "2026-10-22",
     "status_by": "vasild",
     "resolution_evidence": "2026-10-22: vasild: 'I am unsure. Better review this one as a fresh new unrelated one.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "frankomosh",
     "association": "CONTRIBUTOR",
     "type": "objection",
     "kind": "correctness",
     "harm": "A transaction that exhausted send attempts without being echoed cannot be sent again because Add() only restarts resolved transactions but GetStale() skips it",
     "request": "",
     "question": "",
     "text": "A transaction that exhausted send attempts without being echoed cannot be sent again because Add() only restarts resolved transactions but GetStale() skips it",
     "clears_with": "change",
     "blocking": true,
     "status": "accepted",
     "status_note": "frankomosh confirmed the fix looks good",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4348811647"
     ],
     "evidence": "2026-10-19: '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 nothi'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4317490758",
     "id": "rc:4317490758",
     "at": "2026-10-19",
     "status_at": "2026-10-27",
     "status_by": "frankomosh",
     "resolution_evidence": "2026-10-27: frankomosh: 'Looks good now.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "frankomosh",
     "association": "CONTRIBUTOR",
     "type": "suggestion",
     "kind": "interface",
     "harm": "",
     "request": "Keep the first peer and time rather than overwriting received_by_us when another peer sends the same transaction later",
     "question": "",
     "text": "Keep the first peer and time rather than overwriting received_by_us when another peer sends the same transaction later",
     "clears_with": "answer",
     "blocking": false,
     "status": "accepted",
     "status_note": "frankomosh checked the fix and confirmed it looks good",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4348848801"
     ],
     "evidence": "2026-10-19: '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?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4317514180",
     "id": "rc:4317514180",
     "at": "2026-10-19",
     "status_at": "2026-10-27",
     "status_by": "frankomosh",
     "resolution_evidence": "2026-10-27: frankomosh: 'Checked on 295c961.., looks good.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "optout21",
     "association": "CONTRIBUTOR",
     "type": "suggestion",
     "kind": "interface",
     "harm": "",
     "request": "List the stored categories in RPC help: transactions being actively sent, sent but not echoed back, and echoed back",
     "question": "",
     "text": "List the stored categories in RPC help: transactions being actively sent, sent but not echoed back, and echoed back",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author dropped the sentence and pushed an update",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4360971360"
     ],
     "evidence": "2026-10-22: 'Maybe the text should list the stored categories: transactions being actively sent, sent but not echoed back, and echoed back.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4349623306",
     "id": "rc:4349623306",
     "at": "2026-10-22",
     "status_at": "2026-10-23",
     "status_by": "vasild",
     "resolution_evidence": "2026-10-23: vasild: 'Dropped the sentence.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "optout21",
     "association": "CONTRIBUTOR",
     "type": "suggestion",
     "kind": "interface",
     "harm": "",
     "request": "Update this RPC documentation text as well",
     "question": "",
     "text": "Update this RPC documentation text as well",
     "clears_with": "answer",
     "blocking": false,
     "status": "fixed",
     "status_note": "author shortened the documentation and pushed an update",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": true,
     "replies": [
      "rc:4360987566"
     ],
     "evidence": "2026-10-22: 'This should also be updated.'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4349638314",
     "id": "rc:4349638314",
     "at": "2026-10-22",
     "status_at": "2026-10-23",
     "status_by": "vasild",
     "resolution_evidence": "2026-10-23: vasild: 'Shortened to just:'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "optout21",
     "association": "CONTRIBUTOR",
     "type": "question",
     "kind": "correctness",
     "harm": "",
     "request": "",
     "question": "What happens when a previously-finished transaction is requested to be private-broadcast again, and is it intended that it may end up reported as failed?",
     "text": "What happens when a previously-finished transaction is requested to be private-broadcast again, and is it intended that it may end up reported as failed?",
     "clears_with": "answer",
     "blocking": false,
     "status": "accepted",
     "status_note": "optout21 accepted the explanation of why received_by_us remains unset upon re-broadcast",
     "cleared": true,
     "author_replied": true,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [
      "rc:4360850145"
     ],
     "evidence": "2026-10-22: 'what happens when a previously-finished transaction is requested to be private-broadcast again?'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4349714404",
     "id": "rc:4349714404",
     "at": "2026-10-22",
     "status_at": "2026-10-24",
     "status_by": "optout21",
     "resolution_evidence": "2026-10-24: optout21: 'Case 2. could be argued about, but I think it's fine.'",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "optout21",
     "association": "CONTRIBUTOR",
     "type": "suggestion",
     "kind": "approach",
     "harm": "",
     "request": "Consider not clearing the received flag upon a re-request if the transaction is already in the mempool",
     "question": "",
     "text": "Consider not clearing the received flag upon a re-request if the transaction is already in the mempool",
     "clears_with": "answer",
     "blocking": false,
     "status": "open",
     "status_note": "",
     "cleared": false,
     "author_replied": false,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [],
     "evidence": "2026-10-24: 'One idea that we could consider though: upon a re-request don't clean the \"received\" flag if the TX is already in the mempool'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4367750443",
     "id": "rc:4367750443",
     "at": "2026-10-24",
     "status_at": null,
     "status_by": null,
     "resolution_evidence": "",
     "pin": null,
     "from_schema": 2
    },
    {
     "reviewer": "frankomosh",
     "association": "CONTRIBUTOR",
     "type": "suggestion",
     "kind": "maintenance",
     "harm": "",
     "request": "Add a test verifying that received_by_us is not overwritten if already set",
     "question": "",
     "text": "Add a test verifying that received_by_us is not overwritten if already set",
     "clears_with": "answer",
     "blocking": false,
     "status": "open",
     "status_note": "",
     "cleared": false,
     "author_replied": false,
     "others_replied": false,
     "fix_pushed": false,
     "replies": [],
     "evidence": "2026-10-27: 'Maybe 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).'",
     "url": "https://github.com/bitcoin/bitcoin/pull/36477#discussion_r4392941929",
     "id": "rc:4392941929",
     "at": "2026-10-27",
     "status_at": null,
     "status_by": null,
     "resolution_evidence": "",
     "pin": null,
     "from_schema": 2
    }
   ],
   "support": [
    {
     "reviewer": "optout21",
     "reason": "Keeping info about completed transaction is useful for the user and may be useful for feature implementation",
     "substantive": true,
     "verdict": "Concept ACK",
     "id": "c:6343001721",
     "url": "https://github.com/bitcoin/bitcoin/pull/36477#issuecomment-6343001721",
     "at": "2026-10-22",
     "association": "CONTRIBUTOR",
     "evidence": "read",
     "areas": []
    }
   ],
   "participants": [
    {
     "login": "frankomosh",
     "stance": "objection",
     "note": "raised concern about broken retry logic (accepted fix), peer overwrite (accepted fix), suggested adding a test, and asked about relation to #34707 (answered)",
     "association": "CONTRIBUTOR",
     "comments": 5,
     "first": "2026-10-19",
     "last": "2026-10-27"
    },
    {
     "login": "optout21",
     "stance": "support",
     "note": "Concept ACK; suggested RPC doc updates (fixed), accepted answer on re-broadcast behavior, reminded author of suggestion to persist received flag on re-request, and left code comments/nits",
     "association": "CONTRIBUTOR",
     "comments": 11,
     "first": "2026-10-22",
     "last": "2026-10-28"
    }
   ],
   "derivation": "substantive support, no open objection (optout21)",
   "model_state": null,
   "corrections": [],
   "notes": "optout21 reviewed again leaving nits and reminded the author about their open suggestion regarding keeping the received flag for transactions already in the mempool."
  },
  "dependencies": {
   "depends_on": [],
   "enables": []
  },
  "categories": [
   {
    "name": "docs",
    "member": false,
    "evidence": "Contains doc/release-notes-36477.md, but docs excludes release notes that merely accompany code changes.",
    "band": "Unranked",
    "reason_tag": "cleanup",
    "score": 0.0,
    "factors": {
     "bug_severity": 0,
     "leverage": 0,
     "performance": 0,
     "security_stability": 0,
     "user_value": 1
    },
    "rationale": "Release notes documenting a code change belong to the feature's area rather than docs."
   },
   {
    "name": "p2p",
    "member": true,
    "evidence": "Carries the 'Private Broadcast' label and modifies private broadcast tracking and net processing in src/private_broadcast.cpp and src/net_processing.cpp.",
    "band": "P3",
    "reason_tag": "new feature",
    "score": 0.35,
    "factors": {
     "bug_severity": 0,
     "leverage": 0,
     "performance": 0,
     "security_stability": 0,
     "user_value": 1
    },
    "rationale": "Retaining finished private broadcast transactions provides operator visibility into send history and network echoes without altering core relay or origin privacy protocols. The PR description notes that 'this allows the inspection of when and to whom the transaction was sent as well as when/if it was echoed from the network.'"
   },
   {
    "name": "rpc",
    "member": false,
    "evidence": "Modifies src/rpc/mempool.cpp to expose finished transaction data in getprivatebroadcastinfo, but lacks the RPC label and merely exposes underlying subsystem state.",
    "band": "Unranked",
    "reason_tag": "new feature",
    "score": 0.0,
    "factors": {
     "bug_severity": 0,
     "leverage": 0,
     "performance": 0,
     "security_stability": 0,
     "user_value": 1
    },
    "rationale": "The rpc category explicitly excludes the behavior an RPC merely exposes, which belongs to private broadcast."
   },
   {
    "name": "tests",
    "member": false,
    "evidence": "Touches fuzz, unit, and functional tests specifically covering private broadcast.",
    "band": "Unranked",
    "reason_tag": "test coverage",
    "score": 0.0,
    "factors": {
     "bug_severity": 0,
     "leverage": 0,
     "performance": 0,
     "security_stability": 0,
     "user_value": 1
    },
    "rationale": "Tests pinning the behavior of a specific area belong to that area rather than test infrastructure."
   }
  ],
  "confidence": "high",
  "uncertainties": [],
  "needs": []
 },
 "cost_usd": 0.0,
 "source": {
  "record": "2026-10-29T01:23:32+00:00",
  "code": "2026-10-24T01:21:46+00:00",
  "judgments": 4
 }
}