Subject: Re: [bitcoin-dev] Exploring: limiting transaction output amount as a function of total input value

From: ZmnSCPxj <[email-masked]>
Date: Tue, 31 Aug 2021 09:00:15 +0000

Good morning Zac,

> Perhaps you could help me understand what would be required to implement the *unmodified* proposal. That way, the community will be able to better assess the cost (in terms of effort and risk) and weigh it against the perceived benefits. Perhaps *then* we find that the cost could be significantly reduced without any significant reduction of the benefits, for instance by slightly compromising on the functionality such that no changes to consensus would be required for its implementation. (I am skeptical that this would be possible though). The cost reduction must be carefully weighed against the functional gaps it creates.

For one, such output need to be explicitly visible, to implement the "change outputs must also be rate-limited".
A tx spending a rate-limited output has to know that one of the outputs is also a rate-limited output.

This flagging needs to be done by either allocating a new SegWit version --- a resource that is not lightly allocated, there being only 30 versions left if my understanding is correct --- or blessing yet another anyone-can-spend `scriptPubKey` template, something we want to avoid which is why SegWit has versions (i.e. we want SegWit to be the last anyone-can-spend `scriptPubKey` template we bless for a **long** time).

Explicit flagging is bad as well for privacy, which is another mark against it.
Notice how Taproot improves privacy by making n-of-n indistinguishable from 1-of-1 (and with proper design or a setup ritual, k-of-n can be made indistinguishable from 1-of-1).
Notice as well that my first counterproposal is significantly more private than explicit flagging, and my second coutnerproposal is also more private if wallets change their anti-fee-sniping mitigation.
This privacy loss represented by explicit flagging will be resisted by some people, especially those that use a bunch of random letters as a pseudonym (because duh, privacy).

(Yes, people can just decide not to use the privacy-leaking explicitly-flagged outputs, but that reduces the anonymity set of people who *are* interested in privacy, so people who are interested in privacy will prefer that other people do not leak their privacy so they can hide among *those* people as well.)

You also probably need to keep some data with each output.
This can be done by explicitly storing that data in the output directly, rather than a commitment to that data --- again, the "change outputs must also be rate-limited" requirement needs to check those data.

The larger data stored with the output is undesirable, ideally we want each output to just be a commitment rather than contain any actual data, because often a 20-byte commitment is smaller than the data that needs to be stored.
For example, I imagine that your original proposal requires, for change outputs, to store:

* The actual rate limit.
* The time frame of the rate limit.
* The reduced rate limit, since we spent an amount within a specific time frame (i.e. residual limit) which is why this is a change output.
* How long that time frame lasts.
* A commitment to the keys that can spend this.

Basically, until the residual limit expires, we impose the residual limit, then after the expiry of the residual limit we go back to the original rate limit.

The commitment to the keys itself takes at least 20 bytes, and if you are planning a to support k-of-n then that takes at least 32 bytes.
If this was not explicitly tagged, then a 32 byte commitment to all the necessary data would have been enough, but you do need the explicit tagging for the "change outputs must be rate-limited too".

Note as well that the residual needs to be kept with the output.
Bitcoin Core does not store transactions in a lookup table, it stores individual *outputs*.
While the residual can be derived from the transaction, we do not have a transaction table.
Thus, we need to explicitly put it on the output itself, directly, since we only have a lookup table for the unspent outputs, not individual transactions.

(well there is `txindex` but that is an option for each node, not something consensus code can rely on)

So yes, that "change outputs must also be rate-limited" is the big sticking point, and a lot of the "gaps" you worry about occur when we drop this bit.
Drop this bit and you can implement it today without any consensus code change, and with privacy good enough to prevent people with random letters as pseudonym from trying to stop you.

Regards,
ZmnSCPxj