Subject: [bitcoin-dev] OP_AMOUNT Discussion

From: Jeremy Rubin <[email-masked]>
Date: Tue, 8 Mar 2022 09:09:58 -0800

Hi Devs,

Recently, I've been getting a lot of questions about OP_AMOUNT. It's also
come up in the context of "CTV is unsafe because it can't handle differing
amounts". Just sharing some preliminary thinking on it:

It could come in many variants:

OP_PUSHAMOUNT
OP_AMOUNTVERIFY
OP_PUSHAMOUNTSPLIT
OP_SPLITAMOUNTVERIFY

If we want to do a NOP upgrade, we may prefer the *VERIFY formats. If we
want to do a SUCCESSX upgrade, we could do the PUSH format.

The SplitAmount format is required because amounts are > 5 bytes (51 bits
needed max), unless we also do some sort of OP_UPGRADEMATH semantic whereby
presence of an Amount opcode enables 64 bit (or 256 bit?) math opcodes.

And could be applied to the cross product of:

The Transaction
An Input
An Output
The fees total
The fees this input - this output
This Input
"This" Output

A lot of choices! The simplest version of it just being just this input,
and no other (all that is required for many useful cases, e.g. single sig
if less than 1 btc).

A while back I designed some logic for a split amount verifying opcode
here: (I don't love it, so hadn't shared it widely).
https://gist.github.com/JeremyRubin/d9f146475f53673cd03c26ab46492504

There are some decent use cases for amount checking.

For instance, one could create a non-recursive covenant that there must be
an output which exactly matches the sats in the input at the same index.
This could be used for colored coins, statechains, TLUV/EVICT based payment
pools, etc.

Another use case could be to make a static address / descriptor that
disables low security spends if more coins are the input.

Yet another could be to enable pay-what-you-want options, where depending
on how much gets paid into an address different behaviors are permitted.

Lastly, as noted in BIP-119, you can make a belt-and-suspenders value check
in CTV contracts to enable a backup withdrawal should you send the wrong
amount to a vault.

Overall, I think the most straightforward path would be to work on this
only for tapscript, no legacy, and then spec out upgraded math operations,
and then OP_PUSHAMOUNT is pretty straightforward & low technical risk.
Unfortunately, the upgraded math and exact semantics are highly
bikesheddable... If anyone is interested in working on this, I'd be happy
to review/advise on it. Otherwise, I would likely start working on this
sometime after I'm spending less effort on CTV.

Blockstream liquid has some work in this regard that may be copyable for
the math part, but likely not the amount opcode:
https://github.com/ElementsProject/elements/blob/master/doc/tapscript_opcodes.md
 However, they chose to do only 64 bit arithmetic and I personally think
that the community might prefer wider operations, the difficulty being in
not incidentally enabling OP_CAT as a size, bitshift, and add fragment (or
proving that OP_CAT is OK?).

see also: https://rubin.io/bitcoin/2021/12/05/advent-8/#OP_AMOUNT

Cheers,

Jeremy

--
@JeremyRubin <https://twitter.com/JeremyRubin>