---
bip: 347
title: "OP_CAT in Tapscript"
status: Complete
type: Specification
layer: "Consensus (soft fork)"
authors: ["Ethan Heilman","Armin Sabouri"]
assigned: 2023-12-11
last_modified: 2026-04-23
requires: [340,341,342]
topics: ["consensus"]
license: "BSD-3-Clause"
url: https://bipexplorer.com/bip/347
source: https://github.com/bitcoin/bips/blob/master/bip-0347.mediawiki
---

# BIP 347: OP_CAT in Tapscript

> **In plain English:** Brings back OP_CAT, an instruction that joins two pieces of data together, which was disabled in Bitcoin's early days over security concerns. Re-enabled only inside Taproot scripts, this simple building block could make many advanced constructions possible, including spending restrictions (covenants) and more expressive smart contracts.

## Abstract

This BIP introduces OP\_CAT as a tapscript opcode which allows the concatenation of two values on the stack. OP\_CAT would be activated via a soft fork by redefining the opcode OP\_SUCCESS126 (126 in decimal and 0x7e in hexadecimal). This is the same opcode value used by the original OP\_CAT.

## Copyright

This document is licensed under the 3-clause BSD license.

## Specification

When evaluated, the OP\_CAT instruction:

1.  Pops the top two values off the stack,

1.  concatenates the popped values together in stack order,

1.  and then pushes the concatenated value on the top of the stack.

Given the stack _\[x1, x2\]_, where _x2_ is at the top of the stack, OP\_CAT will push _x1 || x2_ onto the stack. By _||_ we denote concatenation. OP\_CAT fails if there are fewer than two values on the stack or if a concatenated value would have a combined size greater than the maximum script element size of 520 bytes.

This opcode would be activated via a soft fork by redefining the tapscript opcode OP\_SUCCESS126 (126 in decimal and 0x7e in hexadecimal) to OP\_CAT.

## Motivation

Bitcoin Tapscript lacks a general purpose way of combining objects on the stack, restricting the expressiveness and power of Tapscript. This prevents, among many other things, the ability to construct and evaluate merkle trees and other hashed data structures in Tapscript. OP\_CAT, by adding a general purpose way to concatenate stack values, would overcome this limitation and greatly increase the functionality of Tapscript.

OP\_CAT aims to expand the toolbox of the tapscript developer with a simple, modular, and useful opcode in the spirit of Unix [1]. To demonstrate the usefulness of OP\_CAT below we provide a non-exhaustive list of some usecases that OP\_CAT would enable:

-   Bitstream, a protocol for the atomic swap (fair exchange) of bitcoins for decryption keys, that enables decentralized file hosting systems paid in Bitcoin. While such swaps are currently possible on Bitcoin without OP\_CAT, they require the use of complex and computationally expensive Verifiable Computation cryptographic techniques. OP\_CAT would remove this requirement on Verifiable Computation, making such protocols far more practical to build in Bitcoin. [2]

-   Tree signatures provide a multisignature script whose size can be logarithmic in the number of public keys and can encode spend conditions beyond n-of-m. For instance a transaction less than 1KB in size could support tree signatures with up to 4,294,967,296 public keys. This also enables generalized logical spend conditions. [3]

-   Post-Quantum Lamport signatures in Bitcoin transactions. Lamport signatures merely require the ability to hash and concatenate values on the stack. [4] It has been proposed that if ECDSA is broken or a powerful computer was on the horizon, there might be an effort to protect ownership of bitcoins by allowing people to mark their taproot outputs as "script-path only" and then move their coins into such outputs with a leaf in the script tree requiring a Lamport signature. It is an open question if a tapscript commitment would preserve the quantum resistance of Lamport signatures. Beyond this question, the use of Lamport Signatures in taproot outputs is unlikely to be quantum resistant even if the script spend-path is made quantum resistant. This is because taproot outputs can also be spent with a key. An attacker with a sufficiently powerful quantum computer could bypass the taproot script spend-path by finding the discrete log of the taproot output and thus spending the output using the key spend-path. The use of "Nothing Up My Sleeve" (NUMS) points as described in [BIP341](https://bipexplorer.com/bip/341) to disable the key spend-path does not disable the key spend-path against a quantum attacker as NUMS relies on the hardness of finding discrete logs. We are not aware of any mechanism which could disable the key spend-path in a taproot output without a softfork change to taproot.

-   Non-equivocation contracts [5] in tapscript provide a mechanism to punish equivocation/double spending in Bitcoin payment channels. OP\_CAT enables this by enforcing rules on the spending transaction's nonce. The capability is a useful building block for payment channels and other Bitcoin protocols.

-   Vaults [6] which are a specialized covenant that allows a user to block a malicious party who has compromised the user's secret key from stealing the funds in that output. As shown in [7] OP\_CAT is sufficient to build vaults in Bitcoin.

-   Replicating CheckSigFromStack [8] which would allow the creation of simple covenants and other advanced contracts without having to presign spending transactions, possibly reducing complexity and the amount of data that needs to be stored. Originally shown to work with Schnorr signatures, this result has been extended to ECDSA signatures [9].

-   OP\_CAT would allow tapscript to perform arbitrary computation on stack elements larger than 32-bits such as signatures and public keys. While Collider Script [10] showed that even without OP\_CAT tapscript can perform arbitrary computation on stack elements larger than 32-bits, this approach is extremely computationally expensive. In practice, today's tapscript can only perform arbitrary computation on 32-bit stack elements. OP\_CAT was not designed with this usecase in mind and OP\_CAT an inefficient way to perform this task.

-   BitVM[11] improvements. OP\_CAT would enable BitVM2 to eliminating the trusted setup from its proof system allow BitVM2 to reduce the size of transactions it uses.

OP\_CAT was available in early versions of Bitcoin. In 2010, a single commit disabled OP\_CAT, along with another 15 opcodes. Folklore states that OP\_CAT was removed in this commit because it enabled the construction of a script whose evaluation could have memory usage exponential in the size of the script. For example, a script that pushed a 1-byte value on the stack and then repeated the opcodes OP\_DUP, OP\_CAT 40 times would result in a stack element whose size was greater than 1 terabyte assuming no maximum stack element size. As Bitcoin at that time had a maximum stack element size of 5000 bytes, the effect of this expansion was limited to 5000 bytes. This is no longer an issue because tapscript enforces a maximum stack element size of 520 bytes.

## Rationale

Our decision to reenable OP\_CAT by redefining a tapscript OP\_SUCCESSx opcode to OP\_CAT was motivated to leverage the tapscript softfork opcode upgrade path introduced in [BIP342](https://bipexplorer.com/bip/342).

We specifically choose to use OP\_SUCCESS126 rather than another OP\_SUCCESSx as OP\_SUCCESS126 uses the same opcode value (126 in decimal and 0x7e in hexadecimal) that was used for OP\_CAT prior to it being disabled in Bitcoin. This removes a potential source of confusion that would exist if we had a opcode value different from the one used in the original OP\_CAT opcode.

While the OP\_SUCCESSx opcode upgrade path could enable us to increase the stack element size while reenabling OP\_CAT, we wanted to separate the decision to change the stack element size limit from the decision to reenable OP\_CAT. This BIP takes no position in favor or against increasing the stack element size limit.

## Backwards Compatibility

OP\_CAT usage in a non-tapscript script will continue to trigger the SCRIPT\_ERR\_DISABLED\_OPCODE. The only change would be to OP\_CAT usage in tapscript. This change to tapscript would be activated as a soft fork that redefines an OP\_SUCCESSx opcode (OP\_SUCCESS126) to OP\_CAT.

## Reference implementation

```
case OP_CAT:
{
  if (stack.size() < 2)
    return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
  valtype& vch1 = stacktop(-2);
  valtype& vch2 = stacktop(-1);
  if (vch1.size() + vch2.size() > MAX_SCRIPT_ELEMENT_SIZE)
    return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
  vch1.insert(vch1.end(), vch2.begin(), vch2.end());
  stack.pop_back();
}
break;
```

The value of `MAX_SCRIPT_ELEMENT_SIZE` is 520.

This implementation is inspired by the original implementation of [OP\_CAT as it existed in the Bitcoin codebase](https://github.com/bitcoin/bitcoin/blob/01cd2fdaf3ac6071304ceb80fb7436ac02b1059e/script.cpp#L381-L393) prior to the commit "misc changes" 4bd188c[12] which disabled it:

```
case OP_CAT:
{
    // (x1 x2 -- out)
    if (stack.size() < 2)
        return false;
    valtype& vch1 = stacktop(-2);
    valtype& vch2 = stacktop(-1);
    vch1.insert(vch1.end(), vch2.begin(), vch2.end());
    stack.pop_back();
    if (stacktop(-1).size() > 5000)
        return false;
}
break;
```

An alternative implementation of OP\_CAT can be found in Elements [13].

## Test Vectors

The following test vectors use Bitcoin-core JSON script-test format.

```
[
    [
        "78a11a1260c1101260",
        "78a11a1260",
        "c1101260",
        "#SCRIPT# CAT EQUAL",
        "#CONTROLBLOCK#",
        0.00000001
    ],
    "",
    "0x51 0x20 #TAPROOTOUTPUT#",
    "P2SH,WITNESS,TAPROOT,OP_CAT",
    "OK",
    "TAPSCRIPT CATs 78a11a1260 and c1101260 together and checks it is EQUAL to stack element 78a11a1260c1101260"
],
[
    [
        "51",
        "bbbb",
        "01",
        "#SCRIPT# IF CAT ELSE DROP ENDIF",
        "#CONTROLBLOCK#",
        0.00000001
    ],
    "",
    "0x51 0x20 #TAPROOTOUTPUT#",
    "P2SH,WITNESS,TAPROOT,OP_CAT",
    "OK",
    "TAPSCRIPT Tests CAT inside of an IF ELSE conditional (true IF)"
],
[
    [
        "",
        "09ca7009ca7009ca7009ca7009ca70",
        "#SCRIPT# CAT",
        "#CONTROLBLOCK#",
        0.00000001
    ],
    "",
    "0x51 0x20 #TAPROOTOUTPUT#",
    "P2SH,WITNESS,TAPROOT,OP_CAT",
    "OK",
    "TAPSCRIPT (['', 09ca7009ca7009ca7009ca7009ca70], CAT) Tests CAT succeeds when one of the two values to concatenate is of size zero"
],
```

A full test suite with additional vectors can be found at the Bitcoin [OP\_CAT PR](https://github.com/bitcoin/bitcoin/pull/29247).

## References

1.  R. Pike and B. Kernighan, "Program design in the UNIX environment", 1983, [https://harmful.cat-v.org/cat-v/unix\_prog\_design.pdf](https://harmful.cat-v.org/cat-v/unix_prog_design.pdf) 
2.  R. Linus, "BitStream: Decentralized File Hosting Incentivised via Bitcoin Payments", 2023, [https://robinlinus.com/bitstream.pdf](https://robinlinus.com/bitstream.pdf) 
3.  P. Wuille, "Multisig on steroids using tree signatures", 2015, [https://blog.blockstream.com/en-treesignatures/](https://blog.blockstream.com/en-treesignatures/) 
4.  J. Rubin, "\[bitcoin-dev\] OP\_CAT Makes Bitcoin Quantum Secure \[was CheckSigFromStack for Arithmetic Values\]", 2021, [https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-July/019233.html](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-July/019233.html) 
5.  T. Ruffing, A. Kate, D. Schröder, "Liar, Liar, Coins on Fire: Penalizing Equivocation by Loss of Bitcoins", 2015, [https://web.archive.org/web/20221023121048/https://publications.cispa.saarland/565/1/penalizing.pdf](https://web.archive.org/web/20221023121048/https://publications.cispa.saarland/565/1/penalizing.pdf) 
6.  M. Moser, I. Eyal, and E. G. Sirer, Bitcoin Covenants, [https://web.archive.org/web/20220203124718/https://fc16.ifca.ai/bitcoin/papers/MES16.pdf](https://web.archive.org/web/20220203124718/https://fc16.ifca.ai/bitcoin/papers/MES16.pdf) 
7.  A. Poelstra, "CAT and Schnorr Tricks II", 2021, [https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-ii.html](https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-ii.html) 
8.  A. Poelstra, "CAT and Schnorr Tricks I", 2021, [https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-i.html](https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-i.html) 
9.  R. Linus, "Covenants with CAT and ECDSA", 2023, [https://gist.github.com/RobinLinus/9a69f5552be94d13170ec79bf34d5e85#file-covenants\_cat\_ecdsa-md](https://gist.github.com/RobinLinus/9a69f5552be94d13170ec79bf34d5e85#file-covenants_cat_ecdsa-md) 
10.  E. Heilman, V. I. Kolobov, A. M. Levy, A. Poelstra, "ColliderScript: Covenants in Bitcoin via 160-bit hash collisions", 2024, [https://eprint.iacr.org/2024/1802](https://eprint.iacr.org/2024/1802) 
11.  R. Linus, L. Aumayr, A. Zamyatin, A. Pelosi, Z. Avarikioti, M. Maffei "BitVM2: Bridging Bitcoin to Second Layers", 2025, [https://bitvm.org/bitvm\_bridge.pdf](https://bitvm.org/bitvm_bridge.pdf) 
12.  S. Nakamoto, "misc changes", Aug 25 2010, [https://github.com/bitcoin/bitcoin/commit/4bd188c4383d6e614e18f79dc337fbabe8464c82#diff-27496895958ca30c47bbb873299a2ad7a7ea1003a9faa96b317250e3b7aa1fefR94](https://github.com/bitcoin/bitcoin/commit/4bd188c4383d6e614e18f79dc337fbabe8464c82#diff-27496895958ca30c47bbb873299a2ad7a7ea1003a9faa96b317250e3b7aa1fefR94) 
13.  Roose S., Elements Project, "Re-enable several disabled opcodes", 2019, [https://github.com/ElementsProject/elements/commit/13e1103abe3e328c5a4e2039b51a546f8be6c60a#diff-a0337ffd7259e8c7c9a7786d6dbd420c80abfa1afdb34ebae3261109d9ae3c19R740-R759](https://github.com/ElementsProject/elements/commit/13e1103abe3e328c5a4e2039b51a546f8be6c60a#diff-a0337ffd7259e8c7c9a7786d6dbd420c80abfa1afdb34ebae3261109d9ae3c19R740-R759) 

## Changelog

-   \_\_1.0.0\_\_ (2026-03-01) - Marked as complete.

-   \_\_0.3.1\_\_ (2026-01-23) - Made compliant with [BIP 3](https://bipexplorer.com/bip/3), use cases added.

-   \_\_0.3.0\_\_ (2024-05-06) - Merged to BIP repo

-   \_\_0.2.0\_\_ (2024-04-24) - Assigned BIP number

-   \_\_0.1.0\_\_ (2023-12-11) - Initial draft posted

May 6, 2024

## Acknowledgements

We wish to acknowledge Dan Gould for encouraging and helping review this effort. We also want to thank Madars Virza, Jeremy Rubin, Andrew Poelstra, Bob Summerwill, Tim Ruffing and Johan T. Halseth for their feedback, review and helpful comments.
