net: send decoy transactions via private broadcast #35252

pull andrewtoth wants to merge 3 commits into bitcoin:master from andrewtoth:decoys changing 7 files +167 −11
  1. andrewtoth commented at 7:54 PM on May 9, 2026: contributor

    The private broadcast feature removes the link between a transaction and its originating node IP or onion address. However, a passive observer with a large number of sybil nodes can still fingerprint transactions that are broadcast via private broadcast. Any recipient of a transaction via a private broadcast connection can be certain that it was deliberately sent via private broadcast.

    This PR introduces private broadcast decoy connections. Randomly on average once every 3 hours, any node with Tor or I2P reachable opens an extra private broadcast connection. Instead of one of the node's own pending transactions, the connection announces the most recent transaction in the mempool. Because of normal transaction relay latency, the recipient may not have seen that transaction yet, and from its point of view the connection is indistinguishable from a user-submitted private broadcast. If the recipient already has the transaction, the private broadcast will timeout after 3 minutes. In this case there is still plausible deniability since this mimics user-submitted transactions. We open 3 connections for each submitted transaction. After the first successful connection the other connections may connect to nodes that have already received the transaction from the first recipient.

    -blocksonly nodes are excluded. If the mempool is empty, no decoy is sent that round.

    Every user-submitted private broadcast now has plausible deniability of being a decoy.

    This makes it more difficult for a network-level observer to distinguish the traffic pattern of a user-submitted broadcast from a decoy.

    Log lines such as

    New private-broadcast peer connected: transport: v2, version: 70016, peer=xxx
    

    still appear, but they no longer distinguish user-submitted transactions from decoys.

  2. net: start private broadcast thread without requiring -privatebroadcast
    The private broadcast thread is currently only started when
    -privatebroadcast is set. Decouple thread startup from that configuration
    option so that the same connection machinery can be reused for decoys.
    f9936ff872
  3. DrahtBot added the label P2P on May 9, 2026
  4. DrahtBot commented at 7:54 PM on May 9, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

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

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35252.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK kevkevinpal

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #34628 (p2p: Replace per-peer transaction rate-limiting with global rate limits by ajtowns)
    • #31260 (scripted-diff: Type-safe settings retrieval by ryanofsky)
    • #30951 (net: option to disallow v1 connection on ipv4 and ipv6 peers by stratospher)
    • #17783 (common: Disallow calling IsArgSet() on ALLOW_LIST options by ryanofsky)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  5. andrewtoth renamed this:
    p2p: send decoy transactions via private broadcast
    net: send decoy transactions via private broadcast
    on May 9, 2026
  6. kevkevinpal commented at 2:13 PM on May 10, 2026: contributor

    Concept ACK

    Correct me if I'm wrong, but with this change, then that transaction will be forwarded twice from the same node, once via flood and another via private broadcast?

    Wouldn't this add additional network load for nodes, albeit small, considering it is one transaction every 6 hours?

    I like the idea, just worth considering if it does add more bandwidth usage.

  7. andrewtoth commented at 2:53 PM on May 10, 2026: contributor

    Wouldn't this add additional network load for nodes, albeit small, considering it is one transaction every 6 hours?

    On average it would be once every 3 hours. However, since we make feeler connections every 2 minutes, I don't think the bandwidth increase is worth considering. The extra overhead of a private broadcast connection vs a feeler is just an inv -> getdata -> tx and ping + pong.

  8. 0xB10C commented at 9:37 PM on May 10, 2026: contributor

    Because of normal transaction relay latency, the recipient may not have seen that transaction yet, and from its point of view the connection is indistinguishable from a user-submitted private broadcast.

    It would be interesting to measure how well this works. If you are not well connected, for example because you only have 8 transaction relaying outbound connections (which receive invs slower than the inbounds you get) as a home node, you might pick decoys a large part of the network already knows about (especially if it's a high feerate transaction, as these propagate faster). Since the other side wouldn't request these if already in mempool, it's able to tell that these are decoys.

    This can be measured by running this PR and counting how many of the decoy transactions are actually requested from you. It might make sense to do this both for listening and non-listening nodes. For testing, a higher rate of decoys is probably useful: e.g. send a decoy every 5min.

  9. net_processing: periodically send decoy transactions via private broadcast
    Randomly on average once every 3 hours, open one extra private broadcast connection
    and announce the most recent mempool transaction.
    95419a3abf
  10. test: add functional test for private broadcast decoys d3e303875f
  11. andrewtoth force-pushed on May 11, 2026
  12. mzumsande commented at 2:27 AM on May 11, 2026: contributor

    Wouldn't any attacker interested in the origin of txns so much that they would run a large-scale Sybil attack almost certainly also have a permanent connection to each reachable node (which is easier and cheaper) - so that the proposed solution would be ineffective because the attacker very likely would already know about the last mempool transaction?

  13. mzumsande commented at 5:14 AM on May 11, 2026: contributor

    Also, I think it would be good to discuss the general issue this is addressing: Why is it bad if an attacker knows that private broadcast was used for a tx if they can't know the sender? Is the concern that this could lead to some kind of stigmatisation in some (even more) dystopian future, or something different?


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-05-11 12:12 UTC

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