Ephemeral Dust (tx fees and policy)

https://github.com/bitcoin/bitcoin/pull/30239

Host: tdb3  -  PR author: instagibbs

Notes

  • Bitcoin Core considers a transaction output to be dust when its value is lower than the cost of creating and spending it.

  • Ephemeral dust is a new concept that allows a single dust output in a transaction, provided the transaction is zero fee. In order to spend any unconfirmed outputs from this transaction, the spender must also spend this dust in addition to any other outputs.

  • Ephemeral dust enables additional options for creating and using dust outputs. This can be useful with types of presigned transactions, chains of transactions, keyed and keyless anchors: allowing zero usage of input funds while still enabling CPFP.

  • Recommended reading:

Questions

  1. Did you review the PR? Concept ACK, approach ACK, tested ACK, or NACK? What was your review approach?

  2. Where in code is it determined if an amount is dust?

  3. Is dust restricted by consensus? Policy? Both?

  4. How can dust be problematic?

  5. Why is the term ephemeral significant? What are the proposed rules specific to ephemeral dust?

  6. Why is it important to impose a fee restriction? Which specific vulnerabilities can you imagine without the fee restriction? Can you think of (in your view) positive use cases that are not possible because of the fee restriction?

  7. How are 1P1C relay and TRUC transactions relevant to ephemeral dust?

  8. What could happen if restrictions on the the child transaction were not in place?

  9. Can a node operator change the amounts considered to be dust? If so, how? How are ephemeral dust rules enforced in this case? What would happen if the node tries to broadcast a transaction after adjusting dust amounts?

  10. Could a miner choose to mine transactions containing dust? Is this a concern? What could be done to address the concerns, if any?

  11. Which types of tests were created for the PR? What is the purpose of each type of test? Did you run the tests locally? If so, which ones? Which tests did you not run, and why?

  12. Do the tests introduced exercise all of the code changes? How might you find out? Can you think of test scenarios and types of tests that could enhance testing?

Bonus questions

  1. Why would a modified fee be relevant to ephemeral dust?

Meeting Log

  117:00 <stickies-v> #startmeeting
  217:00 <tdb3> Welcome everyone to this month's PR review club
  317:00 <hodlinator> hi
  417:00 <stickies-v> hi!
  517:00 <tdb3> The PR is #30239 (Ephemeral Dust)
  617:01 <instagibbs> hi
  717:01 <chinggg> Hi
  817:01 <tdb3> Let's get started
  917:01 <tdb3> Did you review the PR? Concept ACK, approach ACK, tested ACK, or NACK? What was your review approach?
 1017:01 <stickies-v> do we have any first timers in today's review club? feel free to say hi, even if you're just lurking!
 1117:02 <stickies-v> (the notes and questions are available on https://bitcoincore.reviews/30239)
 1217:02 <chinggg> I am a first timer
 1317:02 <itamar53> HI :-)
 1417:02 <tdb3> welcome
 1517:02 <stickies-v> oh hi chinggg, glad you found your way here! i hope you'll find it useful!
 1617:03 <tdb3> Did folks have a chance to take a look at the PR?
 1717:03 <stickies-v> i'm still going through the code but it looks like a pretty strong concept ack from me! my review approach is going through the code commit-by-commit
 1817:04 <tdb3> Same here. The author instagibbs did a great job of making each commit digestible
 1917:05 <tdb3> Let's dive into some specifics
 2017:05 <tdb3> Where in code is it determined if an amount is dust?
 2117:06 <chinggg> IsDust function?
 2217:07 <stickies-v> that's my understanding too, although there's a bit of a call hierarchy so it depends on how you look at it?
 2317:07 <hodlinator> ..which is called from IsStandardTx() in policy.cpp, right?
 2417:07 <tdb3> chinggg: great, yes, IsDust() is called, which in turn calls GetDustThreshold()
 2517:07 <tdb3> hodlinator: right!
 2617:07 <tdb3> https://github.com/bitcoin/bitcoin/blob/2a52718d734cf65aaeeb18f627547e5bca3483f4/src/policy/policy.cpp#L26
 2717:08 <tdb3> Is dust restricted by consensus? Policy? Both?
 2817:09 <hodlinator> since GetDustThreshold() is implemented in policy.cpp I would expect consensus to not depend on it.
 2917:10 <hodlinator> (so it would not be restricted by consensus).
 3017:10 <chinggg> The commit message for GetDustThreshold() was from `Consensus: Minimal way to move dust out of consensus`
 3117:11 <instagibbs> chinggg woah, TIL
 3217:11 <chinggg> I mean the comment for the function was from commit `Consensus: Minimal way to move dust out of consensus`, so the function is probably not restricted by consensus anymore
 3317:12 <instagibbs> ah, it's just moving the defintion
 3417:12 <instagibbs> 330bb5a456a5f9c26703fa742e4c80691e1455ab
 3517:13 <tdb3> So then as a follow up to all, could a miner mine a transaction with dust if they chose to?
 3617:14 <hodlinator> ("move dust out of Consensus" in 330bb5a456a5f9c26703fa742e4c80691e1455ab might be referring to the deprecated libconsensus rather than an actual change to the bitcoin protocol?)
 3717:15 <stickies-v> yeah they could, both before and after this PR
 3817:15 <tdb3> stickies-v: right
 3917:15 <hodlinator> stickies-v +1
 4017:15 <tdb3> How can dust be problematic? Why do we care if a miner mines dust?
 4117:18 <tdb3> Any thoughts?
 4217:18 <stickies-v> it's more an implementation optimization concern than a protocol risk - dust transactions are unlikely to be ever spent, so they may end up bloating the UTXO set forever
 4317:18 <hodlinator> since dust costs more to spend than the amount it provides by definition, the risk is that the UTXO set will grow for all nodes (pruned and non-pruned, blocks-only and regular).
 4417:19 <stickies-v> a larger UTXO set can affect transaction validation speed / resource requirements
 4517:20 <tdb3> stickies-v, hodlinator: that's right. dust transactions can bloat the UTXO set and avoiding performance/resource issues is desirable
 4617:20 <tdb3> Why is the term ephemeral significant? What are the proposed rules specific to ephemeral dust?
 4717:20 <instagibbs> tiny utxos may have incentives to sweep them outside of the satoshi value themselves, but putting sats in outputs is another incentive to eventually spend it
 4817:21 <chinggg> I am not so familiar with the miner's economics. I guess dust could be problematic because the transaction output will not be usable anymore in the future, leading to fragments.
 4917:22 <tdb3> chinggg: it's great that you brought up the concept of miner's economics/incentives
 5017:22 <tdb3> Why is the term ephemeral significant? What are the proposed rules specific to ephemeral dust?
 5117:24 <hodlinator> The PR proposes to allow for relaying dust, but forces the fee of the tx to 0, meaning it is unlikely to make it into a block without a child, which now *has to* spend the dust (else it won't be relayed).
 5217:25 <tdb3> hodlinator: great description!
 5317:25 <hodlinator> So the dust is supposed to be short-lived, ephemeral.
 5417:25 <stickies-v> i think it's significant because it indicates that the dust output is not meant to last, i.e. it gets cleaned up "by definition" (even if it's not guaranteed)
 5517:25 <tdb3> stickies-v: right! lines up nicely with the meaning of ephemeral
 5617:26 <tdb3> Why is it important to impose a fee restriction? (0-fee on dusty tx)
 5717:27 <stickies-v> I think hodlinator already covered that in his previous response about making it less attractive for a minor to include the dusty tx into a block without a spending child?
 5817:27 <tdb3> That's right. Effectively "has to" be spent
 5917:27 <tdb3> How are 1P1C relay and TRUC transactions relevant to ephemeral dust?
 6017:29 <hodlinator> beats me :)
 6117:29 <tdb3> Let's think through 1P1C relay
 6217:29 <instagibbs> the PR was originally written with TRUC in mind, which might be a hint
 6317:31 <tdb3> Food for thought: If transaction containing dust is 0-fee, then would it meet the minimum relay fee?
 6417:32 <hodlinator> instagibbs: Yes, but do the latest pushes still rely on it?
 6517:32 <instagibbs> hodlinator nope, no particular reason it has to
 6617:32 <stickies-v> an ephemeral dust tx (pretty much) requires a fee-bumping child, but without 1P1C we wouldn't really have a mechanism of relaying this
 6717:32 <hodlinator> Feels like package relay is more of a requirement to bypass the min relay fee.
 6817:33 <tdb3> stickies-v: thank you. yes!
 6917:34 <stickies-v> and TRUC aligns very nicely as well, given that it restricts a v3 transaction having just one unconfirmed parent tx
 7017:34 <stickies-v> *ancestor, not parent
 7117:35 <tdb3> that's my understanding as well
 7217:35 <instagibbs> one last thing: TRUC currently is the only way to allow <minrelay transactions, including 0-fee
 7317:35 <instagibbs> (with default settings)
 7417:35 <hodlinator> okay, so pinning is prevented and sibling eviction is supported.
 7517:36 <hodlinator> if parent is v3
 7617:38 <tdb3> The ephemeral dust rules force the child to spend the parent's dust. Why enforce this?
 7717:38 <tdb3> What could happen if this restriction wasn't in place?
 7817:41 <stickies-v> i think it's mostly a dos issue?
 7917:42 <tdb3> If the child wasn't forced to spend the dust of the parent, then the dust would make its way into the UTXO set, right?
 8017:42 <instagibbs> You could imagine a first child spending dust(yay), then a 2nd child, higher fee, not spending dust. Parent and second child get mined first, then first child evicted
 8117:42 <instagibbs> (boo!)
 8217:43 <tdb3> thanks instagibbs
 8317:43 <stickies-v> wait isn't that talking about two different things?
 8417:44 <stickies-v> as in: what instagibbs said is about why we don't allow a dusty tx to have > 1 child transactions
 8517:44 <stickies-v> whereas tdb3's question is about requiring any child to spend the dust output?
 8617:44 <instagibbs> I'll let people discuss :)
 8717:45 <tdb3> yeah, I think you're right, we sort of talked about two different things, but they seem fairly related in the sense that we want to avoid non-ephemeral dust as much as possible.
 8817:46 <instagibbs> You could imagine the rule being: "Make sure the dust is spent by *a* child", but is that sufficient, in other words?
 8917:47 <stickies-v> oh yes, i agree we can't enforce making the sure the dust output is spent without also enforcing there's only 1 child
 9017:47 <hodlinator> Should probably be the highest paying child in that case... to encourage it to be within the same block as the parent. Code gets complicated/slower by allowing multiple children..?
 9117:48 <stickies-v> i just thought the question was about why force the dust to be spent in the first place, which is why i mentioned dos - because otherwise we'd be relaying 0-fee transactions without limit, i think?
 9217:50 <stickies-v> (and of course the utxo bloat, but i suppose technically that doesn't *need* to be addressed at the relay level)
 9317:50 <instagibbs> hodlinator yeah you're thinking along the right lines, I think it just becomes really complicated quickly
 9417:50 <tdb3> great points
 9517:50 <tdb3> When reviewing the PR, all great things to reason through!
 9617:51 <tdb3> Looks like we have a few minutes left
 9717:51 <tdb3> Can a node operator change the amounts considered to be dust? If so, how?
 9817:53 <hodlinator> By running a pre-segwit node that doesn't see witness bytes?
 9917:54 <tdb3> Interesting. How so?
10017:54 <stickies-v> there's also the `-dustrelayfee` startup option
10117:55 <hodlinator> If the witness data makes the tx big enough that segwit nodes calculate the outputs as below the dust limit, but a non-segwit node only sees the transaction without the witness data bytes?
10217:55 <tdb3> stickies-v: yes, thanks
10317:56 <tdb3> hodlinator: that's pretty interesting!
10417:56 <tdb3> hadn't thought of that
10517:57 <instagibbs> can you elaborate? GetDustThreshold is a function over the output being made, and the dust relay rate
10617:57 <tdb3> If a node set -dustrelayfee such that all dust is allowed, are the ephemeral dust rules enforced?
10717:58 <stickies-v> instagibbs: +1, I don't think segwit is relevant here
10817:58 <tdb3> What would happen if the node tries to broadcast a transaction after adjusting the amounts it considers dust?
10918:01 <tdb3> any thoughts?
11018:01 <hodlinator> tdb3: Probably rejected by peers.
11118:02 <tdb3> hodlinator: yes, as I understand it, the other nodes receiving the tx would refuse to relay it
11218:02 <chinggg> +1
11318:03 <tdb3> and to touch on the first question, the first commit of the PR creates a great test that ensures that ephemeral dust rules don't conflict with adjusting dust limits
11418:04 <tdb3> I don't want to hold people up, but I'm happy to stay a bit longer
11518:04 <instagibbs> thanks tdb3
11618:04 <tdb3> As a last bit to discuss, there are some great tests introduced in this PR
11718:04 <stickies-v> let's wrap up the meeting here and folks who want to stay on / discuss more are of course welcome to do so!
11818:05 <tdb3> Which types of tests were created for the PR? What is the purpose of each type of test?
11918:05 <tdb3> stickies-v: sounds great, thanks
12018:05 <stickies-v> thanks a lot for hosting this meeting tdb3, that was such a helpful way to go through the PR. and of course thank you instagibbs for your work on this code, and to join today as well!
12118:05 <tdb3> thanks all, take care
12218:05 <hodlinator> thanks!
12318:05 <stickies-v> #endmeeting