Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIP 347: OP_CAT in Tapscript #1525

Merged
merged 58 commits into from May 6, 2024
Merged
Changes from 39 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
83ca57f
Create bip-???-cat.mediawiki
EthanHeilman Dec 11, 2023
f1169dd
Fixes typo
EthanHeilman Dec 12, 2023
26e8e5f
Better fits bitcoin style guide
EthanHeilman Dec 12, 2023
0335c9d
Grammar fix
EthanHeilman Dec 12, 2023
3d31e5c
Adds brackets
EthanHeilman Dec 12, 2023
bb725e6
Wording
EthanHeilman Dec 15, 2023
9779dc9
Keeps past tense consistant
EthanHeilman Dec 15, 2023
c5d66d6
Better phrasing
EthanHeilman Dec 15, 2023
848352f
Phrasing
EthanHeilman Dec 15, 2023
a2b0100
Typo
EthanHeilman Dec 15, 2023
6a790ec
Removes space in ref
EthanHeilman Dec 15, 2023
01db3ac
Removes space in ref
EthanHeilman Dec 15, 2023
945e2a3
Typos
EthanHeilman Dec 15, 2023
7180c1c
Prefer bytes to Bytes
EthanHeilman Dec 15, 2023
6f5a74d
Increases conciseness and clarity
EthanHeilman Dec 15, 2023
d4f85b1
Lowercase bytes
EthanHeilman Dec 15, 2023
beb5802
Adds subsection header
EthanHeilman Dec 15, 2023
0a143d3
Use BSD-3 license
EthanHeilman Dec 15, 2023
8219830
Code formatting
EthanHeilman Dec 15, 2023
0b8a7e4
Code formatting
EthanHeilman Dec 15, 2023
77509f6
Period to colon
EthanHeilman Dec 15, 2023
4f39e4b
Avoids designing or discussing how to add post-quantum commitments to…
EthanHeilman Dec 16, 2023
97635f5
Lowercase the signatures
EthanHeilman Dec 17, 2023
e3dc3ba
Italicize variables
EthanHeilman Dec 17, 2023
e492a90
Better reference for OP_CAT removal
EthanHeilman Dec 19, 2023
785b11e
Add backwards compatibility section
0xBEEFCAF3 Dec 29, 2023
e91621e
Merge pull request #1 from 0xBEEFCAF3/patch-1
EthanHeilman Dec 29, 2023
82fe9fc
specify the hex value of the opcode
EthanHeilman Dec 29, 2023
ae68ef1
add clarifying note about the current opcode
0xBEEFCAF3 Jan 7, 2024
f9e100e
Notes that the opcode used is the same as the original cat opcode
EthanHeilman Jan 7, 2024
799dc0c
Merge branch 'cat' into patch-1
0xBEEFCAF3 Jan 7, 2024
2cec73a
rm comment on disabled CAT opcode
0xBEEFCAF3 Jan 7, 2024
5dde7ea
revert changes to abstract
0xBEEFCAF3 Jan 7, 2024
2b5ab3b
Merge pull request #2 from 0xBEEFCAF3/patch-1
EthanHeilman Jan 7, 2024
b349374
update OP_CAT implementation
0xBEEFCAF3 Mar 20, 2024
35641a8
Merge pull request #3 from 0xBEEFCAF3/cat
EthanHeilman Mar 21, 2024
ac231a1
Fixes broken mediawiki link
EthanHeilman Mar 21, 2024
c235aa4
Adds more acknowledgements
EthanHeilman Mar 27, 2024
f8ad6ed
Changes OP_CAT BIP based on feedback given by Bob Summerwill
EthanHeilman Apr 12, 2024
6c729c4
Renamed to use BIP-0347
EthanHeilman Apr 25, 2024
0a3869d
Fixes comment URI
EthanHeilman Apr 25, 2024
7ed8f6f
Better quantum resistant section based Tim's comments
EthanHeilman Apr 25, 2024
852502b
Specifies exact tree signature limit (suggested by Ali Sherief)
EthanHeilman Apr 26, 2024
c10870a
Adds comma
EthanHeilman Apr 26, 2024
5413e18
Consistent formatting for Section Headings
EthanHeilman Apr 26, 2024
dbc612e
Consistent formatting for Section Headings
EthanHeilman Apr 26, 2024
a05543c
Changes title of BIP to "Enable OP_CAT in Tapscript"
EthanHeilman Apr 29, 2024
1d55304
OP_CAT in Tapscript
EthanHeilman Apr 29, 2024
3d78cc0
Fixes typos
EthanHeilman Apr 30, 2024
696cc17
Adds post history, fixes created date
EthanHeilman May 1, 2024
d670035
Adds sentence suggested by murchandamus to quantum paragraph
EthanHeilman May 1, 2024
e9e7636
Increases commas and capital letters
EthanHeilman May 1, 2024
6815c39
Adds commas
EthanHeilman May 1, 2024
6ea9fda
Fixes link to liar liar
EthanHeilman May 2, 2024
31f5192
Add BIP-347 OP_CAT to table
murchandamus May 3, 2024
f05e162
Merge branch 'master' into cat
murchandamus May 3, 2024
cda34ee
Improved accuracy of paragraph on OP_CAT's removal in 2010
EthanHeilman May 5, 2024
7ad0f82
Adds stable URL for Liar, Liar, Coins on Fire!
EthanHeilman May 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
105 changes: 105 additions & 0 deletions bip-???-cat.mediawiki
@@ -0,0 +1,105 @@
<pre>
BIP: ?
Layer: Consensus (soft fork)
Title: OP_CAT
Author: Ethan Heilman <ethan.r.heilman@gmail.com>
Armin Sabouri <arminsdev@gmail.com>
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-op-cat
Status: Draft
Type: Standards Track
Created: 2023-10-21
License: BSD-3-Clause
</pre>

==Abstract==

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a note that this is the same opcode used for OP_CAT originally.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

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:
# Pops the top two values off the stack,
# concatenates the popped values together in stack order,
# and then pushes the concatenated value on the top of the stack.

Given the stack ''<nowiki>[x1, x2]</nowiki>'', 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.
EthanHeilman marked this conversation as resolved.
Show resolved Hide resolved

OP_CAT aims to expand the toolbox of the tapscript developer with a simple, modular, and useful opcode in the spirit of Unix <ref>R. Pike and B. Kernighan, "Program design in the UNIX environment", 1983, https://harmful.cat-v.org/cat-v/unix_prog_design.pdf</ref>. 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. <ref>R. Linus, "BitStream: Decentralized File Hosting Incentivised via Bitcoin Payments", 2023, https://robinlinus.com/bitstream.pdf</ref>
* 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 a thousand public keys. This also enables generalized logical spend conditions. <ref> P. Wuille, "Multisig on steroids using tree signatures", 2015, https://blog.blockstream.com/en-treesignatures/</ref>
* Post-Quantum Lamport signatures in Bitcoin transactions. Lamport signatures merely require the ability to hash and concatenate values on the stack. <ref>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</ref> It is an open question if the quantum resistance of Lamport signatures can be preserved when used in a taproot output.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
* Post-Quantum Lamport signatures in Bitcoin transactions. Lamport signatures merely require the ability to hash and concatenate values on the stack. <ref>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</ref> It is an open question if the quantum resistance of Lamport signatures can be preserved when used in a taproot output.
* Post-quantum Lamport signatures in Bitcoin transactions. Lamport signatures merely require the ability to hash and concatenate values on the stack. <ref>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</ref> It is an open question if the quantum resistance of Lamport signatures can be preserved when used in a taproot output.

It is an open question if the quantum resistance of Lamport signatures can be preserved when used in a taproot output.

I'm not sure if this adds even more confusion. In the most direct sense, taproot outputs are clearly not post-quantum secure because the attacker can perform a key-path spend. Maybe something like: "Putting aside the ability to perform key-path spends, which clearly makes taproot insecure against a quantum attacker, it is an open question if the quantum resistance of Lamport signatures can be preserved when used in a script committed to in a taproot output."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@real-or-random Thanks for taking a look at this.

There is some history behind the intentional ambiguity in our statement here. we've been doing research on the quantum security of tapscript. I agree the script spend commit is probably provably quantum resistant under some assumptions. I had hoped I could find a way to prevent key path spends by constructing the taproot output in such a way that it would break the key spend path, e.g. an output where the only key spend signatures result in an invalid curve point. I haven't fully thrown in the towel on that attempt but it is looking highly unlikely at this point.

Let me edit this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@real-or-random Edited the quantum resistance section. Let me know what you think about it now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, great, I think it's clearer now.

Micro nit in the new paragraph: s/Lamport Signatures/Lamport signatures

* Non-equivocation contracts <ref>T. Ruffing, A. Kate, D. Schröder, "Liar, Liar, Coins on Fire: Penalizing Equivocation by Loss of Bitcoins", 2015, https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.727.6262&rep=rep1&type=pdf</ref> 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 <ref>M. Moser, I. Eyal, and E. G. Sirer, Bitcoin Covenants, http://fc16.ifca.ai/bitcoin/papers/MES16.pdf</ref> 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 <ref>A. Poelstra, "CAT and Schnorr Tricks II", 2021, https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-ii.html</ref> OP_CAT is sufficient to build vaults in Bitcoin.
* Replicating CheckSigFromStack <ref>A. Poelstra, "CAT and Schnorr Tricks I", 2021, https://medium.com/blockstream/cat-and-schnorr-tricks-i-faf1b59bd298</ref> 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 <ref>R. Linus, "Covenants with CAT and ECDSA", 2023, https://gist.github.com/RobinLinus/9a69f5552be94d13170ec79bf34d5e85#file-covenants_cat_ecdsa-md</ref>.

The opcode OP_CAT was available in early versions of Bitcoin. However, OP_CAT was removed 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 value whose size was greater than 1 terabyte. 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 [[bip-0342.mediawiki|BIP342]].

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 an 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 a soft fork that redefines an OP_SUCCESSx opcode (OP_SUCCESS126) to OP_CAT.

==Reference implementation==

<pre>
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;
</pre>


The value of <code>MAX_SCRIPT_ELEMENT_SIZE</code> is 520.

This implementation is inspired by the original implementation of [https://github.com/bitcoin/bitcoin/blob/01cd2fdaf3ac6071304ceb80fb7436ac02b1059e/script.cpp#L381-L393 OP_CAT as it existed in the Bitcoin codebase] prior to the commit "misc changes" 4bd188c<ref>S. Nakamoto, "misc changes", Aug 25 2010, https://github.com/bitcoin/bitcoin/commit/4bd188c4383d6e614e18f79dc337fbabe8464c82#diff-27496895958ca30c47bbb873299a2ad7a7ea1003a9faa96b317250e3b7aa1fefR94</ref> which disabled it:

<pre>
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;
</pre>

An alternative implementation of OP_CAT can be found in Elements <ref>Roose S., Elements Project, "Re-enable several disabled opcodes", 2019, https://github.com/ElementsProject/elements/commit/13e1103abe3e328c5a4e2039b51a546f8be6c60a#diff-a0337ffd7259e8c7c9a7786d6dbd420c80abfa1afdb34ebae3261109d9ae3c19R740-R759</ref>.

==References==

<references/>

==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 for their feedback, review and helpful comments.