Test: Add script vectors for interpreter edges

Add script_tests.json and tx_invalid.json vectors for edge cases that
other implementations have gotten wrong, including CSV with -2, IFDUP
on negative zero, ROLL with duplicate values, a taproot output key
that is not a valid x coordinate, and single-flag STRICTENC, LOW_S and
NULLFAIL cases.

Some policy cases were only caught by the tx_valid harness adding
flags back, which implementations copying the JSON don't replicate.
This commit is contained in:
benthecarman
2026-10-07 13:43:30 -05:00
parent aef8a04966
commit 5d2fb8d309
2 changed files with 38 additions and 1 deletions
+22 -1
View File
@@ -82,6 +82,8 @@
["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"],
["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
["0x05 0x0100000000 IFDUP", "DEPTH 2 EQUALVERIFY 0x05 0x0100000000 EQUAL", "P2SH,STRICTENC", "OK", "IFDUP dups non ints"],
["0x01 0x80 IFDUP", "DEPTH 1 EQUALVERIFY 0x01 0x80 EQUAL", "P2SH,STRICTENC", "OK", "IFDUP does not dup negative zero"],
["0x02 0x0000 IFDUP", "DEPTH 1 EQUALVERIFY 0x02 0x0000 EQUAL", "P2SH,STRICTENC", "OK", "IFDUP does not dup non-minimal zero"],
["0 DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"],
["0 1", "NIP", "P2SH,STRICTENC", "OK"],
@@ -92,6 +94,7 @@
["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"],
["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"],
["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"],
["0x01 0xaa 0x01 0xbb 0x01 0xaa 0x01 0xcc 0x01 0xaa", "2 ROLL 0x01 0xaa EQUALVERIFY 0x01 0xaa EQUALVERIFY 0x01 0xcc EQUALVERIFY 0x01 0xbb EQUALVERIFY 0x01 0xaa EQUAL", "P2SH,STRICTENC", "OK", "ROLL moves the element at depth n, not another element with the same value"],
["22 21 20", "ROT 22 EQUAL", "P2SH,STRICTENC", "OK"],
["22 21 20", "ROT DROP 20 EQUAL", "P2SH,STRICTENC", "OK"],
["22 21 20", "ROT DROP DROP 21 EQUAL", "P2SH,STRICTENC", "OK"],
@@ -685,11 +688,13 @@
["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "", "OK"],
["While not really correctly DER encoded, the empty signature is allowed by"],
["STRICTENC/DERSIG to provide a compact way to provide a deliberately invalid signature."],
["STRICTENC/DERSIG/LOW_S to provide a compact way to provide a deliberately invalid signature."],
["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC", "OK"],
["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "DERSIG", "OK"],
["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC", "OK"],
["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "DERSIG", "OK"],
["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "LOW_S", "OK"],
["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "LOW_S", "OK"],
["CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and"],
["pubkeys in a specific order, and will exit early if the number of signatures"],
@@ -1033,6 +1038,8 @@
["-2147483648", "1ADD 1", "P2SH,STRICTENC", "SCRIPTNUM", "Because we use a sign bit, -2147483648 is also 5 bytes"],
["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "SCRIPTNUM", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
["2147483648", "1SUB 1", "P2SH,STRICTENC", "SCRIPTNUM", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
["0x05 0xff00000000", "1ADD DROP 1", "P2SH,STRICTENC", "SCRIPTNUM", "We cannot do math on 5-byte integers, even if the value fits in 1 byte when minimally encoded"],
["0x09 0x000000000000000000", "1ADD DROP 1", "P2SH,STRICTENC", "SCRIPTNUM", "We cannot do math on 9-byte integers"],
["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "SCRIPTNUM", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"],
["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "SCRIPTNUM", "We cannot do BOOLAND on 5-byte integers"],
@@ -1141,6 +1148,8 @@
["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY", "Tests for Script.IsPushOnly()"],
["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY"],
["0x01 0xff 16", "16 EQUALVERIFY 0x01 0xff EQUAL", "SIGPUSHONLY", "OK", "OP_16 is a push for Script.IsPushOnly()"],
["16 0x02 0x6087", "HASH160 0x14 0x0365830433de321aea9c57d446d3b305a2bcf5be EQUAL", "P2SH,STRICTENC", "OK", "P2SH scriptSig with OP_16 is push only"],
["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED in P2SH should fail"],
["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER in P2SH should fail"],
@@ -1304,6 +1313,7 @@
[["51", 0.00000000 ], "00", "1 0x021234", "P2SH,WITNESS", "WITNESS_MALLEATED", "OP_1 does introduce a witness program"],
[["51", 0.00000000 ], "00", "16 0x021234", "P2SH,WITNESS", "WITNESS_MALLEATED", "OP_16 does introduce a witness program"],
[["51", 0.00000000 ], "", "NOP 0x021234", "P2SH,WITNESS", "WITNESS_UNEXPECTED", "NOP does not introduce a witness program"],
[["51", 0.00000000 ], "", "-1 0x021234", "P2SH", "OK", "Unexpected witness is ignored without WITNESS"],
[["6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616151", 0.00000000 ],
"",
"0 0x20 0x73a0a078cb5f8f39cffbaeac999da2572e65229ef9cf4510cfa765bfe1aa1854",
@@ -2603,6 +2613,8 @@
["CHECKSEQUENCEVERIFY tests"],
["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on an empty stack"],
["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"],
["-2", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV fails for any negative operand, even though -2 has the disable flag bit set"],
["0x09 0x000000000000000000", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "SCRIPTNUM", "CSV fails for a 9-byte operand"],
["0x0180", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "Negative zero is treated as 0, so CSV fails with UNSATISFIED_LOCKTIME rather than NEGATIVE_LOCKTIME"],
["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "SCRIPTNUM", "CSV fails if stack top is not minimally encoded"],
["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"],
@@ -2787,6 +2799,15 @@
"TAPSCRIPT: OP_CHECKSIG with empty pubkey must fail"
],
["A taproot output key that is not a valid x coordinate is not anyone-can-spend"],
[["51", "c079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 0.00000001], "", "1 0x20 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "P2SH,WITNESS,TAPROOT", "WITNESS_PROGRAM_MISMATCH", "Taproot output key is not a valid x coordinate"],
["Signature encoding checks that apply under a single policy flag"],
["0x09 0x300602010102010100", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "", "OK", "P2PK NOT with invalid sig and hashtype 0 but no STRICTENC"],
["0x09 0x300602010102010100", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "STRICTENC", "SIG_HASHTYPE", "P2PK NOT with invalid sig and hashtype 0"],
["0x09 0x300602010102010180", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT", "STRICTENC", "SIG_HASHTYPE", "P2PK NOT with invalid sig and hashtype ANYONECANPAY|0"],
["0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801", "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG", "LOW_S", "SIG_DER", "P2PK with too much R padding and only LOW_S"],
["NULLFAIL should cover all signatures and signatures only"],
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"],
["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"],
+16
View File
@@ -198,6 +198,18 @@
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "DERSIG"],
["The same transaction is invalid with only LOW_S, which also requires strict DER."],
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "LOW_S"],
["c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73 has a signature with SIGHASH type 0, which STRICTENC rejects"],
[[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]],
"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", "STRICTENC"],
["NULLFAIL applies to a CHECKMULTISIG signature that matched a key before the operation failed"],
[[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]],
"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", "NULLFAIL"],
["CHECKSEQUENCEVERIFY tests"],
["By-height locks, with argument just beyond txin.nSequence"],
@@ -224,6 +236,10 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 CHECKSEQUENCEVERIFY"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "CHECKSEQUENCEVERIFY"],
["Argument -2 with by-blockheight txin.nSequence=0, even though -2 has the disable flag bit set"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-2 CHECKSEQUENCEVERIFY"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "CHECKSEQUENCEVERIFY"],
["Argument/tx height/time mismatch, both versions"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "CHECKSEQUENCEVERIFY"],