#29247 CAT in Tapscript (BIP-347)

ReviewabilityReviewsAgreementSize
#29247 arminsabouri CAT in Tapscript (BIP-347)Author silent 169d0Blocked46 + 742 tests
  • Enable byte and string concatenation in Tapscript under the standard 520-byte stack element limit
  • Provide interpreter logic and test harness support for BIP-347 evaluation without bundling activation
  • Review is likely to wait on the author, who has been inactive on the PR for over four months
  • No review verdicts recorded
  • Blocking objection: cannot merge a consensus opcode without project or community consensus (achow101)
  • Nonblocking objection: standard limit enables unintended introspection like SIGHASH assembly (moonsettler)
  • Support for merging the opcode implementation into the interpreter (EthanHeilman)
  • 46 lines added or modified outside tests
  • 742 lines added or modified in tests
  • 7 lines removed in total
  • 9 files, 3 commits
Validation#21 of 53
P2 · new feature
  • P2 because it implements a major consensus opcode proposal in the Tapscript interpreter
  • Validates execution correctness and 520-byte stack bounds for prospective script capabilities
  • Ranking pass: Grouped with the other proposed-opcode implementations rather than ahead of concrete fixes
Reviewability: ReadyStalePaused
Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets
Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs.
Size: lines added or modified outside tests, then in tests; greener = smaller.

Goal

This pull request implements the OP_CAT opcode in Tapscript according to BIP-347 by redefining opcode OP_SUCCESS126 (0x7e). It introduces two script flags, SCRIPT_VERIFY_OP_CAT for consensus evaluation and SCRIPT_VERIFY_DISCOURAGE_OP_CAT for mempool policy, while omitting miner signaling or activation parameters. The change also adds helper macros to the JSON script test runner to simplify writing Tapscript test cases alongside unit and functional tests.

Problem: Bitcoin Script currently lacks string and byte concatenation operations, which were disabled in 2010 over memory exhaustion concerns. BIP-347 proposes reintroducing OP_CAT in Tapscript with explicit bounds enforced by the 520-byte stack element limit, but Bitcoin Core lacks the interpreter logic and test harness to evaluate or eventually deploy the proposal.

Evidence of importance:

  • Author notes the implementation matches BIP-347 and BIN-2024-0001, which was merged into bitcoin-inquisition on April 25, 2024, activated on Signet on April 30, 2024, and reviewed in the Bitcoin Core PR Review Club.
  • Author description highlights live Signet testing: 'Since Apr 30 2024 there have been many OP_CAT transactions created and spent on signet.'
  • Author emphasizes this PR deliberately omits consensus activation: 'This PR does not include miner activation functionality... If this PR is merged it is not a signal of community consensus around activating CAT'.

Scope: Modifies core script execution in interpreter.cpp and policy flags in policy.h. It also extends test/script_tests.cpp with custom string substitution tokens (#SCRIPT#, #CONTROLBLOCK#, #TAPROOTOUTPUT#) to auto-generate Tapscript outputs and control blocks in script_tests.json.

Reviewability

Stale · Author silent 169d

No author activity for 169 days; a review may wait a long time for a response.

Waiting on (from the thread read):

  • decision: project and community consensus on OP_CAT in Tapscript 2024-10-19
  • decision: community and project consensus on OP_CAT activation 2024-10-19

Agreement

Blocked

objection that needs a change, nobody has replied (achow101)

Thread notes: Re-evaluated under current schema: converted rot13maxi's rc:1757499656 to a suggestion since it requested additional test coverage rather than naming an unavoidable harm; added Co1nB3e's question c:2857183685; awin28522's approval remains unlisted in support as an empty verdict with no project history rationale. / Re-classified rot13maxi's request for test combinations as a suggestion rather than an objection; marked moonsettler's objection answered via bigspider's technical reply; added Co1nB3e

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
moonsettler (none)objection, scopestandard 520-byte OP_CAT enables open-ended second-order effects such as assembling SIGHASH or CTV templates on the stack for unintended introspectionopen · no author reply; bigspider discussed the idea but author has not repliedansweredby others2024-02-15: 'It explicitly disables open ended second order effects by removing the ability to assemble a SIGHASH or CTV template on the stack for more detailed introspection than intended.'
rot13maxi (none)suggestion, correctnessadd unit tests exercising combinations of SCRIPT_VERIFY_DISCOURAGE_OP_CAT and SCRIPT_VERIFY_OP_CATfixed · fix pushed · tests added to script_tests.jsonansweredyes2024-09-12: 'it would be great to have a test that exercises the combinations of SCRIPT_VERIFY_DISCOURAGE_OP_CAT and SCRIPT_VERIFY_OP_CAT'
Status from: 2024-09-17: arminsabouri: 'Added some additional unit tests to script_tests.json testing different combinations of scripts with and without (SCRIPT_VERIFY_DISCOURAGE_OP_CAT, SCRIPT_VERIFY_OP_CAT and SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS)'
achow101 (member)objection, scopemerging a consensus opcode change without project or community consensusopen · draft status remains; consensus has not formedchangedno2024-10-19: 'there does not appear to be consensus for the concept of OP_CAT in TapScript yet, so this PR cannot be merged even if the code is okay.'
Co1nB3e (none)question, interfacewhether the case where SCRIPT_VERIFY_OP_CAT = False and SCRIPT_VERIFY_DISCOURAGE_OP_CAT = False is part of the tests and soft fork tableanswered · answered by EthanHeilman, arminsabouri, and ajtownsansweredyes2025-05-07: 'What about SCRIPT_VERIFY OP_CAT = False and SCRIPT_VERIFY DISCOURAGE_OP_CAT = False? This combination is not described in the "soft fork" table. Is it part of the tests?'
Status from: 2025-05-09: arminsabouri: 'That said, @AlexSQY, you're right -- this edge case deserves documentation. If I recall correctly, it’s being tested here'

Support:

  • EthanHeilman (contributor) (2026-04-30): I am still very interested in merging this, however there was unexpected progress in quantum computers and I am temporarily shifting my attention to that.

Participants:

  • moonsettler (none, objection, 1 statements 2024-02-15 to 2024-02-15): suggested capping OP_CAT output to 80 bytes to prevent unintended introspection and CTV templates on the stack
  • bigspider (contributor, neutral, 1 statements 2024-02-16 to 2024-02-16): pointed out that limiting output to 80 bytes would not prevent CHECKSIG stack tricks
  • awin28522 (none, neutral, 1 statements 2024-08-31 to 2024-08-31): left an empty approval review without rationale
  • rot13maxi (none, neutral, 1 statements 2024-09-12 to 2024-09-12): suggested adding test coverage for combinations of SCRIPT_VERIFY_DISCOURAGE_OP_CAT and SCRIPT_VERIFY_OP_CAT
  • ajtowns (member, neutral, 2 statements 2024-10-09 to 2025-05-12): linked bitcoin-inquisition PR and clarified flag expectations for relay versus block validation
  • achow101 (member, objection, 3 statements 2024-10-15 to 2024-10-20): converted PR to draft due to lack of community and project consensus on OP_CAT
  • EthanHeilman (contributor, support, 5 statements 2024-10-19 to 2026-04-30): supports merging OP_CAT, discussed draft criteria, and noted temporary shift to quantum computing
  • Co1nB3e (none, question, 2 statements 2025-05-07 to 2025-05-08): asked about the untested edge case where both OP_CAT and DISCOURAGE_OP_CAT flags are false

Dependencies

Enables:

  • Deployment and activation mechanism for BIP-347 OP_CAT

Files

743 lines under test/bench/ci.

  • src/test/data/script_tests.json +414/-0
  • test/functional/feature_opcat.py +248/-0
  • src/test/script_tests.cpp +79/-1
  • src/script/interpreter.cpp +36/-5
  • src/script/interpreter.h +4/-0
  • src/policy/policy.h +2/-1
  • src/script/script_error.h +3/-0
  • src/script/script_error.cpp +1/-0
  • test/functional/test_runner.py +1/-0

Card

The short text the ranking pass compares across PRs.

This pull request implements OP_CAT in Tapscript according to BIP-347 by redefining OP_SUCCESS126. It allows concatenation of stack elements up to the 520-byte maximum script element size under a new script verification flag, while keeping OP_CAT discouraged under standard mempool relay policy and disabled on legacy script types. It does not include consensus activation parameters or miner signaling. The change enables developers and researchers to evaluate and test the opcode implementation directly in Core, following its activation on bitcoin-inquisition Signet in April 2024.

Data

dossier JSON · extract JSON · model ledger, generated 2026-09-25T01:25, confidence high, input hash cf9b0df045efb337
thread read through 2026-04-30 (19 statements), head 6ca33cb59e
labels: Consensus · draft

Categories

Validation

P2 · new feature (ranking pass: Grouped with the other proposed-opcode implementations rather than ahead of concrete fixes)

The PR implements a major proposed consensus opcode (BIP-347 OP_CAT) in the Tapscript interpreter, which warrants deliberate validation review to verify interpreter bounds and execution correctness. While consensus has not yet formed around activation, validating the opcode implementation and its 520-byte stack limits addresses a prominent script capability proposal.

Membership: Carries Consensus label, modifies src/script/interpreter.cpp and src/script/interpreter.h to implement OP_CAT in Tapscript.

Factors: security/stability 1, bug 0, performance 0, user value 2, leverage 2