private broadcast: Extra guard against unintended non-private broadcast of private transactions #36607

pull optout21 wants to merge 4 commits into bitcoin:master from optout21:2610-privbcast-guard changing 13 files +495 −76
  1. optout21 commented at 2:03 PM on October 22, 2026: contributor

    Motivation: Reduce the risk of accidental privacy leak happening when broadcasting non-privately a requested transaction that had been previously broadcast privately.

    Background: During the initial phase of private broadcast implementation there were unforeseen instances when a private transaction could get broadcast non-privately (e.g. see #36277 #36330 #36309).

    Currently known pathways:

    • Re-submission through submitpackage
    • Wallet-rebroadcast (when a private transaction is "picked up" by the wallet, and rebrodcast after 1-2 days)

    Note that these are being addressed, but other, currently non-identified pathways cannot be excluded.

    Change summary: 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.

    Transaction relay is not affected, as it should not be affected by private broadcast. When we receive a previously private-broadcast transaction for the first time (it's not yet in our mempool), we relay it as any other relayed transaction. Behavior is unchanged in this regard.

    Notes:

    • Prerequisite: This is built on top of #36477, as keeping finished private broadcasts in the queue is a prerequisite for this change to work.
    • This proposed change is not an alternative to the use-case specific safeguards, but a complementary one.
    • Testing currently uses the two pathways listed above. When they are closed, testing will be more difficult (i.e., it is hard to establish whether non-private broadcast is prevented by the use-case specific or the present generic guard).
    • The private broadcast queue is not persisted, it doesn't survive node restarts
    • Entries deleted via abortprivatebroadcast will be forgotten.
  2. private broadcast: show finished transactions in getprivatebroadcastinfo
    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.
    
    Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
    35ebe832c5
  3. test: Add new private-then-public broadcast test via submitpackage fa04f1e7b6
  4. test: Add private-then-public broadcast test via wallet resend
    Extend p2p_private_broadcast_then_public.py with a second case (if the
    wallet is compiled): a wallet transaction is sent via private broadcast,
    comes back from the network into the mempool and the wallet of the
    originator, and is then announced to all peers by the periodic resend
    of the wallet.
    57fb0ee289
  5. net_processing: don't announce privately broadcast txs on request
    With -privatebroadcast, sendrawtransaction sends the transaction only
    via short-lived private broadcast connections and does not add it to
    the mempool. However, other code paths can later add the same
    transaction to the mempool and announce it to all peers, which links
    the transaction to this node:
    - the submitpackage RPC
    - the wallet, on commit and on its periodic resend (e.g. after the
      transaction came back from the network and was picked up by the
      wallet)
    - the GUI PSBT broadcast
    - ReattemptInitialBroadcast(), for transactions in the unbroadcast set
    
    All of these end up in PeerManager::InitiateTxBroadcastToAll(), which
    is also used to relay transactions received from peers. Add a reason
    parameter to it (RELAY or REQUESTED). If the reason is not RELAY and
    the transaction is known to the private broadcast storage, then do not
    announce it, remove it from the mempool's unbroadcast set, so that it
    is not retried, and log that.
    
    Relaying a privately broadcast transaction after it was received back
    from the network is not affected: at that point the node behaves like
    any other node that received the transaction.
    
    Extend p2p_private_broadcast_then_public.py to check that re-sending
    a privately broadcast transaction via submitpackage or via the periodic
    resend of the wallet does not reach a public peer, while another
    transaction sent the same way does.
    a100ddec89
  6. DrahtBot added the label Private Broadcast on Oct 22, 2026
  7. DrahtBot commented at 2:03 PM on October 22, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    External sites

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process. A summary of reviews will appear here.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

    LLM Linter (✨ experimental)

    Possible typos and grammar issues:

    • test/functional/p2p_private_broadcast_then_public.py: privateproadcast-aware → private-broadcast-aware [misspelling]

    <sup>2026-10-22 14:03:31</sup>

  8. DrahtBot added the label CI failed on Oct 22, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-10-25 01:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me