#36607 private broadcast: Extra guard against unintended non-private broadcast of private transactions
| Reviewability | Reviews | Agreement | Size | ||||
|---|---|---|---|---|---|---|---|
| #36607 private broadcast: Extra guard against unintended non-private broadcast of private transactions | Review #36477 first | 0 | Crickets | 149 + 353 tests | |||
|
|
|
|
| |||
Reviewability: ReadyStalePaused Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs. Size: lines added or modified outside tests, then in tests; greener = smaller. | |||||||
Goal
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—such 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.
Evidence of importance:
- 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: Includes commits and diff from underlying PR #36477, which updates private broadcast queue retention and RPC metadata.
Risk of a mistake: medium (p2p, mempool_policy). Incorrectly identifying announcement reasons or false matches in private broadcast tracking could silence legitimate transaction broadcasts or mempool relay.
Changed since the previous assessment: Tests in test/functional/p2p_private_broadcast_then_public.py were split into separate commits for the submitpackage and wallet resend scenarios.
Reviewability
Ready · Review #36477 first
Stacked on #36477; the base PR's changes are included in this diff.
Waiting on (from the thread read):
- author: author is keeping PR in draft pending prerequisite #36477
Agreement
Crickets
no substantive comment either way
Thread 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.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| maflcko (member) | suggestion, approach | Make the test deterministic using syncs if it cares about trickle delay, or set noban_tx_relay globally if it does not | fixed · fix pushed · author agreed and updated the test to use global noban_tx_relay | answered | yes | 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?' Status from: 2026-10-28: optout21: 'This test doesn't care about trickle delay, so disabling it globally is a simpler solution. Changed now.' |
Participants:
- maflcko (member, neutral, 1 statements 2026-10-28 to 2026-10-28): suggested cleaner approaches for the test trickle-delay fix
Dependencies
Files
383 lines under test/bench/ci.
- test/functional/p2p_private_broadcast_then_public.py +262/-0
- src/test/fuzz/private_broadcast.cpp +68/-20
- src/private_broadcast.cpp +57/-18
- src/private_broadcast.h +38/-17
- src/net_processing.cpp +16/-6
- src/test/private_broadcast_tests.cpp +15/-7
- src/rpc/mempool.cpp +14/-5
- doc/release-notes-36477.md +11/-0
- test/functional/p2p_private_broadcast.py +7/-3
- src/node/types.h +8/-0
- src/net_processing.h +4/-1
- src/node/transaction.cpp +1/-1
- test/functional/test_runner.py +1/-0
Card
The short text the ranking pass compares across PRs.
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.
Data
thread read through 2026-10-28 (4 statements), head 350a7f3783
labels: Needs rebase, Private Broadcast · draft
Categories
P2P
P2 · bug fix
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).
Membership: Has the Private Broadcast label and modifies transaction announcement and relay logic in src/net_processing.cpp and src/private_broadcast.cpp.
Factors: security/stability 2, bug 2, performance 0, user value 1, leverage 0