0349 - Draft - Standards - Nov. 14, 2024 (1 year, 8 months ago)
14
2024
BIP: 349
Layer: Consensus (soft fork)
Title: OP_INTERNALKEY
Author: Brandon Black <[email protected]>
Jeremy Rubin <[email protected]>
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP 349
Status: Draft
Type: Standards Track
Created: 2024-11-14
License: BSD-3-Clause
This BIP describes a new tapscript opcode (
OP_INTERNALKEY
) which
pushes the
taproot internal key
to the stack.
When verifying taproot script path spends having leaf version
0xc0
(as
defined in
BIP 342
),
OP_INTERNALKEY
replaces
OP_SUCCESS203
(0xcb).
OP_INTERNALKEY
pushes the 32-byte x-only representation of the
taproot
internal key
(referred to as
p
), as defined in
BIP 341
, to the stack.
When building taproot outputs, especially those secured by an aggregate key
representing more than one signer, the parties may wish to collaborate on
signing with the
taproot internal key
, but only with additional script
restrictions. In this case,
OP_INTERNALKEY
saves 8 vBytes.
In cases where key path spending is not desired, the internal key may be set to a NUMS point whose bytes would otherwise be required in a tapscript. This could be used with any hash locked transaction, for example, to save 8 vBytes.
Note: The internal key must be the X coordinate of a point on the SECP256K1 curve, so any such hash must be checked and modified until it is such an X coordinate. This will typically take approximately 2 attempts.
Consider a program such
CTV <X> CSFS <S+1> CLTV
. Such fragments are useful for LN-Symmetry applications.
Such a program would be embedded within a Taproot script path, such as
TR(X, {CTV <X> CSFS <S+1> CLTV})
.
Were the internal key to be updated from
X
to
Y
, the resulting program would be:
TR(Y, {CTV <X> CSFS <S+1> CLTV})
.
The key in the leaf and the key-path would be mismatched. Were
OP_INTERNALKEY
to be used,
the leaf would automatically re-key.
E.g.,
TR(X, {CTV OP_INTERNALKEY CSFS <S+1> CLTV})
is equivalent to
TR(X, {CTV <X> CSFS <S+1> CLTV})
and
TR(Y, {CTV OP_INTERNALKEY CSFS <S+1> CLTV})
is equivalent to
TR(Y, {CTV <Y> CSFS <S+1> CLTV})
.
While this particular example is contrived, the general technique of using
OP_INTERNALKEY
as updatable across an entire script tree is a helpful covenant primitive when it is desirable to
invalidate signatures from prior states. For example, the theoretical
OP_TAPLEAFUPDATEVERIFY
opcode
modifies the internal key directly to remove or add a participant, and
OP_INTERNALKEY
would ensure
that the tweaked key is used from all script paths where desired.
A reference implementation is provided here:
https://github.com/bitcoin/bitcoin/pull/29269
By constraining the behavior of an OP_SUCCESS opcode, deployment of the BIP
can be done in a backwards compatible, soft-fork manner. If anyone were to
rely on the OP_SUCCESS behavior of
OP_SUCCESS203
,
OP_INTERNALKEY
would
invalidate their spend.
TBD
The concept for INTERNALKEY first arose in a discussion between Russell O'Connor and Jeremy Rubin in Bitcoin Wizards IRC, inspired by BIP 118's key punning technique for the internal key. It was later drafted into this BIP by Brandon Black.
This document is licensed under the 3-clause BSD license.