BIP451: Dust UTXO Disposal Protocol #2150

pull bubb1es71 wants to merge 6 commits into bitcoin:master from bubb1es71:ddust_protocol_bip changing 2 files +286 −0
  1. jonatack added the label New BIP on Apr 24, 2026
  2. jonatack renamed this:
    Add draft BIP for a dust utxo disposal protocol
    BIP draft: Dust UTXO Disposal Protocol
    on Apr 24, 2026
  3. in bip-XXXX.md:172 in 4089a81c3e
     167 | +
     168 | +Bitcoin relay policy enforces a minimum transaction base size of 65 bytes to prevent certain attack vectors. Compliant transactions must meet this threshold to be relayed by standard nodes.
     169 | +
     170 | +### Why 0.1 sat/vB Minimum Fee Rate?
     171 | +
     172 | +Dust disposal transactions must meet the minimum relay fee rate, which is currently 0.1 sat/vB (Bitcoin Core 28.3, 29.1, 30.0+). This allows dust UTXOs to be disposed of economically even when their value is small. Implementations targeting older node versions may need higher minimum fee rates.
    


    jonatack commented at 7:59 PM on April 24, 2026:

    Maybe address theoretical updating if the minimum relay fee rate changes in the future.


    bubb1es71 commented at 2:24 AM on April 25, 2026:

    Would adding a sentence like this work?

    "Dust disposal transactions should always pay at least the current standard minimum relay fee rate if it changes in the future."

  4. jonatack commented at 8:01 PM on April 24, 2026: member

    Looks complete and correct at first glance.

  5. jonatack added the label Needs number assignment on Apr 25, 2026
  6. Add draft BIP for dust utxo disposal protocol d65128a8fe
  7. bubb1es71 force-pushed on Apr 27, 2026
  8. in bip-XXXX.md:24 in d65128a8fe
      19 | +
      20 | +## Motivation
      21 | +
      22 | +### The Dust Attack Problem
      23 | +
      24 | +Dust attacks are a well-documented privacy threat where attackers send small amounts of bitcoin to numerous addresses. When wallet software later consolidates these dust UTXOs with non-dust UTXOs, the attacker can analyze the blockchain to link previously unassociated addresses, potentially deanonymizing users.
    


    murchandamus commented at 4:15 PM on April 27, 2026:

    Perhaps:

    Dust attacks are a well-documented privacy threat where attackers send small amounts of bitcoin to numerous addresses. When wallet software later consolidates these dust UTXOs with non-dust UTXOs, the attacker use the [common-input-ownership heuristic](https://en.bitcoin.it/wiki/Privacy#Common-input-ownership_heuristic) to link previously unassociated addresses together and with future spending, reducing the privacy of users.
    
  9. in bip-0451.md:41 in d65128a8fe outdated
      36 | +
      37 | +- **No New UTXOs**: OP_RETURN outputs are provably unspendable and not stored in the UTXO set.
      38 | +- **No Address Linking**: Without a change output, there is no new address to link.
      39 | +- **Permanent Removal**: The dust UTXOs are removed from the user's wallet entirely.
      40 | +- **Miner Compensation**: OP_RETURN outputs are small, providing higher transaction fee rates.
      41 | +- **No Cost to Victims**: Dust attack UTXO values are used to pay for their own disposal.
    


    murchandamus commented at 4:23 PM on April 27, 2026:

    The term “dust” is so central to this proposal, that you might want to clarify how you use the term. Colloquially, dust refers often to any small amounts, Bitcoin Core defines dust as outputs that are less valuable than specific amounts for specific output types, and another colloquial meaning refers to outputs of amounts that cannot pay for themselves. E.g., 1-sat outputs from the Socchi spam wave cannot pay for themselves even at the new lower feerates.

    Edit: I see that line 97 does sort of define “dust”, but perhaps that definition could be moved earlier in the text.


    bubb1es71 commented at 2:50 AM on April 28, 2026:

    I agree we should clarify that the concern of this BIP is disposing of dust used in a "dust attack", i.e. dust used to de-anonymizing a user using the common input ownership heuristic (as you linked above). We're not concerned with UTXOs that just happen to be too small to pay for themselves or match the exact core definition. I'll work on improving the abstract and/or motivation.


    murchandamus commented at 5:04 AM on April 28, 2026:

    Ah sounds good. I think another term of art for that is “forced address reuse attack”.


    bubb1es71 commented at 12:52 AM on April 29, 2026:

    Is it OK to rename this proposal to "Dust Attack UTXO Disposal Protocol" ? The goal is to clarify that the protocol is focused on disposing of dust attack UTXOs and not the other kinds of dust UTXOs. I also added an aka "forced address reuse attack" in the Motivation section.


    bubb1es71 commented at 10:05 PM on April 29, 2026:

    Keeping proposal name "Dust UTXO Disposal Protocol".

  10. in bip-XXXX.md:61 in d65128a8fe
      56 | +A compliant dust disposal transaction MUST satisfy all the following requirements:
      57 | +
      58 | +#### Overall
      59 | +
      60 | +1. The nLockTime MUST be set to block height 0.
      61 | +2. The fee rate MUST be at least 0.1 sat/vB.
    


    murchandamus commented at 4:24 PM on April 27, 2026:

    Perhaps:

    2. The fee rate MUST be at least the minimum transaction relay feerate (0.1 sat/vB at the time of writing).
    
  11. in bip-0451.md:69 in d65128a8fe outdated
      64 | +
      65 | +1. The transaction MUST have exactly one output.
      66 | +2. The single output MUST be an OP_RETURN.
      67 | +3. The OP_RETURN data MUST be either:
      68 | +   - Empty: `0x6a 0x00` (OP_RETURN OP_0), or
      69 | +   - The ASCII string "ash": `0x6a 0x03 0x61 0x73 0x68` (OP_RETURN OP_PUSHBYTES_3 "ash").
    


    murchandamus commented at 4:33 PM on April 27, 2026:

    I had the impression from our discussion on the mailing list that you were considering on always requiring the ash output in order for all transactions to always be aggregatable. Looking at it again, I realize that it was the answer from Steven Slater that made me think so. I assume you considered only standardizing a single output variant, but could you perhaps further explain in the Rationale why you decided to settle on two output variants rather than eating the slightly elevated size for legacy and wrapped segwit transactions in favor of a simpler protocol?


    bubb1es71 commented at 2:37 AM on April 28, 2026:

    The rationale here is that in most cases there won't be an opportunity to batch, so we should be as efficient as possible for spending the legacy dust who don't get the witness discount. And in practice as legacy usage dies off most dust disposal tx will have witness inputs and need the OP_RETURN "ash" output anyway. I'll add this to the rationale section.


    bubb1es71 commented at 12:55 AM on April 29, 2026:

    Working on an update to reference code per bubb1es71/ddust#36 and then will update BIP here.

  12. in bip-0451.md:76 in d65128a8fe outdated
      71 | +#### Inputs
      72 | +
      73 | +1. All inputs MUST set the nSequence to 0xFFFFFFFF (do not signal for BIP 125 RBF).
      74 | +2. All inputs MUST use the signature hash type `ALL|ANYONECANPAY` (0x81).
      75 | +3. For Taproot (P2TR) inputs using key-path spending, implementations MUST explicitly append the signature hash type byte `ALL|ANYONECANPAY` (0x81) to enable ANYONECANPAY semantics, as the default sighash for Taproot (SIGHASH_DEFAULT, which omits the byte) does not include ANYONECANPAY.
      76 | +4. All inputs must be confirmed in the blockchain at least one block deep.
    


    murchandamus commented at 4:35 PM on April 27, 2026:

    I’m curious why you require that inputs must be confirmed. Could you please add that to the Rationale?


    bubb1es71 commented at 2:07 AM on April 28, 2026:

    The thinking is that we don't want a dust attacker to see their dust is being disposed of and double spend it before it's confirmed. And if the dust is included in a batch with other disposed dust this could be a way for the dust attackers to fight back against (or at least grief) victims trying to dispose of their dust attack UTXOs. Additionally there's generally no urgency in disposing of dust since it can temporarily be locked to prevent it from being accidentally spent while unconfirmed. I'll update the rationale section.

  13. in bip-XXXX.md:93 in d65128a8fe
      88 | +
      89 | +### Dust Selection
      90 | +
      91 | +Implementations SHOULD allow users to configure how dust UTXOs are selected based on:
      92 | +
      93 | +1. The current and anticipated fee rates.
    


    murchandamus commented at 4:40 PM on April 27, 2026:

    Since the feerate directly follows from the potential dust UTXO (i.e. its amount and output type), it is not obvious to me why the current or anticipated feerates play a relevant role: whenever the transaction would be created it would have the same feerate anyway.

    I do see that sending a dust disposal transaction when the current demand is low would lead to quick confirmation which would quickly resolve the wallet’s dust situation. However, broadcasting at high feerates would give more time for multiple dust disposals to be aggregated. So, really any time seems fine for different reasons.

    I would also point out that if wallets have opinionated default behavior on when to create and broadcast dust disposal transactions, the broadcast time might become a (weak?) wallet fingerprint.


    bubb1es71 commented at 3:22 AM on April 28, 2026:

    We were thinking here about the dynamic mempoolminfee and that if mempools are full or near full users (or their wallets) may have to make a judgement call when selecting viable dust UTXOs to try to dispose of.

    Would it make more sense to rewrite this section to make the only user configurable parameters the max UTXO amount that is considered dust. This is needed since we don't know how the amounts may change in the future. And otherwise dust UTXOs should always be selected if the fee rate of their dispose tx is at least the mempoolminfee rate?


    murchandamus commented at 9:33 PM on April 28, 2026:

    A configurable max amount sounds like a good idea generally. Broadcasting transactions only when they make it into the mempool also sounds reasonable. Although it is not logistically an issue if the transaction were created when it doesn’t propagate. If you e.g., create a transaction in Bitcoin Core it will be rebroadcast every 12–24h until it gets confirmed. Especially if you intend to use privatebroadcast it doesn’t seem like a big privacy issue either, if it were submitted to peers a few more times before it propagates widely.


    bubb1es71 commented at 10:04 PM on April 28, 2026:

    I forgot that Bitcoin Core will keep rebroadcasting so I think it's safe here to just focus on letting the user configure the max amount.

  14. in bip-0451.md:102 in d65128a8fe outdated
      97 | +A UTXO is generally considered dust if its value is less than the cost to spend it at a reasonable fee rate, but any small UTXO value could be used in a dust attack.
      98 | +
      99 | +Implementations SHOULD NOT select dust UTXOs for disposal if there are any unspent, non-dust UTXOs for the same address. This is especially important if:
     100 | +
     101 | +1. No funds have previously been spent from the address.
     102 | +2. The address type uses a hashed public key (e.g. P2PKH, P2WPKH).
    


    murchandamus commented at 4:47 PM on April 27, 2026:

    Perhaps give a recommendation what to do with such outputs:

    Implementations SHOULD NOT select dust UTXOs for disposal if there are any unspent, non-dust UTXOs for the same address. This is especially important if:
    
    1. No funds have previously been spent from the address.
    2. The address type uses a hashed public key (e.g. P2PKH, P2WPKH).
    
    Instead, the dust UTXO should be spent together with the other UTXOs that share the same output script at the time that any of the UTXOs is selected, or may be disposed after the other UTXOs have been spent, if it would reduce the feerate of the transaction that spends the other UTXOs.
    

    bubb1es71 commented at 11:46 PM on April 28, 2026:

    Instead, the dust UTXO should be spent together with the other UTXOs that share the same output script at the time that any of the UTXOs is selected, or may be disposed after the other UTXOs have been spent, if it would reduce the feerate of the transaction that spends the other UTXOs.

    I'd rather not include the above since it gets into the whole topic of how to safely spend dust UTXOs and not how to dispose of them.

    A protocol for safely and efficiently spending dust UTXOs to a non-OR outputs should probably be its own BIP.

  15. in bip-0451.md:109 in d65128a8fe outdated
     104 | +### Address Consolidation Rules
     105 | +
     106 | +Implementations consolidating dust UTXOs owned by a single user (i.e., not batching unrelated dust UTXOs):
     107 | +
     108 | +- MUST NOT spend dust UTXOs that were sent to different addresses in the same transaction.
     109 | +- MUST NOT broadcast dust disposal transactions at the same time for dust sent to different addresses.
    


    murchandamus commented at 4:49 PM on April 27, 2026:

    This text should perhaps make clearer that no user should broadcast a transaction with multiple dust inputs in the first instance any of those outputs are seen. However, especially if it were generally recommended best practice for wallets to add their own inputs to transactions seen in the mempool, or to disseminate queued dust disposal transactions whenever any are seen in the mempool, it could be indistinguishable for a disposer to privately broadcast multiple dust disposals in a slightly staggered sequence.


    bubb1es71 commented at 3:38 AM on April 28, 2026:

    I'll add the recommendation to always try to batch a dust input with an unconfirmed disposal tx if one exists and refer to the batching section.

    I get what you mean that privately broadcasting staggered dust should still be private. But there's no way to know what intervals would be safe since we don't know how frequently this will be used. And even if we had some historic data the patterns could change in unexpected ways. I think it's safer to leave it up to human judgement on when and which UTXOs to dispose of.


    murchandamus commented at 9:34 PM on April 28, 2026:

    SGTM.

  16. in bip-XXXX.md:144 in d65128a8fe
     139 | +- **Key Security**: Signing dust disposal transactions requires signing with the user's wallet private keys. This could be a risk for cold storage wallets where the key or keys needed to sign are not easily accessible.
     140 | +- **Transaction Correctness**: Transaction signers must carefully review and verify that only dust UTXOs are spent and no other inputs are signed.
     141 | +
     142 | +#### Privacy Preservation
     143 | +
     144 | +- **Network surveillance**: Internet service providers and other internet monitors may be able to determine the nodes that initially broadcast a dust disposal transaction. If available the `sendrawtransaction -privatebroadcast` RPC feature should be used (Bitcoin Core 31.0).
    


    murchandamus commented at 5:01 PM on April 27, 2026:

    Just the version is a bit underspecified, and it may become available in other software later. How about:

    - **Network surveillance**: Internet service providers and other internet monitors may be able to determine the nodes that initially broadcast a dust disposal transaction. If available the `sendrawtransaction -privatebroadcast` RPC feature should be used (e.g., available in Bitcoin Core 31.0+).
    
  17. in bip-0451.md:160 in d65128a8fe outdated
     155 | +### Why Empty or "ash" OP_RETURN Data?
     156 | +
     157 | +- **Minimal Size**: Empty data (2 bytes: OP_RETURN OP_0) minimizes the transaction size.
     158 | +- **Standardization**: Consistent transaction construction eliminates wallet fingerprinting.
     159 | +- **Padding Option**: The "ash" string (5 bytes: OP_RETURN OP_PUSHBYTES_3 "ash") provides a standardized way to meet the minimum transaction size; e.g., for a single P2TR dust input.
     160 | +- **Semantic Meaning**: The word "ash" metaphorically represents the result of "burning" the dust.
    


    murchandamus commented at 5:19 PM on April 27, 2026:

    My gut feeling is that it is still preferable to only standardize one output variant. From the sender’s perspective, the transaction will for itself either way. Since the empty OR-output is only feasible for legacy and wrapped segwit inputs, it increases the transaction size by less than 1.8%, but it makes all transactions aggregatable. It’s just saving 3 bytes, but aggregating a solitary dust input into another transaction saves 21 bytes. So if increased compatibility caused one in seven transactions to be aggregated rather than solitary, it would break even. It would also make it simpler to implement support for this proposal, in particular the aggregation.


    bubb1es71 commented at 3:49 AM on April 28, 2026:

    I'll think on this a bit more, it would simplify the spec and code.

    As mentioned in my other comment our assumption is that batching won't happen too often and eventually be all segwit OR "ash" variety anyway. But OTOH if this spec becomes widely adopted there are plenty of dust UTXOs out there that can/should be disposed of and batching saves more than the extra "ash" bytes.

  18. in bip-XXXX.md:166 in d65128a8fe
     161 | +
     162 | +### Why Per-Address Transactions?
     163 | +
     164 | +Consolidating dust from multiple addresses for the same wallet creates the same privacy harm that dust attacks attempt to achieve. By requiring implementations to create separate transactions per address (by default), the protocol ensures dust disposal doesn't harm privacy.
     165 | +
     166 | +### Why 65 Byte Minimum?
    


    murchandamus commented at 5:20 PM on April 27, 2026:
    ### Why 65-Byte Minimum?
    
  19. in bip-XXXX.md:244 in d65128a8fe
     239 | +
     240 | +#### Example dust disposal transaction sizes
     241 | +
     242 | +|                   | P2PKH | P2SH (2-3) | P2WPKH | P2WSH (2-3) | P2TR  |
     243 | +|-------------------|-------|------------|--------|-------------|-------|
     244 | +| Overhead (b)      | 10    | 10         | 10     | 10          | 10    | 
    


    murchandamus commented at 5:26 PM on April 27, 2026:

    Nit: byte is abbreviated with a capital B

  20. in bip-0451.md:264 in d65128a8fe outdated
     259 | +| 325          | 1.92    | 1.03       | 3.51   | 2.51        | 3.95  |
     260 | +| 330          | 1.95    | 1.04       | 3.57   | 2.55        | 4.01  |
     261 | +
     262 | +### Batching dust disposal txs via RBF
     263 | +
     264 | +1. Adding a Bech32m dust input to an unconfirmed disposal transaction with a legacy dust input keeps the original single empty OP_RETURN output.
    


    murchandamus commented at 5:30 PM on April 27, 2026:

    If you are going to retain the two output variants, perhaps it should be best practice that any non-native-segwit input that is added to a dust disposal transaction with an “ash” output is first broadcast as a solitary transaction with an empty OP_RETURN ouput, before the aggregated transaction. This would give the other dust disposer with the ASH output the opportunity to instead add their input to the transaction with the empty OR output.

    Still, it seems simpler to only standardize one output variant.

  21. murchandamus commented at 5:35 PM on April 27, 2026: member

    Looks pretty good already! Thanks again for working on this so diligently before submitting it here.

  22. murchandamus commented at 2:00 PM on April 28, 2026: member

    Let’s call this BIP 451. Please add the number to the preamble, set the Assigned header to today, rename the BIP file, and add an entry to the README table.

  23. murchandamus renamed this:
    BIP draft: Dust UTXO Disposal Protocol
    BIP451: Dust UTXO Disposal Protocol
    on Apr 28, 2026
  24. murchandamus removed the label Needs number assignment on Apr 28, 2026
  25. Assign number 451, update preamble, rename BIP file, and add entry to README table 44e79b16de
  26. murchandamus added the label PR Author action required on Apr 28, 2026
  27. bubb1es71 commented at 12:44 AM on April 29, 2026: contributor

    I pushed 54bccb1 with some small edits. I'll squash this and other commits once the review process is done.

  28. Small edits
    * Change title, abstract, motivation to focus on dust attack UTXOs
    * Simpify dust selection section
    * Add batching to address consolidation rules
    * Fix core version in privacy preservation
    * Fix table units
    54bccb1bd6
  29. bubb1es71 force-pushed on Apr 29, 2026
  30. murchandamus commented at 12:59 AM on April 29, 2026: member

    Yeah, thanks, adding separate commits without squashing them during the review phase is preferred.

  31. bubb1es71 force-pushed on Apr 29, 2026
  32. Add confirmed utxo rationale a9dcb9e2e7
  33. bubb1es71 force-pushed on Apr 29, 2026
  34. in bip-0451.md:4 in a9dcb9e2e7
       0 | @@ -0,0 +1,281 @@
       1 | +```
       2 | +  BIP: 451
       3 | +  Layer: Applications
       4 | +  Title: Dust Attack UTXO Disposal Protocol
    


    murchandamus commented at 4:51 PM on April 29, 2026:

    Weak opinion weakly held, but I thought the title was better without “Attack”. It doesn’t really matter how the Dust came to be in the wallet, if the user decides to get rid of it.

      Title: Dust UTXO Disposal Protocol
    

    bubb1es71 commented at 5:11 PM on April 29, 2026:

    I don't have a strong preference here either, just want to be clear about the focus of the proposal. But that is already done in the text of the doc. I'll change it back since it's shorter and reads a little better.

  35. murchandamus commented at 4:56 PM on April 29, 2026: member

    The Preamble updates and table entry look good. Thanks for the quick turn-around. Given that you said that you are still mulling over some of the review comments, I’ll leave the “PR Author action required” tag for the time being. Please let me know when you’re ready for another review.

  36. Revert title back to original e1c7071334
  37. Change output to always be OP_RETURN ash 686c1b0ed7
  38. bubb1es71 commented at 3:18 AM on May 1, 2026: contributor

    @murchandamus this one is ready for another look. In 686c1b0 I updated it to use only OP_RETURN "ash" and some other small edits.

  39. murchandamus removed the label PR Author action required on May 1, 2026
  40. murchandamus approved
  41. murchandamus commented at 6:19 PM on May 1, 2026: member

    Thanks, I looked only over the updates since my full review. Everything looks good to me, no further comments at this time.

  42. murchandamus merged this on May 6, 2026
  43. murchandamus closed this on May 6, 2026


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bips. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-05-19 06:50 UTC