-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Changes from 21 commits
83ca57f
f1169dd
26e8e5f
0335c9d
3d31e5c
bb725e6
9779dc9
c5d66d6
848352f
a2b0100
6a790ec
01db3ac
945e2a3
7180c1c
6f5a74d
d4f85b1
beb5802
0a143d3
8219830
0b8a7e4
77509f6
4f39e4b
97635f5
e3dc3ba
e492a90
785b11e
e91621e
82fe9fc
ae68ef1
f9e100e
799dc0c
2cec73a
5dde7ea
2b5ab3b
b349374
35641a8
ac231a1
c235aa4
f8ad6ed
6c729c4
0a3869d
7ed8f6f
852502b
c10870a
5413e18
dbc612e
a05543c
1d55304
3d78cc0
696cc17
d670035
e9e7636
6815c39
6ea9fda
31f5192
f05e162
cda34ee
7ad0f82
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<pre> | ||
BIP: ??? | ||
Layer: Consensus (soft fork) | ||
Title: OP_CAT | ||
Author: Ethan Heilman <[email protected]> | ||
Armin Sabouri <[email protected]> | ||
Status: Draft | ||
Type: Standards Track | ||
Created: 2023-10-21 | ||
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-op-cat | ||
License: BSD-3-Clause | ||
</pre> | ||
|
||
==Abstract== | ||
|
||
This BIP reintroduces OP_CAT in the form of a new tapscript opcode which allows the concatenation of two values on the stack. This opcode would be activated via a soft fork by redefining the opcode OP_SUCCESS126. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, updated bip |
||
|
||
When evaluated the OP_CAT instruction: | ||
# Pops the top two values off the stack, | ||
# concatenates the popped values together, | ||
# and then pushes the concatenated value on the top of the stack. | ||
|
||
OP_CAT fails if there are less 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. | ||
|
||
==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 expands 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> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lamport signatures in tapscript aren't actually quantum secure because the taptweak still relies on EC operations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As far as I know it is an open question if the taptweak based commitment is quantum secure or not. This BIP could not take a position on this question. I will reword this to fix any confusion. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, I spoke too soon. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm glad you brought this up. I wouldn't want the BIP to be seen as making an authoritative statement on this question. Let me know if you think my change addresses the issue or not.
EthanHeilman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* 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 sufficent 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. | ||
|
||
==Specification== | ||
|
||
OP_CAT pops two elements off the stack, concatenates them together in stack order and pushes the resulting element onto 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. | ||
EthanHeilman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
===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_INVALID_STACK_OPERATION); | ||
} | ||
vch1.insert(vch1.end(), vch2.begin(), vch2.end()); | ||
stack.pop_back(); | ||
} | ||
break; | ||
</pre> | ||
This implementation is inspired by the original implementation of OP_CAT as shown below. 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>. | ||
|
||
The value of <code>MAX_SCRIPT_ELEMENT_SIZE</code> is 520. | ||
|
||
==Notes== | ||
|
||
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-27496895958ca30c47bbb873299a2ad7a7ea1003a9faa96b317250e3b7aa1fefL381</ref> which disabled it: | ||
EthanHeilman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
<pre> | ||
// (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; | ||
} | ||
</pre> | ||
|
||
==References== | ||
|
||
<references/> | ||
|
||
==Acknowledgements== | ||
|
||
We wish to acknowledge Dan Gould for encouraging and helping review this effort. | ||
|
||
== Copyright == | ||
This document is licensed under the 3-clause BSD license. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed