Getting your Trinity Audio player ready...
|
This post was first published on Medium.
The OP_CAT opcode has potential to enhance the flexibility and functionality of Bitcoin, if reactivated. It allows developers to create impressive new features such as covenants. In particular, we demonstrate a trustless sale of an Ordinal NFT using a layer-1 covenant made possible by re-enabling OP_CAT, without intermediaries.
OP_CAT
OP_CAT stands for “concatenate” in Bitcoin’s scripting language. It was originally included in the scripting language but was disabled due to concerns over potential vulnerabilities. OP_CAT allows concatenation of two strings on the stack.
It has been reactivated on Bitcoin Cash and SV since 2018 and has been used extensively to significantly enhance scripting capabilities while maintaining security. A few prominent use cases are:
On BTC, the reintroduction of OP_CAT has garnered interest lately. It has been assigned the Bitcoin Improvement Proposal (BIP) number 347, marking the first step towards potentially implementing this long-discussed software upgrade. It has been activated on signet, where our implementation is on.
Covenants
In the context of Bitcoin, a covenant refers to a mechanism that can impose constraints on how future transactions involving a specific set of coins can be spent. Covenants are essentially restrictions or rules embedded within Bitcoin transactions, designed to control the conditions under which the coins can be transferred or spent. For example, they can restrict the addresses to which the coins can be sent, or require certain scripts to be included in future transactions.
One straightforward way to add covenants is to introduce new opcode such as OP_CHECKTEMPLATEVERIFY (CTV) in BIP 119. Alternatively, it turns out covenants can be implemented by using a trick if OP_CAT were reactivated.
We first wrote about the introspection trick in 2020 using ECDSA signatures, which we called OP_PUSH_TX and its optimal variant.
Later on, it was written by Andrew Poelstra in 2021 and extended to Schnorr signatures.
Covenants Using Schnorr Signatures
BTC’s Taproot upgrade introduced Schnorr signatures (see BIP-340). The signature scheme uses the same underlying elliptic curve as in ECDSA.
Suppose we want to sign using the key pair (x, P = xG). We generate an ephemeral key pair (k, R = kG). The signature is defined as the tuple (R, s), where
s = k + xe
e is a hash of three things concatenated: our public key P’s x-coordinate, the x-coordinate of ephemeral R, and our transaction data/preimage.
e = H(Rx || Px || transaction)
If we choose k = 1 and x = 1, we can simplify the equation:
s = 1 + e
By constructing such a signature within script and passing it to an OP_CHECKSIG, we can constrain chunks of the transaction data. In short, we get a working covenant with OP_CAT, which allows calculating the equation in script. You can read more about this trick in the aforementioned articles.
Ordinal Locks
A seller transfers her ordinal NFT into a covenant smart contract (called an ordinal lock) in a taproot output that can only be redeemed if the spending transaction pays the seller the asking price. Traditional Ordinals marketplaces based on Partially Signed Bitcoin Transactions (PSBTs) generally do not share these PSBT listings with each other. Ordinal lock can potentially create a global shared on-chain order book with more liquidity and transparency, which is public for everyone to access.
Implementation
The signature equation above requires us to add 1 to a 256-bit integer. BTC currently only allows arithmetic in integers of 32 bits long, so we need to find a workaround.
Because e is derived from our transaction data, we can malleate the transaction until it hashed to a value of e that ends with 0x01 (or any value less than 0xFF) as we did in optimal PUSHTX. This takes 256 tries on average, which is instantaneous on modern hardware. For this example, we iterate on the value of nLockTime in the transaction, starting from 0, which won’t have an effect on the transaction’s validity/finality.
Once we have a value ending with 0x01, we can simply cut off the last byte and append 0x02 to it within the script to arrive at the correct value for s.
Let us implement a simple script:
If the script execution succeeds, it leaves us with a verified e’ on the stack.
Let’s extend the script to also get the sighash along with its transaction preimage via input and make it validate the correct value of e:
Doing this we quickly run into another of BTC’s limitations, where each witness input element can be a maximum of 80 bytes. Because the preimage is larger than that, we have to split it up in advance and re-assemble it in the script using OP_CAT.
Finally, let’s also constrain the transaction preimage’s second output and their sighash type.
In the above script, we label the constrained output the payment output. This means that the transaction MUST contain this output exactly as specified by the script in order to be valid. For the seller, this means the blockchain guarantees them a payout of the listing price if there’s a buyer willing to purchase the ordinal.
Additionally, we constrain the SigHash type to SIGHASH_ALL, to avoid preimage spoofing.
A single run results in the following transactions:
- Listing Transaction ID:
Bitcoin Signet Transaction: fc052b4ff87762bebad075ab8d50a51a73440dbd6e9eef592cb1582265ace5b7 - Purchase Transaction ID:
Bitcoin Signet Transaction: 9df613654191537fc239b6ec8b933edf712eac68930fb988b648112d225eb5c9
![OP_CAT-enabled covenants on Bitcoin](https://coingeek.com/wp-content/uploads/2024/05/Lots-of-OP_CATs.png)
Full code is at https://github.com/sCrypt-Inc/btc-ordinal-listing.
In addition to the covenant mechanism, the Pay-to-Taproot (P2TR) output can also commit to an alternative leaf script that simply checks for the seller’s signature, plus a time lock. This allows the seller to cancel/withdraw the listing.
Watch: sCrypt makes smart contracts possible on the BSV blockchain
New to blockchain? Check out CoinGeek’s Blockchain for Beginners section, the ultimate resource guide to learn more about blockchain technology.