This commit creates new test utilities for future Taproot script tests within script_tests.json. The key features of this commit are the addition of three new tags: #SCRIPT#
, #CONTROLBLOCK#
, and #TAPROOTOUTPUT#
. These tags streamline the test creation process by eliminating the need to manually generate these components outside the test suite.
#SCRIPT#
: Parses Tapscript and outputs a byte string of opcodes.#CONTROLBLOCK#
: Automatically generates the control block for a given Taproot output.#TAPROOTOUTPUT#
: Generates the final Taproot scriptPubKey.
This code was originally part of the OP_CAT PR #29247 but was pulled out into a separate PR to reduce the rebase treadmill for the OP_CAT PR.
Rationale
While writing JSON script tests (script_tests.json) for #29247 we ran into the following problem. The JSON script tests are simple and easy to write for pre-Tapscript scripts, but adding or changing a Tapscript test requires substantial work per test. Consider the following pre-tapscript test:
0["'aa' 'bb'", "CAT 0x4c 0x02 0xaabb EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"]
whereas a Tapscript test for the same script (annotated with comments for better readability) would look like:
0[
1 [
2 "aa",
3 "bb",
4 "7e4c02aabb87", // output script
5 "c0d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d", // control block
6 0.00000001
7 ],
8 "",
9 "0x51 0x20 0x15048ed3a65748549c27b671936987093cf73a4c9cb18522a74fb9553060ca99", // Tapscript output
10 "P2SH,WITNESS,TAPROOT",
11 "OK",
12 "TAPSCRIPT CATs aa and bb together and checks if EQUAL to aabb"
13]
Computing the Tapscript output, such as 0x51 0x20 0x15048ed3a65748549c27b671936987093cf73a4c9cb18522a74fb9553060ca99
, requires writing custom code and running it for each test. The same is true for the Tapscript control block, such as c0d6889cb081036e0faefa3a35157ad71086b123b2b144b649798b494c300a961d
. If a test is changed or updated new outputs and control blocks must be computed. The complexity of doing this is likely the reason that no one has added any Tapscript tests to JSON script tests until this PR.
In this PR we address this issue by adding the following improvements to JSON script tests:
Adding simple macros ("#SCRIPT# and #CONTROLBLOCK#) that allow the script test parser to automatically generate and inject a valid Tapscript output and control block to be computed automatically from the JSON script. Allowing Tapscript scripts to use the human readable strings like pre-script scripts by marking the location of the script in the witness stack using #SCRIPT#. This transforms the unreadable script 7e4c02aabb87 into #SCRIPT# CAT 0x4c 0x02 0xaabb EQUAL. This results in the following JSON script test which is far easier to write and easier to read.
0[
1 [
2 "aa",
3 "bb",
4 "#SCRIPT# CAT",
5 "#CONTROLBLOCK#",
6 0.00000001
7 ],
8 "",
9 "0x51 0x20 #TAPROOTOUTPUT#",
10 "P2SH,WITNESS,TAPROOT,OP_CAT",
11 "OK",
12 "TAPSCRIPT Test of OP_CAT flag by calling CAT on two elements. TAPSCRIPT_OP_CAT flag is set so CAT is executed."
13],