Subject: [bitcoin-dev] A small tweak to TLUV to enable off-chain cancellation of payment pool transactions

From: Antoine Riard <[email-masked]>
Date: Sun, 15 May 2022 20:01:29 -0400

Hi,

Proposing a small tweak to TLUV to enable cancellation of an off-chain
transaction among a set of pool participants. Namely, to give the index of
the constrained output as an opcode item.

Using CoinPool terminology, the Withdraw phase happens by a participant
publishing an Update transaction and her own Withdraw transaction, freeing
her balance from the pool control. From then, any participant can
recursively and unilaterally publish a Withdraw transaction. Or the
consensus of the remaining participants can agree to stay in the pool by
cancelling the non-published Withdraw transactions with a Snapshot one
spending the pool output. This transaction implies a rotation of the
tapscripts, effectively cancelling the Withdraws.

The presence of this latest transaction is a bit artificial and could be
removed by cancelling the non-published Withdraw transactions. This
cancellation would be manifested by producing a group signature spending
any non-published Withdraw transaction `pool_output` and `balance_output`.

If the SIGHASH_ANYPREVOUTANYSCRIPT semantic is used, this re-lifting Update
transaction could be attached on any Withdraw transaction, even if the user
balances are not equal, as the amounts are not committed. To enable
rebinding on multiple cancelled Withdraw
transactions, I think SIGHASH_ANYONECANPAY could be used.

However, the group producing the signature to spend any cancelled output
should reflect the new set of pool participants after the withdrawals have
been played out. Any withdrawing user should have been removed, as there is
no interest anymore to
contribute to the signature. We would like to avoid a former participant
with nothing at stake in the pool to block the pool operations.

E,g let's say you have Alice, Bob, Caroll and Dave as pool participants.
Each of them owns a Withdraw transaction to exit their individual balances
at any time. Alice publishes her Withdraw transaction. Bob, Caroll and Dave
would like to cancel their non-published ones to pursue the pool
operations. To cancel the non-published transactions, only Bob, Caroll and
Dave should be part of the group of signers encumbering the non-published
Withdraw transactions outputs.

That said, the composition of this group of signers is a function of the
Withdraw transactions order, and as thus is unknown at pool state
generation. Therefore, it should be constrained leveraging some covenant
mechanism.

I believe this is achievable using TLUV semantics, at the condition to add
an output index to target the second output. Currently, a Withdraw
transaction `balance_output` is only the owner pubkey. The update internal
pubkey should also be inherited there to make the output cancellable. The
owner withdrawing capability could be moved as a timelock + a key inside a
tapscript.

A tapscript from a CoinPool Withdraw transaction currently looks like this
"0 A MERKLESUB P CHECKSIGVERIFY" [0]

The new tapscript would duplicate TLUV with an output index to constrain
the spending transactions both outputs, and therefore make them cancellable:

"<output_index=0> <control_integer> <path_step> <pubkey_tweak> TLUV
<output_index=1 <control_integer> <path_step> <pubkey_tweak> TLUV
<pubkey> CHECKSIGVERIFY"

I think it is a really slight modification of TLUV and it might serve other
use-cases, beyond the payment pool one ?

Thoughts ?

[0] While it could be argue to split TLUV in two smaller opcodes like
OP_MERKLESUB or a hypothesis OP_MERKLEADD to save few bytes when only the
subtraction or the addition feature is used, I'm not sure it's worthy the
complexity increased. In the context of payment pools, the usage of a TLUV
opcode should only happen in case of "pessimistic" non-cooperative
publication...