Skip to content

Instantly share code, notes, and snippets.

@moonsettler
Last active December 28, 2024 12:26
Show Gist options
  • Save moonsettler/d2369e043473c42ff7fa52878dd064a5 to your computer and use it in GitHub Desktop.
Save moonsettler/d2369e043473c42ff7fa52878dd064a5 to your computer and use it in GitHub Desktop.
CTV + OP_TEMPLATEHASH + OP_INPUTAMOUNTS

CTV++

Two additional opcodes to consider as an addition to OP_CHECKTEMPLATEVERIFY:

  • OP_TEMPLATEHASH
  • OP_INPUTAMOUNTS

Together they relax the strict limitations that OP_CHECKTEMPLATEVERIFY imposes, because it explicitly commits to the output amounts and therefore implicitly commits to the spendable input amounts in a lot of cases.

OP_TEMPLATEHASH

Builds the CTV template hash from the stack.

<inputIndex>
# FOR i = inputCount-1; i >= 0; i--; LOOP
  <sequence[i]>
# END LOOP
<inputCount>
<nLockTime>
# FOR j = outputCount-1; j >= 0; j--; LOOP
  <out[j].amount>
  <out[j].script>
# END LOOP
<outputCount>
<nVersion>
OP_TEMPLATEHASH
OP_CHECKTEMPLATEVERIFY

OP_INPUTAMOUNTS

Taproot only. Consumes a 32 bit signed integer n as parameter

  • n = 0 return the SUM of all input amounts with same script
  • n < 0 return the SUM of last abs(n) input amounts including current input
  • n > 0 return the SUM of first n input amounts of the transaction

fails if

  • n < 0 and abs(n) > inputIndex + 1
  • n > inputCount
<n>
OP_INPUTAMOUNTS

Example use:

This contract below allows the combining of UTXOs locked by the same script for something like a withdrawal from a Vault contract to a staging address where the relative time lock can begin. It works with any amount UTXOs unlike basic CTV Vaults. Also allows for paying fees endogenously and registering a change address. The fee paying input would sign with SIGHASH_ALL.

### Witness stack BEGIN ###

<inputIndex>
# FOR i = inputCount-1; i >= 0; i--; LOOP
  <sequence[i]>
# END LOOP
<inputCount>
<nLockTime>
<changeAmount>        # out[1].amount
<changeScriptPub>     # out[1].script

### Witness stack END ###

<0>                   # sum of all inputs with same script
OP_INPUTAMOUNTS       # out[0].amount
<stagingScriptPub>    # out[0].script 33 bytes for P2TR
<2>                   # outputCount
<2>                   # nVersion
OP_TEMPLATEHASH
OP_CHECKTEMPLATEVERIFY

Credits:

  • Jeremy Rubin who have already came up with everything many years ago
  • James O'Beirne for his awesome work on OP_VAULT
  • Salvatore Ingala for his work on CCV/MATT and to generalize state carrying covenants
  • Many others who have explored the covenant design space and CTV in particular
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment