{"number":349,"title":"OP_INTERNALKEY","authors":["Brandon Black","Jeremy Rubin"],"status":"Draft","type":"Specification","layer":"Consensus (soft fork)","created":"2024-11-14","license":"BSD-3-Clause","requires":[],"replaces":[],"replacedBy":[],"discussion":[],"abstract":"This BIP describes a new tapscript opcode ( OP_INTERNALKEY ) which pushes the taproot internal key to the stack.","eli5":"Adds a small script instruction that places a Taproot output's 'internal key', the main key behind the output, onto the script's working data. It saves space by avoiding repeating that key inside scripts, and is designed to complement other proposed instructions for advanced contracts.","categories":["wallets"],"filename":"bip-0349.md","githubUrl":"https://github.com/bitcoin/bips/blob/master/bip-0349.md","format":"markdown","readingMinutes":2,"inbound":1,"revisions":11,"impact":37,"core":false,"references":[],"lastModified":"2025-10-08","html":"<h2 id=\"abstract\">Abstract</h2>\n<p>This BIP describes a new tapscript opcode (<code>OP_INTERNALKEY</code>) which\npushes the <em>taproot internal key</em> to the stack.</p>\n<h2 id=\"specification\">Specification</h2>\n<p>When verifying taproot script path spends having leaf version <code>0xc0</code> (as\ndefined in <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki\">BIP 342</a>), <code>OP_INTERNALKEY</code> replaces <code>OP_SUCCESS203</code> (0xcb).\n<code>OP_INTERNALKEY</code> pushes the 32-byte x-only representation of the <em>taproot\ninternal key</em> (referred to as <em>p</em>), as defined in <a href=\"https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki\">BIP 341</a>, to the stack.</p>\n<h2 id=\"motivation\">Motivation</h2>\n<h3 id=\"key-spend-with-additional-conditions\">Key spend with additional conditions</h3>\n<p>When building taproot outputs, especially those secured by an aggregate key\nrepresenting more than one signer, the parties may wish to collaborate on\nsigning with the <em>taproot internal key</em>, but only with additional script\nrestrictions. In this case, <code>OP_INTERNALKEY</code> saves 8 vBytes.</p>\n<h3 id=\"mitigated-control-block-overhead-for-scripts-using-hash-locks\">Mitigated control block overhead for scripts using hash locks</h3>\n<p>In cases where key path spending is not desired, the internal key may be set to\na NUMS point whose bytes would otherwise be required in a tapscript. This could\nbe used with any hash locked transaction, for example, to save 8 vBytes.</p>\n<p>Note: The internal key must be the X coordinate of a point on the SECP256K1\ncurve, so any such hash must be checked and modified until it is such an X\ncoordinate. This will typically take approximately 2 attempts.</p>\n<h3 id=\"re-keying-with-merkle-root-preservation\">Re-Keying with Merkle Root Preservation</h3>\n<p>Consider a program such <code>CTV &lt;X&gt; CSFS &lt;S+1&gt; CLTV</code>. Such fragments are useful for LN-Symmetry applications.</p>\n<p>Such a program would be embedded within a Taproot script path, such as <code>TR(X, {CTV &lt;X&gt; CSFS &lt;S+1&gt; CLTV})</code>.</p>\n<p>Were the internal key to be updated from <code>X</code> to <code>Y</code>, the resulting program would be: <code>TR(Y, {CTV &lt;X&gt; CSFS &lt;S+1&gt; CLTV})</code>.</p>\n<p>The key in the leaf and the key-path would be mismatched. Were <code>OP_INTERNALKEY</code> to be used,\nthe leaf would automatically re-key.\nE.g., <code>TR(X, {CTV OP_INTERNALKEY CSFS &lt;S+1&gt; CLTV})</code> is equivalent to <code>TR(X, {CTV &lt;X&gt; CSFS &lt;S+1&gt; CLTV})</code>\nand <code>TR(Y, {CTV OP_INTERNALKEY CSFS &lt;S+1&gt; CLTV})</code> is equivalent to <code>TR(Y, {CTV &lt;Y&gt; CSFS &lt;S+1&gt; CLTV})</code>.</p>\n<p>While this particular example is contrived, the general technique of using <code>OP_INTERNALKEY</code>\nas updatable across an entire script tree is a helpful covenant primitive when it is desirable to\ninvalidate signatures from prior states. For example, the theoretical <code>OP_TAPLEAFUPDATEVERIFY</code> opcode\nmodifies the internal key directly to remove or add a participant, and <code>OP_INTERNALKEY</code> would ensure\nthat the tweaked key is used from all script paths where desired.</p>\n<h2 id=\"reference-implementation\">Reference Implementation</h2>\n<p>A reference implementation is provided here:</p>\n<p><a href=\"https://github.com/bitcoin/bitcoin/pull/29269\">https://github.com/bitcoin/bitcoin/pull/29269</a></p>\n<h2 id=\"backward-compatibility\">Backward Compatibility</h2>\n<p>By constraining the behavior of an OP_SUCCESS opcode, deployment of the BIP\ncan be done in a backwards compatible, soft-fork manner. If anyone were to\nrely on the OP_SUCCESS behavior of <code>OP_SUCCESS203</code>, <code>OP_INTERNALKEY</code> would\ninvalidate their spend.</p>\n<h2 id=\"deployment\">Deployment</h2>\n<p>TBD</p>\n<h2 id=\"credits\">Credits</h2>\n<p>The concept for INTERNALKEY first arose in a <a href=\"https://gnusha.org/bitcoin-wizards/2022-01-05.log\">discussion</a> between Russell O&#39;Connor\nand Jeremy Rubin in Bitcoin Wizards IRC, inspired by BIP-0118&#39;s key punning technique\nfor the internal key. It was later\ndrafted into this BIP by Brandon Black.</p>\n<h2 id=\"copyright\">Copyright</h2>\n<p>This document is licensed under the 3-clause BSD license.</p>\n","toc":[{"id":"abstract","title":"Abstract","level":2},{"id":"specification","title":"Specification","level":2},{"id":"motivation","title":"Motivation","level":2},{"id":"key-spend-with-additional-conditions","title":"Key spend with additional conditions","level":3},{"id":"mitigated-control-block-overhead-for-scripts-using-hash-locks","title":"Mitigated control block overhead for scripts using hash locks","level":3},{"id":"re-keying-with-merkle-root-preservation","title":"Re-Keying with Merkle Root Preservation","level":3},{"id":"reference-implementation","title":"Reference Implementation","level":2},{"id":"backward-compatibility","title":"Backward Compatibility","level":2},{"id":"deployment","title":"Deployment","level":2},{"id":"credits","title":"Credits","level":2},{"id":"copyright","title":"Copyright","level":2}],"history":{"totalCommits":11,"firstCommit":"2024-11-14T18:10:42+01:00","lastUpdated":"2025-10-08T14:59:36-07:00","events":[{"sha":"24e96e870fffaa257b465ce1f0370c14aac588e8","date":"2025-10-08T14:59:36-07:00","author":"Murch","message":"process: Created ↦ Assigned","url":"https://github.com/bitcoin/bips/commit/24e96e870fffaa257b465ce1f0370c14aac588e8","kind":"edit"},{"sha":"5207ef92a52d0b8902895b0dbb40823a4d698ec9","date":"2025-04-11T20:08:17-07:00","author":"Murch","message":"process: Author ↦ Authors","url":"https://github.com/bitcoin/bips/commit/5207ef92a52d0b8902895b0dbb40823a4d698ec9","kind":"edit"},{"sha":"59730dec4fb641a41589aa1b91d3c452f13e0e36","date":"2025-04-11T20:05:13-07:00","author":"Murch","message":"process: Remove Comments-URI and -Summary","url":"https://github.com/bitcoin/bips/commit/59730dec4fb641a41589aa1b91d3c452f13e0e36","kind":"edit"},{"sha":"a233bde4af52c6a11269e2e6dd9707abce441ffe","date":"2025-04-11T18:19:21-07:00","author":"Murch","message":"process: Standards Track ↦ Specification","url":"https://github.com/bitcoin/bips/commit/a233bde4af52c6a11269e2e6dd9707abce441ffe","kind":"edit"},{"sha":"726df6f4d54c7c7f9f1856ab37d07ece5defa0eb","date":"2025-02-08T20:04:18+10:00","author":"Anthony Towns","message":"Use code block instead of pre for markdown","url":"https://github.com/bitcoin/bips/commit/726df6f4d54c7c7f9f1856ab37d07ece5defa0eb","kind":"edit"},{"sha":"337f5591504b0c8175d9c2690c23e93e71aa2df4","date":"2024-12-21T14:43:40-05:00","author":"Jeremy Rubin","message":"[BIP-0349] Add Re-Keying explanation to OP_INTERNALKEY","url":"https://github.com/bitcoin/bips/commit/337f5591504b0c8175d9c2690c23e93e71aa2df4","kind":"edit"},{"sha":"d3d34c04f362d369ab9861808de85c77e2eabe07","date":"2024-12-21T12:39:05-05:00","author":"Jeremy Rubin","message":"[BIP-0349] wrap discussion link","url":"https://github.com/bitcoin/bips/commit/d3d34c04f362d369ab9861808de85c77e2eabe07","kind":"edit"},{"sha":"b02d2db5860eabe6601954c72b91dc6de29ef593","date":"2024-12-19T23:52:11-05:00","author":"Jeremy Rubin","message":"[BIP0-0349] OP_INTERNALKEY add credit section","url":"https://github.com/bitcoin/bips/commit/b02d2db5860eabe6601954c72b91dc6de29ef593","kind":"edit"},{"sha":"217ae0dfa8c51a16a5d1e1b66f20c6bfb2d64147","date":"2024-11-14T16:28:11-05:00","author":"Murch","message":"BIP349: Set Created header to number assignment","url":"https://github.com/bitcoin/bips/commit/217ae0dfa8c51a16a5d1e1b66f20c6bfb2d64147","kind":"edit"},{"sha":"669d3b3570adad74febcb054f21c4d56b3ee4106","date":"2024-11-14T16:26:55-05:00","author":"Murch","message":"BIP349: Fix preamble for CI issues","url":"https://github.com/bitcoin/bips/commit/669d3b3570adad74febcb054f21c4d56b3ee4106","kind":"edit"},{"sha":"329b0d3db50dea3b348f7322cb5af4ec37064013","date":"2024-11-14T18:10:42+01:00","author":"moonsettler","message":"BIP-349","url":"https://github.com/bitcoin/bips/commit/329b0d3db50dea3b348f7322cb5af4ec37064013","kind":"edit"}]}}