BIP 449: OP_TWEAKADD - x-only key tweak addition
2026-03-05
View on GitHub
  BIP: 449
  Layer: Consensus (soft fork)
  Title: OP_TWEAKADD - x-only key tweak addition
  Authors: Jeremy Rubin <jeremy@char.network>
  Status: Draft
  Type: Specification
  Assigned: 2026-03-05
  License: BSD-3-Clause

Abstract

This proposal defines a new tapscript opcode, OP_TWEAKADD, that takes an x-only public key and a 32-byte integer t on the stack and pushes the x-only public key corresponding to P + t*G, where P is the lifted point for the input x-coordinate and G is the secp256k1 generator. The operation mirrors the Taproot tweak used by BIP340 signers and enables simple, verifiable key modifications inside script without revealing private keys or relying on hash locks.

Motivation

Bitcoin already leverages x-only key tweaking when deriving Taproot output keys, but tapscript currently has no way to perform the same group operation inside script and continue using the derived key. Without such a primitive, protocols that depend on relations between keys must instead reveal preimages, commit to multiple full public keys, or perform additional signature checks at each step.

Making key tweaking available in script enables several concrete constructions. These include tweak-reveal scripts built from OP_TWEAKADD together with proposed opcodes such as BIP 348 OP_CHECKSIGFROMSTACK and BIP 349 OP_INTERNALKEY, proof-of-signing-order constructions in which one signature commits to another signer acting later, delegation schemes in which one participant adjusts another participant's signing key, and target-tweak or key-reveal contracts that prove knowledge of a discrete logarithm by matching one tweaked key against another.

In these constructions, the script commonly commits to the base key while the witness provides the scalar used to derive the spending key. OP_TWEAKADD therefore exposes only the elliptic-curve addition primitive and adopts an operand order that fits that pattern directly, while leaving hashing, Taproot-specific tweak construction, and higher-level protocol logic to script composition or future opcodes.

Specification

Applicability and opcode number

  • Context: Only valid in tapscript (witness version 1, leaf version 0xc0). In legacy or segwit v0 script, OP_TWEAKADD is disabled and causes script failure.
  • Opcode: OP_TWEAKADD (0xBE, or TBD, any unused OP_SUCCESSx, preferably one which might never be restored in the future).

Stack semantics


... [tweak32] [pubkey32] OP_TWEAKADD  -> ... [pubkey32_out]

Input:

  • pubkey32: 32-byte x-only public key (big-endian x coordinate).
  • tweak32: 32-byte big-endian unsigned integer encoding scalar t.

Output:

  • pubkey32_out: 32-byte x-only public key for Q = P + t*G.

Operation and failure conditions

Let n be the secp256k1 curve order.

  1. If tweak32 or pubkey32 are not 32 bytes, fail.
  2. Parse tweak32 as big-endian integer t. If t >= n, fail.
  3. Interpret pubkey32 as an x-coordinate and attempt the BIP340 even-Y lift:
    • If no curve point exists with that x, fail.
    • Otherwise, obtain P with even Y.
  4. Compute Q = P + t*G. If Q is the point at infinity, fail.
  5. Push x(Q) as a 32-byte big-endian value.

Note: t = 0 may fail if pubkey32 is not valid.

Script evaluation rules

  1. If less than 2 stack elements, fail.
  2. Pop pubkey32 and then tweak32.
  3. If either length is not 32, fail.
  4. Run tweak_add as above.
  5. Push the 32-byte x-only result.

Resource usage

  • Performs one fixed-base EC scalar multiplication (t*G) plus one EC point addition (P + t*G).
  • Costs should be aligned with OP_CHECKSIG operation, budget is decremented by 50.

Rationale

X-only encoding and failure conditions

Using the BIP340 even-Y lift keeps the opcode aligned with the x-only key model already used by Taproot. Rejecting invalid lifts and the point at infinity ensures that OP_TWEAKADD never produces a value that cannot be interpreted as a usable x-only public key.

The opcode also rejects scalars greater than or equal to the curve order instead of reducing them modulo the curve order. Modular reduction would permit distinct 32-byte inputs to encode the same effective tweak, introducing an unnecessary source of malleability. In constructions where the tweak is derived from witness data, for example <data> OP_SHA256 <P> OP_TWEAKADD, this would allow different witness elements to produce the same derived key while changing transaction weight and fee characteristics. More generally, protocols should not be able to infer equality of tweak encodings from equality of derived keys when two distinct tweak values could be congruent modulo the curve order. Rejecting non-canonical scalars avoids these ambiguities. Applications that derive scalars from 32-byte hashes already need to handle the negligible-probability case in which the resulting value is not a valid secp256k1 scalar.

Push semantics

OP_TWEAKADD pushes a derived key instead of directly verifying a signature. This keeps the opcode narrowly scoped and reusable. The derived key can feed into existing or proposed signature opcodes, equality checks, or other script logic, rather than forcing all uses through a single verification flow.

Raw tweak input

The opcode accepts a raw 32-byte scalar instead of internally hashing the input or computing a Taproot-specific tweak. This keeps the consensus rule minimal. Constructions that require a hashed tweak can apply OP_SHA256 before OP_TWEAKADD. Constructions that require a BIP341 tweak to be computed entirely on-chain would require additional general-purpose opcodes that expose tapleaf hashes or taptree commitments to script.

Argument order

The chosen stack order puts the public key on top of the stack when OP_TWEAKADD executes. In the common pattern described above, the script pushes a fixed key and the witness supplies the scalar. This permits tweak-reveal, delegation, and proof-of-signing-order constructions to invoke OP_TWEAKADD without first inserting an OP_SWAP.

Compatibility

This is a soft-fork change which is tapscript-only. Un-upgraded nodes will continue to treat unknown tapscript opcode as OP_SUCCESSx.

A future upgrade, such as OP_CAT or an opcode that exposes tapleaf hashes or taptree commitments to script, could prepare the 32-byte scalar required to derive BIP341-compatible Taproot output keys entirely on-chain.

Deployment

TBD

Security considerations

  • Scalar range check prevents overflow, ambiguity, and alternate encodings of the same effective tweak.
  • Infinity guard ensures valid outputs only.
  • Scripts must control t derivation securely, which in many applications is trivial.
  • No new witness malleability is introduced by alternate tweak encodings because tweaks must be exactly 32 bytes, must encode scalars less than the curve order, and x-only keys admit a unique even-Y lift.

Reference semantics (pseudocode)

SECP256K1_ORDER = n  # 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141

def tweak_add(pubkey32: bytes, tweak32: bytes) -> bytes:
    if len(pubkey32) != 32 or len(tweak32) != 32:
        raise ValueError
    t = int.from_bytes(tweak32, 'big')
    if t >= SECP256K1_ORDER:
        raise ValueError
    P = lift_x_even_y(pubkey32)  # BIP340 lift of x to the point with even Y
    if P is None:
        raise ValueError
    Q = point_add(P, scalar_mul_G(t))  # Q = P + t*G
    if Q is None:  # point at infinity
        raise ValueError
    return Q.x.to_bytes(32, 'big')

Reference implementation notes

  • Reuse BIP340 lift/encode helpers from Taproot verification.
  • Implement t*G via fixed-base multiplication, then combine with P using point addition.
  • Serialize the result as 32-byte x-only.
  • Charge EC op budget as 50, like OP_CHECKSIGADD.

Protocol Design Note: Scalar Adjustment

When working with x-only keys, it is important to remember that each 32-byte value encodes the equivalence class {P, −P}. BIP340 defines the canonical lift as the point with even Y. As a result:

  • If an off-chain protocol describes an x-only key as "the point s·G," then in consensus terms the actual key is adj(s)·G, where:

adj(s) = s        if y(s·G) is even
       = n − s    if y(s·G) is odd

  • Consequently, OP_TWEAKADD(x(s·G), t) always computes:

result = x(adj(s)·G + t·G)

not simply x(s·G + t·G).

This distinction is invisible when signing or verifying against BIP340 keys, because both s and n − s yield the same x-only key. But it matters when a protocol tries to relate "a tweak applied at the base" (x(G), t = s) to "a tweak applied at a derived key" (x(s·G), t = 1). In general those will differ unless the original point already had even Y.

  • If you want consistent algebraic relations across different ways of composing tweaks, normalize scalars off-chain before pushing them into script.
  • That is: replace every candidate tweak s with adj(s), so that adj(s)·G has even Y.
  • A simple library function can perform this parity check and adjustment using libsecp256k1 without a consensus modification or opcode.

If the tweak is derived from inflexible state, such as a transaction hash or a signature, it may be infeasible to depend on commutativity of tweaking. Protocols such as LN-Symmetry may simply grind the tx if even-y of tweak is required.

Protocol Design Note: Algebraic Limits

OP_TWEAKADD implements only:

x(lift_x(X) + t*G)

If X = x(G), then because the secp256k1 generator has even Y, this becomes:

x(G + t*G) = x((t + 1)*G)

This may suggest that repeated applications of OP_TWEAKADD can emulate an x-only scalar-multiplication opcode. In general this is not correct. After each application, the 32-byte x-only output is interpreted again using the BIP340 even-Y lift before the next tweak is added. Consequently:

OP_TWEAKADD(OP_TWEAKADD(x(G), t), n - 1)
= x(adj(t + 1)*G - G)

which equals x(t*G) only when (t + 1)*G already has even Y.

More generally, OP_TWEAKADD does not provide a generic OP_ECMUL_XONLY or OP_ECADD for hidden points. The opcode only adds multiples of the fixed generator G; it does not multiply an arbitrary point by a scalar, and x-only encodings do not retain the sign information needed to compose arbitrary point additions without additional data. As a result, OP_TWEAKADD is useful for expressing relations to a known base key or to generator-derived tweaks, but it does not subsume generic elliptic-curve arithmetic or signature verification primitives. For example, checking a Schnorr relation s*G = R + e*P requires scalar multiplication of an arbitrary public key P by e and point addition with R, neither of which can be implemented from OP_TWEAKADD alone without revealing additional information outside the x-only model.

Illustrative Constructions

The following sketches are non-normative examples. Some of them compose OP_TWEAKADD with other proposed opcodes, notably BIP 348 OP_CHECKSIGFROMSTACK and BIP 349 OP_INTERNALKEY.

Tweak-reveal scripts

A tapscript may commit to a base key and accept a witness-provided scalar that must be revealed to derive the signing key. One such construction composes OP_TWEAKADD with BIP 348 OP_CHECKSIGFROMSTACK and BIP 349 OP_INTERNALKEY. When the construction requires the scalar to be hashed before use, the script can express that explicitly:

witness: <sig> <msg> <tweak>
script:  OP_SHA256 OP_INTERNALKEY OP_TWEAKADD OP_CHECKSIGFROMSTACK

Alternatively, with OP_CHECKSIG:

witness: <sig> <tweak>
script:  OP_SHA256 OP_INTERNALKEY OP_TWEAKADD OP_CHECKSIG

Applying OP_SHA256 to the witness-provided scalar in these constructions prevents key cancellation.

Proof of signing order and transaction refinement

OP_TWEAKADD can bind one signer's authorization to another signer's signature by tweaking key A with SHA256(sig_B). The second signature then proves that A signed only after seeing B's complete signature, so B can fix transaction details first and A can refine them later:

witness: <sig_A> <sig_B>
script:  DUP TOALT <B> CHECKSIGVERIFY FROMALT SHA256 <A> OP_TWEAKADD OP_CHECKSIG

In this construction, A is bound to B's complete signature. B may use any sighash flag combination, so A refines B's signature rather than the reverse.

For example, B may sign with SIGHASH_SINGLE|SIGHASH_ANYONECANPAY to commit only to one particular output paying B, while leaving input selection, fee payment, and change outputs unspecified. A may then sign the completed transaction with SIGHASH_ALL, selecting the concrete inputs, fee arrangement, and any additional outputs while remaining bound to that exact authorization from B. In this sense, A refines B's partial authorization into authorization for one fully specified transaction.

Delegation

A delegation protocol may allow A to delegate broad authority to key B. The predicate enforced by this script is that B produced a valid signature and that A authorized delegation to B by signing for the key derived from base key A and scalar SHA256(B). The script verifies B's signature first and then checks A's delegation authorization. This verification order is chosen to avoid OP_SWAP; it does not imply that B must have signed before A authorized delegation.

witness: <sig_A> <sig_B> <B>
script:  DUP TOALT CHECKSIGVERIFY FROMALT SHA256 <A> OP_TWEAKADD OP_CHECKSIG

If A uses a weak sighash mode such as SIGHASH_NONE, A need only authorize delegation to B and does not materially constrain the final transaction. B may then choose the concrete inputs, outputs, and fees, and provide the transaction signature that refines A's permissive authorization into authorization for one fully specified transaction.

Unlike the signing-order construction above, this construction does not require OP_CHECKSIGFROMSTACK, because A need only be bound to B's public key rather than to B's eventual signature bytes.

Target-tweak and key-reveal contracts

In its simplest form, OP_TWEAKADD can prove knowledge of a scalar t such that tG + k1G = k2G:

witness: <t>
script:  <k1G> OP_TWEAKADD <k2G> OP_EQUAL

If the construction requires the scalar to be hashed first, the script can express that directly:

witness: <t>
script:  OP_SHA256 <k1G> OP_TWEAKADD <k2G> OP_EQUAL

If k2G is used as a Taproot output key, this construction can force disclosure of the scalar needed to account for the corresponding Taproot tweak.

A key-reveal contract is a special case of the target-tweak construction. Given T = tG, the script can require disclosure of t by checking that G + tG = T + G:

witness: <t>
script:  <G> OP_TWEAKADD <T_plus_G> OP_EQUAL

Merkleized commitments

OP_TWEAKADD can also be used to commit to the root of a Merkleized data structure by treating the root hash as a tweak scalar. Let K_root = tweak(P, H(root)), where root is the Merkle root of some application state or set of valid transitions and H(root) is interpreted as a secp256k1 scalar when valid. Revealing the root can then be checked with:

witness: <root>
script:  OP_SHA256 <P> OP_TWEAKADD <K_root> OP_EQUAL

This permits a script to commit to a large data structure using one derived key while deferring disclosure of the underlying tree to the witness. If the script also has a way to compute parent hashes from child hashes, for example OP_CAT OP_SHA256, then a Merkle branch can be verified by iteratively recomputing root from a revealed leaf and its sibling path, and then checking the resulting root against the committed key above. In that setting, OP_TWEAKADD provides the bridge from a Merkle root to a key that can be consumed by the rest of the script, allowing Merkleized state or transition commitments in the style of constructions such as MATT.

Even without arbitrary concatenation opcodes, OP_TWEAKADD can be used to build a Merkle-like authenticated tree over 32-byte node commitments. Let B_leaf = x(2G) and B_node = x(3G) be distinct fixed x-only public keys, and define:

Leaf(x)   = tweak(B_leaf, SHA256(x))
Node(L,R) = tweak(tweak(B_node, HASH256(L)), SHA256(HASH256(R)))

Here the point input is always either a fixed valid x-only key or the output of a prior OP_TWEAKADD, so no hash-to-point grinding is required. The different hash constructions separate the left-child and right-child roles, while the distinct base keys separate leaf commitments from internal-node commitments.

One parent reduction can be expressed directly in script:

witness: <L> <R>
script:  OP_TOALTSTACK OP_HASH256 <B_node> OP_TWEAKADD
         OP_FROMALTSTACK OP_HASH256 OP_SHA256 OP_SWAP OP_TWEAKADD

A branch proof starts from Leaf(x) for the revealed leaf value x, then iteratively combines it with each sibling commitment using the appropriate left or right parent rule until the committed root key is reconstructed.

This construction should be understood as an ordered binary commitment tree rather than as a general Merkle compression opcode. The recursive use of SHA256, HASH256, and SHA256(HASH256(.)) separates roles, but it does not by itself define a canonical tree shape. A protocol using this pattern should therefore also fix the tree arity, proof length, and any empty-subtree or append rules so that the same application state cannot be represented by multiple tree layouts.

For comparison, BIP 442 OP_PAIRCOMMIT is purpose-built for pair commitments and yields simpler and cheaper Merkleized constructions in practice. The construction above is therefore best understood as a potentially useful tree-commitment technique if OP_TWEAKADD were deployed on its own, rather than as a primary reason to add OP_TWEAKADD when a dedicated pair-commitment opcode is available.

Test vectors (Generated)

Curve order n = fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141

Passing cases

  1. Identity tweak (t = 0)
  pubkey32    =  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
  tweak32     =  0000000000000000000000000000000000000000000000000000000000000000
  expect      =  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798

  script      =  <0000000000000000000000000000000000000000000000000000000000000000> <79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798> OP_TWEAKADD <79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798> OP_EQUAL
  1. Increment by 1
  pubkey32    =  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
  tweak32     =  0000000000000000000000000000000000000000000000000000000000000001
  expect      =  c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5

  script      =  <0000000000000000000000000000000000000000000000000000000000000001> <79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798> OP_TWEAKADD <c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5> OP_EQUAL
  1. Increment by 2
  pubkey32    =  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
  tweak32     =  0000000000000000000000000000000000000000000000000000000000000002
  expect      =  f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9

  script      =  <0000000000000000000000000000000000000000000000000000000000000002> <79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798> OP_TWEAKADD <f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9> OP_EQUAL
  1. Increment by 5
  pubkey32    =  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
  tweak32     =  0000000000000000000000000000000000000000000000000000000000000005
  expect      =  fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556

  script      =  <0000000000000000000000000000000000000000000000000000000000000005> <79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798> OP_TWEAKADD <fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556> OP_EQUAL
  1. Input x(2G), t = 3
  pubkey32    =  c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5
  tweak32     =  0000000000000000000000000000000000000000000000000000000000000003
  expect      =  2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4

  script      =  <0000000000000000000000000000000000000000000000000000000000000003> <c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5> OP_TWEAKADD <2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4> OP_EQUAL
  1. Input x(7G), t = 9
  pubkey32    =  5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc
  tweak32     =  0000000000000000000000000000000000000000000000000000000000000009
  expect      =  e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a

  script      =  <0000000000000000000000000000000000000000000000000000000000000009> <5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc> OP_TWEAKADD <e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a> OP_EQUAL
  1. Input x(h(1) G), t = 1
  pubkey32    =  d415b187c6e7ce9da46ac888d20df20737d6f16a41639e68ea055311e1535dd9
  tweak32     =  0000000000000000000000000000000000000000000000000000000000000001
  expect      =  c6713b2ac2495d1a879dc136abc06129a7bf355da486cd25f757e0a5f6f40f74

  script      =  <0000000000000000000000000000000000000000000000000000000000000001> <d415b187c6e7ce9da46ac888d20df20737d6f16a41639e68ea055311e1535dd9> OP_TWEAKADD <c6713b2ac2495d1a879dc136abc06129a7bf355da486cd25f757e0a5f6f40f74> OP_EQUAL
  1. Input x(h(2) G), t = 1
  pubkey32    =  d27cd27dbff481bc6fc4aa39dd19405eb6010237784ecba13bab130a4a62df5d
  tweak32     =  0000000000000000000000000000000000000000000000000000000000000001
  expect      =  136f23e6c2efcaa13b37f0c22cd6cfb0d4e6e9eddccefe17e747f5cf440bb785

  script      =  <0000000000000000000000000000000000000000000000000000000000000001> <d27cd27dbff481bc6fc4aa39dd19405eb6010237784ecba13bab130a4a62df5d> OP_TWEAKADD <136f23e6c2efcaa13b37f0c22cd6cfb0d4e6e9eddccefe17e747f5cf440bb785> OP_EQUAL
  1. Input x(h(7) G), t = 1
  pubkey32    =  ddc399701a78edd5ea56429b2b7b6cd11f7d1e4015e7830b4f5e07eb25058768
  tweak32     =  0000000000000000000000000000000000000000000000000000000000000001
  expect      =  0e27b02714b3f2344f2bfa6d821654f2bd9f0ef497ec541b653b8dcb3a915faf

  script      =  <0000000000000000000000000000000000000000000000000000000000000001> <ddc399701a78edd5ea56429b2b7b6cd11f7d1e4015e7830b4f5e07eb25058768> OP_TWEAKADD <0e27b02714b3f2344f2bfa6d821654f2bd9f0ef497ec541b653b8dcb3a915faf> OP_EQUAL
  1. Input x(G), t = 1
  pubkey32    =  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
  tweak32     =  4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a
  expect      =  c6713b2ac2495d1a879dc136abc06129a7bf355da486cd25f757e0a5f6f40f74

  script      =  <4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a> <79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798> OP_TWEAKADD <c6713b2ac2495d1a879dc136abc06129a7bf355da486cd25f757e0a5f6f40f74> OP_EQUAL
  1. Input x(G), t = h(2)
  pubkey32    =  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
  tweak32     =  dbc1b4c900ffe48d575b5da5c638040125f65db0fe3e24494b76ea986457d986
  expect      =  136f23e6c2efcaa13b37f0c22cd6cfb0d4e6e9eddccefe17e747f5cf440bb785

  script      =  <dbc1b4c900ffe48d575b5da5c638040125f65db0fe3e24494b76ea986457d986> <79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798> OP_TWEAKADD <136f23e6c2efcaa13b37f0c22cd6cfb0d4e6e9eddccefe17e747f5cf440bb785> OP_EQUAL
  1. Input x(G), t = h(7) (Note: differs from 9)
  pubkey32    =  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
  tweak32     =  ca358758f6d27e6cf45272937977a748fd88391db679ceda7dc7bf1f005ee879
  expect      =  00b152fb17d249541e3b2f51455269e02d76507ad7857aaa98e3c51ee5da5b1d

  script      =  <ca358758f6d27e6cf45272937977a748fd88391db679ceda7dc7bf1f005ee879> <79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798> OP_TWEAKADD <00b152fb17d249541e3b2f51455269e02d76507ad7857aaa98e3c51ee5da5b1d> OP_EQUAL

Failing cases

A) Scalar out of range (t = n)

  pubkey32    =  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
  tweak32     =  fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
  expect      =  fail
  script      =  <fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141> <79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798> OP_TWEAKADD OP_DROP OP_1

B) Invalid x (x = 0), t = 1

  pubkey32    =  0000000000000000000000000000000000000000000000000000000000000000
  tweak32     =  0000000000000000000000000000000000000000000000000000000000000001
  expect      =  fail
  script      =  <0000000000000000000000000000000000000000000000000000000000000001> <0000000000000000000000000000000000000000000000000000000000000000> OP_TWEAKADD OP_DROP OP_1

C) Infinity result (x(G), t = n-1)

  pubkey32    =  79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
  tweak32     =  fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140
  expect      =  fail
  script      =  <fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140> <79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798> OP_TWEAKADD OP_DROP OP_1

Acknowledgements

This proposal extends the Taproot tweak mechanism (BIP340/341) into script, inspired by prior work on scriptless scripts and key-evolution constructions. There has been various discussion of OP_TWEAKADD over the years, including by Russell O'Connor and Steven Roose.

References

This BIP is licensed under the BSD-3-Clause License.


Updated

2026-05-24

See an issue with rendering or formatting? Submit an issue on GitHub

Do you find this site useful? Please consider donating some sats to support ongoing development.

bips.dev is presented by nickmonad

All content is owned and licensed by the respective author(s). This website makes no claim of ownership.