wallet: only rebroadcast transactions originating from the wallet #36398

pull mzumsande wants to merge 2 commits into bitcoin:master from mzumsande:202620_wallet_restric_rebroadcast changing 3 files +28 −6
  1. mzumsande commented at 2:25 PM on October 1, 2026: contributor

    As explained in #3828, rebroadcast of transactions paying the wallet (but not spending any wallet inputs) is a privacy leak, since anyone can generate these, choose a low fee, and observe who rebroadcasts them. While it is somewhat intuitive that submitting transactions has privacy implications - at least until confirmation - this is manageable by various strategies (switching to privacy networks for a while, using private broadcast, making sure it confirms before rebroadcast). However, I find it rather unexpected that just passively running a node with a wallet loaded can lead to a loss of privacy as well.

    This PR stops rebroadcasting transactions that don't spend any wallet inputs. For the same reason, they are also no longer re-added to the mempool on startup or after an import: otherwise our node might be the only one still having a transaction the rest of the network has dropped, which can be detected with active probing (e.g. by submitting a child).

    This does have the trade-off that receivers (who have an incentive to get paid) will now need to manually resubmit transactions if the transaction doesn't confirm and the sender doesn't rebroadcast, but I think it is worth the privacy benefit.

    An alternative approach is #36380, although these could also be combined (make rebroadcast optional, but never rebroadcast non-originating transactions)

    Fixes #3828

  2. wallet: only rebroadcast transactions originating from the wallet
    Rebroadcasting transactions that only pay the wallet is a privacy leak,
    since anyone can send low-fee transactions to a wallet, unlikely to be
    mined in 24h, and observe who rebroadcasts them. Also don't re-add them
    to the mempool in case of a restart if they were previously dropped, to
    prevent active probing.
    
    This means that rebroadcasting is now the sole responsibility of the
    sender.
    23813b6ad5
  3. DrahtBot added the label Wallet on Oct 1, 2026
  4. DrahtBot commented at 2:25 PM on October 1, 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.

    Type Reviewers
    Concept NACK achow101
    Concept ACK vasild

    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:

    • #36482 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/36482.svg"></sub> (wallet: Only broadcast resubmitted transactions that were added to the mempool by achow101)
    • #36380 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/36380.svg"></sub> (wallet: extend -walletbroadcast to allow initial send only by vasild)
    • #35820 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/35820.svg"></sub> (refactor: keep duration calculations typed by l0rinc)
    • #10102 <sub><img src="https://drahtbot.space/ack_count/bitcoin/bitcoin/10102.svg"></sub> (Multiprocess bitcoin 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. doc: add release note for wallet rebroadcast change f63a38f781
  6. mzumsande force-pushed on Oct 1, 2026
  7. DrahtBot added the label CI failed on Oct 1, 2026
  8. DrahtBot removed the label CI failed on Oct 1, 2026
  9. achow101 commented at 5:25 PM on October 1, 2026: member

    Concept NACK-ish

    Rebroadcasting transactions that are not ours is useful as rebroadcasting does have an effect on getting such transactions confirmed. Furthermore, if we want to CPFP a transaction, it needs to be in our mempool first, otherwise the wallet will be unable to broadcast the child.

    Instead of trying to delete rebroadcasting in the name of privacy, we should consider other ways to enable rebroadcasting in a privacy preserving manner, such as a rebroadcast pool in the node.

  10. instagibbs commented at 5:51 PM on October 1, 2026: member

    rebroadcast pool histories: #16698 and #21061 in case its helpful

    I think we need to start a fresh issue on the topic and lay down alternatives side by side

  11. achow101 commented at 7:49 PM on October 1, 2026: member

    I've opened #36403 where we can have more high level discussion about transaction rebroadcast in general.

  12. vasild commented at 8:27 AM on October 6, 2026: contributor

    Concept ACK, but make this configurable somehow.

    Like somebody said "there is no one size fits all" and from above - rebroadcasting by the recipient has some positive sides.

    In such cases I think it is best if we let the users decide what is best for them - give them the tools to configure it according to their environment and priorities.

    If you decide to make this configurable, one possibility would be to extend -walletbroadcast=<0|1> with a new value, similarly to #36380.

  13. fametrano commented at 11:23 AM on October 25, 2026: contributor

    After a restart without mempool.dat, or after mempool expiry, a CPFP child that the wallet itself created for an incoming payment stays out of the mempool on this branch, and no resend timer brings it back.

    The child spends our output of the incoming parent, so IsFromMe() still selects it, but the parent is now skipped, and without the parent the child cannot enter the mempool. I measured this on regtest at f63a38f781 and at its base d4b0e1e4b0: one node pays the wallet at 1 sat/vB and is disconnected, then the wallet spends that unconfirmed output at 50 sat/vB. After a restart with -persistmempool=0, the base re-adds both transactions and announces both to a fresh peer at the next resend timer; this branch re-adds neither and announces neither. Letting both expire from the mempool, without a restart, gives the same result. Submitting the parent by hand with sendrawtransaction, as the release note suggests, brings the child back at the next timer.

    achow101 noted above that CPFP needs the parent in our mempool; this is the same dependency once the child already exists. One way to keep it would be to also resubmit an unconfirmed incoming parent whose output a resubmitted transaction of ours spends: announcing that child already shows that the parent pays us. Otherwise the release note could name this case. I can share the probe script.


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-30 09:40 UTC