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

From: Zac Greenwood <[email-masked]>
Date: Tue, 31 Aug 2021 16:09:04 +0200

Hi ZmnSCPxj,

Thank you for your helpful response. We're on the same page concerning
privacy so I'll focus on that. I understand from your mail that privacy
would be reduced by this proposal because:

* It requires the introduction of a new type of transaction that is
different from a "standard" transaction (would that be P2TR in the
future?), reducing the anonymity set for everyone;
* The payment and change output will be identifiable because the change
output must be marked encumbered on-chain;
* The specifics of how the output is encumbered must be visible on-chain as
well reducing privacy even further.

I don't have the technical skills to judge whether these issues can somehow
be resolved. In functional terms, the output should be spendable in a way
that does not reveal that the output is encumbered, and produce a change
output that cannot be distinguished from a non-change output while still
being encumbered. Perhaps some clever MAST-fu could somehow help?

I imagine that the offered functionality does not justify the above
mentioned privacy reductions, so unless these can be addressed, without
functional modification this proposal sadly seems dead in the water.

Thanks again.

Zac

On Tue, Aug 31, 2021 at 11:00 AM ZmnSCPxj <[email-masked]> wrote:

> 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
>
>