<h3>Background</h3>
<p>Bitcoin script is a stack-based verification language. Because it's a verification language any operation available in the language can be used to either take inputs and produce an output for later use in the script, or require inputs to be provided for use in the script which produce a pre-determined output. As Andrew Poelstra says - operations can be run forward or backward.</p>
<p>Currently, bitcoin scripts have 3 ways to verify the transaction in which they are spent:</p>
<ul>
<li>Requiring a specific <code>nLockTime</code> field on the transaction  (<code>OP_CHECKLOCKTIMEVERIFY</code>)</li>
<li>Requiring a specific <code>nSequence</code> field on the input (OP_CHECKSEQUENCEVERIFY)</li>
<li>Requiring a signature over a hash of the transaction (<code>OP_CHECKSIG</code> and its variants)</li>
</ul>
<p>When people discuss &quot;adding covenants&quot; to bitcoin, they refer to adding <em>additional</em> ways to verify the spending transaction, most commonly restrictions on the outputs the transaction will make.</p>
<p>Bitcoin signature checking operations internally hash the transaction being verified. Because the hashing and signing are contained in a single operation, neither the signature hash nor the input data for that hash can be directly inspected by script.</p>
<p><a href="https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki" rel="nofollow noreferrer">BIP 340</a> signatures consist of <code>(R,s)</code> satisfying the function <code>s⋅G = R + hash(R || P || m)⋅P</code> where <code>m</code> is the signature hash, <code>P</code> is the signer's public key, and <code>G</code> is the secp256k1 generator point.</p>
<h3>Getting the signature hash on the stack</h3>
<p>As Andrew Poelstra <a href="https://medium.com/blockstream/cat-and-schnorr-tricks-i-faf1b59bd298" rel="nofollow noreferrer">describes</a> in detail, by setting <code>R</code> and <code>P</code> equal to <code>G</code>, we can force <code>s</code> to be equal to <code>hash(G || G || m) + 1</code>. Using CAT, we can deconstruct the 64-byte signature into its <code>R</code> and <code>s</code> values, and if we further require the spend stack to include the first 31 bytes of <code>hash(G || G || m)</code> (ground until the last byte would have been <code>0x00</code>), we can then further require the spend stack to provide <code>m</code>.</p>
<h3>Verifying transaction elements</h3>
<p><a href="https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki" rel="nofollow noreferrer">BIP 341</a> signature hashes are composed of internal hashes of many parts of the transaction being verified. Using CAT, a bitcoin spend script can require the spend stack to include the <em>unconstrained</em> inputs to the signature hashes and concatenate them with script-provided constrained portions to verify that the constrained portions match the actual transaction. This means that any datum included in the signature hash can be constrained individually using CAT.</p>
<p>Thus, by including (for example) a hash of transaction outputs in a locking script, an OP_CAT-based covenant script can require the caller to provide all other transaction data and the hashes described above and require that the spending transaction has the required outputs. An additional covenant in bitcoin script.</p>
<hr />
<p>Full working code using these techniques can be seen in @rot13maxi's <a href="https://github.com/taproot-wizards/purrfect_vault" rel="nofollow noreferrer">Purrfect Vaults</a></p>

CC BY-SA 4.0
2024-08-07T20:35:00.940Z
I did a deep dive on this topic with more naive eyes and [wrote up my understanding (with some ascii art!)](https://blog.yonson.dev/log/2024-02-vol3/). I'd be happy to write up a more condensed version here to complement your answer, or feel free to poach some or none of this.
yonson
CC BY-SA 4.0
2024-08-08T16:54:07.847Z
Thanks! Added some text that based on your write-up that I think was missing here.
Brandon - Rearden
CC BY-SA 4.0
2024-08-01T20:36:53.743Z
2024-08-08T16:53:49.627Z
2024-08-08T16:53:49.627Z
Brandon - Rearden
<p><a href="https://bitcoin.stackexchange.com/questions/123826/what-is-the-op-cat-proposal">OP_CAT</a> takes the top 2 stack items, concatenates them and pushes the result to the stack. How can this be used to add new restrictions how a UTXO can be spent? (Beyond the existing signature and time lock covenants)</p>

<taproot><smartcontracts><covenants><bip347-op-cat>
How can OP_CAT be used to implement additional covenants?
Brandon - Rearden
# How can OP_CAT be used to implement additional covenants?

(Asked by: username_0 on 2024-08-01)

[OP\_CAT](https://bitcoin.stackexchange.com/questions/123826/what-is-the-op-cat-proposal) takes the top 2 stack items, concatenates them and pushes the result to the stack. How can this be used to add new restrictions how a UTXO can be spent? (Beyond the existing signature and time lock covenants)

**Tags:** taproot, smartcontracts, covenants, bip347-op-cat


---

## 1 answers

### Answer by username_0 on 2024-08-01. Score: 3 | Accepted answer

### Background

Bitcoin script is a stack-based verification language. Because it's a verification language any operation available in the language can be used to either take inputs and produce an output for later use in the script, or require inputs to be provided for use in the script which produce a pre-determined output. As Andrew Poelstra says - operations can be run forward or backward.

Currently, bitcoin scripts have 3 ways to verify the transaction in which they are spent:

* Requiring a specific `nLockTime` field on the transaction (`OP_CHECKLOCKTIMEVERIFY`)
* Requiring a specific `nSequence` field on the input (OP\_CHECKSEQUENCEVERIFY)
* Requiring a signature over a hash of the transaction (`OP_CHECKSIG` and its variants)

When people discuss "adding covenants" to bitcoin, they refer to adding *additional* ways to verify the spending transaction, most commonly restrictions on the outputs the transaction will make.

Bitcoin signature checking operations internally hash the transaction being verified. Because the hashing and signing are contained in a single operation, neither the signature hash nor the input data for that hash can be directly inspected by script.

[BIP 340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) signatures consist of `(R,s)` satisfying the function `s⋅G = R + hash(R || P || m)⋅P` where `m` is the signature hash, `P` is the signer's public key, and `G` is the secp256k1 generator point.

### Getting the signature hash on the stack

As Andrew Poelstra [describes](https://medium.com/blockstream/cat-and-schnorr-tricks-i-faf1b59bd298) in detail, by setting `R` and `P` equal to `G`, we can force `s` to be equal to `hash(G || G || m) + 1`. Using CAT, we can deconstruct the 64-byte signature into its `R` and `s` values, and if we further require the spend stack to include the first 31 bytes of `hash(G || G || m)` (ground until the last byte would have been `0x00`), we can then further require the spend stack to provide `m`.

### Verifying transaction elements

[BIP 341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki) signature hashes are composed of internal hashes of many parts of the transaction being verified. Using CAT, a bitcoin spend script can require the spend stack to include the *unconstrained* inputs to the signature hashes and concatenate them with script-provided constrained portions to verify that the constrained portions match the actual transaction. This means that any datum included in the signature hash can be constrained individually using CAT.

Thus, by including (for example) a hash of transaction outputs in a locking script, an OP\_CAT-based covenant script can require the caller to provide all other transaction data and the hashes described above and require that the spending transaction has the required outputs. An additional covenant in bitcoin script.

---

Full working code using these techniques can be seen in @rot13maxi's [Purrfect Vaults](https://github.com/taproot-wizards/purrfect_vault)

> **Comments:**
> **username_1**: I did a deep dive on this topic with more naive eyes and [wrote up my understanding (with some ascii art!)](https://blog.username_1.dev/log/2024-02-vol3/). I'd be happy to write up a more condensed version here to complement your answer, or feel free to poach some or none of this.  
> **username_0**: Thanks! Added some text that based on your write-up that I think was missing here.  

---

