diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1780,6 +1780,30 @@ } } + if (flags & SCRIPT_VERIFY_INPUT_SIGCHECKS) { + // This limit is intended for standard use, and is based on an + // examination of typical and historical standard uses. + // - allowing P2SH ECDSA multisig with compressed keys, which at an + // extreme (1-of-15) may have 15 SigChecks in ~590 bytes of scriptSig. + // - allowing Bare ECDSA multisig, which at an extreme (1-of-3) may have + // 3 sigchecks in ~72 bytes of scriptSig. + // - Since the size of an input is 41 bytes + length of scriptSig, then + // the most dense possible inputs satisfying this rule would be: + // 2 sigchecks and 26 bytes: 1/33.50 sigchecks/byte. + // 3 sigchecks and 69 bytes: 1/36.66 sigchecks/byte. + // The latter can be readily done with 1-of-3 bare multisignatures, + // however the former is not practically doable with standard scripts, + // so the practical density limit is 1/36.66. + static_assert(INT_MAX > MAX_SCRIPT_SIZE, + "overflow sanity check on max script size"); + static_assert(INT_MAX / 43 / 3 > MAX_OPS_PER_SCRIPT, + "overflow sanity check on maximum possible sigchecks " + "from sig+redeem+pub scripts"); + if (int(scriptSig.size()) < metrics.nSigChecks * 43 - 60) { + return set_error(serror, ScriptError::INPUT_SIGCHECKS); + } + } + metricsOut = metrics; return set_success(serror); } diff --git a/src/script/script_error.h b/src/script/script_error.h --- a/src/script/script_error.h +++ b/src/script/script_error.h @@ -19,6 +19,7 @@ STACK_SIZE, SIG_COUNT, PUBKEY_COUNT, + INPUT_SIGCHECKS, /* Operands checks */ INVALID_OPERAND_SIZE, diff --git a/src/script/script_error.cpp b/src/script/script_error.cpp --- a/src/script/script_error.cpp +++ b/src/script/script_error.cpp @@ -36,6 +36,8 @@ return "Signature count negative or greater than pubkey count"; case ScriptError::PUBKEY_COUNT: return "Pubkey count negative or limit exceeded"; + case ScriptError::INPUT_SIGCHECKS: + return "Input SigChecks limit exceeded"; case ScriptError::INVALID_OPERAND_SIZE: return "Invalid operand size"; case ScriptError::INVALID_NUMBER_RANGE: diff --git a/src/script/script_flags.h b/src/script/script_flags.h --- a/src/script/script_flags.h +++ b/src/script/script_flags.h @@ -105,6 +105,12 @@ // Whether to allow new OP_CHECKMULTISIG logic to trigger. (new multisig // logic verifies faster, and only allows Schnorr signatures) SCRIPT_ENABLE_SCHNORR_MULTISIG = (1U << 21), + + // Require the number of sigchecks in an input to satisfy a specific + // bound, defined by scriptSig length. + // Note: The Segwit Recovery feature is a (currently moot) exception to + // VERIFY_INPUT_SIGCHECKS + SCRIPT_VERIFY_INPUT_SIGCHECKS = (1U << 22), }; #endif // BITCOIN_SCRIPT_SCRIPT_FLAGS_H diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -3342,6 +3342,97 @@ "SIG_NONSCHNORR", "CHECKMULTISIG 3-of-3 Schnorr with mixed-in ECDSA signature" ], +[ + "0 0x47 0x3044022031feb7bc6e213668042b34749aa7aa99a4b40dc8ba53f872fb270442a2e69ecf0220012df792d5bc247a4ebe12f4de300d70aa768f5d9f49a5db752aef86e23f1bd501", + "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "SigChecks on bare CHECKMULTISIG 1-of-3 ECDSA" +], +[ + "0x03 0x010000 0x41 0x071da33a41ccc6ff5fcb275cae36e953e6a6092af5c8d256ca640387d36c42ae25117b502bae0881437ad0ff7db7ab23afba59fbcb03563471941733e67fb1ac01", + "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0x01 0x14 CHECKMULTISIG", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "SigChecks on bare CHECKMULTISIG 1-of-20 Schnorr" +], +[ + "0x41 0xd78d543b601bc93b394b5c669933d16d860dc7480383efcaae9521d6ceb4065ba17c02a6d9289efef762fa7a0482eff9c5bce4dd95f8bea421ee70bdd8d5488d01", + "0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKSIG", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "SigChecks on P2PK Schnorr" +], +[ + "0x47 0x30440220355bca231b5c6eac1c304ece6391404a5e8c9683f1c20749736e56f35969954302205d4af886536352ddf065407828763f3fc41755c34fd08afa4934505fd75e14ed01", + "0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 CHECKSIG", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "SigChecks on P2PK ECDSA" +], +[ + "0 0x47 0x3044022007a5b776fff5a7540301e9abbe29198575ce549333b47c90e2949c08d4ecaf8002203f8d71618b7a5cd3e99eeba0fb3c4cad4115e550ea27563d65074899d074a2d301 0x4d0102 0x51210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff46405fae", + "HASH160 0x14 0xf12c94c5293b608240ce28dc992a3ee1110926c1 EQUAL", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "SigChecks on P2SH CHECKMULTISIG 1-of-15 ECDSA with compressed keys" +], +[ + "0x44 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817980078ac78ac78ac78ac78ac78ac78ac78ac78ac78ac78ac78ac78ac78ac78ac78ac75", + "HASH160 0x14 0xe35559f8e010a9efb62973594c029ddc6f52b031 EQUAL", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "Null signatures make no SigChecks (CHECKSIG)" +], +[ + "0x47 0x00210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798000070ba70ba70ba70ba70ba70ba70ba70ba70ba70ba70ba70ba70ba70ba70ba70ba6d77", + "HASH160 0x14 0x0c01c2ac37ed03194c339b0f9915ae6acd0afeba EQUAL", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "Null signatures make no SigChecks (CHECKDATASIG)" +], +[ + "0 0 0x32 0x766e6f6f6f6f60210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798766e6f6f6f6f60ae91", + "HASH160 0x14 0x653b2bb5171f68633c8e3437d075e23640fdf4d1 EQUAL", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "Null signatures make no SigChecks (CHECKMULTISIG)" +], +[ + "0 0x47 0x304402200c90f014caff5716cd50749d52c5a4b5f1d6b79c67c96f71713f6fa3e84f3a8a02203ab681add2f4f908c41f083c982d24b62871e6c4f6eaa5d677572fc7c43c5e2201", + "1 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 DUP 4 CHECKMULTISIG", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "INPUT_SIGCHECKS", + "SigChecks on bare CHECKMULTISIG 1-of-4 ECDSA" +], +[ + "0 0x47 0x30440220418df29b58de691affb63165b3276a3932e80d56eb3392114b438f4f61fc9d2902207270492c16a9c56be78f6d926448038de44dd0de7d4ecea61f04f590be8c321401 0x4de001 0x514f210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817982103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff46405fae", + "HASH160 0x14 0x5493830eb1862c448c66236c694e2b3b37d8fd60 EQUAL", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "INPUT_SIGCHECKS", + "SigChecks on P2SH CHECKMULTISIG 1-of-15 ECDSA with a runt key" +], +[ + "0x02 0x0200 0x41 0xc33a73f6c920c95d79d4abf75a3471daac41cfb76a40a40eac752e0c522d1ce7be10d486c52aad12b1a1802f78f860d20dc6be065bebb672e641d17edc7ea7d501 0x4de001 0x514f210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817982103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464021038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff46405fae", + "HASH160 0x14 0x5493830eb1862c448c66236c694e2b3b37d8fd60 EQUAL", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "SigChecks on P2SH CHECKMULTISIG 1-of-15 Schnorr with a runt key" +], +[ + "0 0x0d 0x004f4f4f4f4f4f4f4f4f4f5aae", + "HASH160 0x14 0xa3ef8a4b54cc4437e684c5072535acbbf1f29598 EQUAL", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "Very short P2SH multisig 0-of-10, spent with legacy mode (0 sigchecks)" +], +[ + "0x02 0x0000 0x0d 0x004f4f4f4f4f4f4f4f4f4f5aae", + "HASH160 0x14 0xa3ef8a4b54cc4437e684c5072535acbbf1f29598 EQUAL", + "INPUT_SIGCHECKS,MINIMALDATA,NULLFAIL,P2SH,SCHNORR_MULTISIG,STRICTENC", + "OK", + "Very short P2SH multisig 0-of-10, spent with schnorr mode (0 sigchecks)" +], ["CHECKSEQUENCEVERIFY tests"], ["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on an empty stack"], diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -56,6 +56,7 @@ {ScriptError::STACK_SIZE, "STACK_SIZE"}, {ScriptError::SIG_COUNT, "SIG_COUNT"}, {ScriptError::PUBKEY_COUNT, "PUBKEY_COUNT"}, + {ScriptError::INPUT_SIGCHECKS, "INPUT_SIGCHECKS"}, {ScriptError::INVALID_OPERAND_SIZE, "OPERAND_SIZE"}, {ScriptError::INVALID_NUMBER_RANGE, "INVALID_NUMBER_RANGE"}, {ScriptError::IMPOSSIBLE_ENCODING, "IMPOSSIBLE_ENCODING"}, @@ -2243,6 +2244,163 @@ .PushSigSchnorr(keys.key2) .SetScriptError(ScriptError::SIG_NONSCHNORR)); + // SigChecks tests follow. We want to primarily focus on behaviour with + // the modern set of (relevant) flags. + uint32_t sigchecksflags = + SCRIPT_ENABLE_SCHNORR_MULTISIG | SCRIPT_VERIFY_NULLFAIL | + SCRIPT_VERIFY_MINIMALDATA | SCRIPT_VERIFY_STRICTENC | + SCRIPT_VERIFY_INPUT_SIGCHECKS | SCRIPT_VERIFY_P2SH; + // First, try some important use cases that we want to make sure are + // supported but that have high density of sigchecks. + tests.push_back(TestBuilder(CScript() << 1 << ToByteVector(keys.pubkey0C) + << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << 3 + << OP_CHECKMULTISIG, + "SigChecks on bare CHECKMULTISIG 1-of-3 ECDSA", + sigchecksflags) + .Num(0) + .PushSigECDSA(keys.key0)); + tests.push_back( + TestBuilder(CScript() << 1 << ToByteVector(keys.pubkey0C) << -1 << -1 + << -1 << -1 << -1 << -1 << -1 << -1 << -1 << -1 + << -1 << -1 << -1 << -1 << -1 << -1 << -1 << -1 + << -1 << 20 << OP_CHECKMULTISIG, + "SigChecks on bare CHECKMULTISIG 1-of-20 Schnorr", + sigchecksflags) + .Push("010000") + .PushSigSchnorr(keys.key0)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, + "SigChecks on P2PK Schnorr", sigchecksflags) + .PushSigSchnorr(keys.key0)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, + "SigChecks on P2PK ECDSA", sigchecksflags) + .PushSigECDSA(keys.key0)); + tests.push_back( + TestBuilder( + CScript() + << 1 << ToByteVector(keys.pubkey0C) + << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) + << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) + << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) + << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) + << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) + << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) + << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) + << 15 << OP_CHECKMULTISIG, + "SigChecks on P2SH CHECKMULTISIG 1-of-15 ECDSA with compressed " + "keys", + sigchecksflags, true) + .Num(0) + .PushSigECDSA(keys.key0) + .PushRedeem()); + tests.push_back( + TestBuilder(CScript() + << ToByteVector(keys.pubkey0C) << 0 << OP_OVER + << OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER + << OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER + << OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER + << OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER + << OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER + << OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER + << OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_OVER + << OP_CHECKSIG << OP_OVER << OP_CHECKSIG << OP_DROP, + "Null signatures make no SigChecks (CHECKSIG)", + sigchecksflags, true) + .PushRedeem()); + tests.push_back( + TestBuilder(CScript() + << 0 << ToByteVector(keys.pubkey0C) << 0 << 0 + << OP_2OVER << OP_CHECKDATASIG << OP_2OVER + << OP_CHECKDATASIG << OP_2OVER << OP_CHECKDATASIG + << OP_2OVER << OP_CHECKDATASIG << OP_2OVER + << OP_CHECKDATASIG << OP_2OVER << OP_CHECKDATASIG + << OP_2OVER << OP_CHECKDATASIG << OP_2OVER + << OP_CHECKDATASIG << OP_2OVER << OP_CHECKDATASIG + << OP_2OVER << OP_CHECKDATASIG << OP_2OVER + << OP_CHECKDATASIG << OP_2OVER << OP_CHECKDATASIG + << OP_2OVER << OP_CHECKDATASIG << OP_2OVER + << OP_CHECKDATASIG << OP_2OVER << OP_CHECKDATASIG + << OP_2OVER << OP_CHECKDATASIG << OP_2DROP << OP_NIP, + "Null signatures make no SigChecks (CHECKDATASIG)", + sigchecksflags, true) + .PushRedeem()); + // Note that the following test case is "legacy-only", there is no schnorr + // counterpart since schnorr mode does not permit any null signatures nor + // an incorrect popcount in checkbits. + tests.push_back( + TestBuilder(CScript() + << OP_DUP << OP_2DUP << OP_3DUP << OP_3DUP << OP_3DUP + << OP_3DUP << 16 << ToByteVector(keys.pubkey0C) + << OP_DUP << OP_2DUP << OP_3DUP << OP_3DUP << OP_3DUP + << OP_3DUP << 16 << OP_CHECKMULTISIG << OP_NOT, + "Null signatures make no SigChecks (CHECKMULTISIG)", + sigchecksflags, true) + .Num(0) + .Num(0) + .PushRedeem()); + + // Now some unusual use cases (some are unsupported behaviour) + tests.push_back(TestBuilder(CScript() << 1 << ToByteVector(keys.pubkey0C) + << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) + << OP_DUP << 4 << OP_CHECKMULTISIG, + "SigChecks on bare CHECKMULTISIG 1-of-4 ECDSA", + sigchecksflags) + .Num(0) + .PushSigECDSA(keys.key0) + .SetScriptError(ScriptError::INPUT_SIGCHECKS)); + tests.push_back( + TestBuilder( + CScript() + << 1 << -1 << ToByteVector(keys.pubkey0C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << 15 << OP_CHECKMULTISIG, + "SigChecks on P2SH CHECKMULTISIG 1-of-15 ECDSA with a runt key", + sigchecksflags, true) + .Num(0) + .PushSigECDSA(keys.key0) + .PushRedeem() + .SetScriptError(ScriptError::INPUT_SIGCHECKS)); + tests.push_back( + TestBuilder( + CScript() + << 1 << -1 << ToByteVector(keys.pubkey0C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << 15 << OP_CHECKMULTISIG, + "SigChecks on P2SH CHECKMULTISIG 1-of-15 Schnorr with a runt key", + sigchecksflags, true) + .Push("0200") + .PushSigSchnorr(keys.key0) + .PushRedeem()); + tests.push_back(TestBuilder(CScript() << 0 << -1 << -1 << -1 << -1 << -1 + << -1 << -1 << -1 << -1 << -1 << 10 + << OP_CHECKMULTISIG, + "Very short P2SH multisig 0-of-10, spent with " + "legacy mode (0 sigchecks)", + sigchecksflags, true) + .Num(0) + .PushRedeem()); + tests.push_back(TestBuilder(CScript() << 0 << -1 << -1 << -1 << -1 << -1 + << -1 << -1 << -1 << -1 << -1 << 10 + << OP_CHECKMULTISIG, + "Very short P2SH multisig 0-of-10, spent with " + "schnorr mode (0 sigchecks)", + sigchecksflags, true) + .Push("0000") + .PushRedeem()); + std::set tests_set; { diff --git a/src/test/scriptflags.cpp b/src/test/scriptflags.cpp --- a/src/test/scriptflags.cpp +++ b/src/test/scriptflags.cpp @@ -33,6 +33,7 @@ {"CHECKDATASIG", SCRIPT_VERIFY_CHECKDATASIG_SIGOPS}, {"DISALLOW_SEGWIT_RECOVERY", SCRIPT_DISALLOW_SEGWIT_RECOVERY}, {"SCHNORR_MULTISIG", SCRIPT_ENABLE_SCHNORR_MULTISIG}, + {"INPUT_SIGCHECKS", SCRIPT_VERIFY_INPUT_SIGCHECKS}, }; uint32_t ParseScriptFlags(std::string strFlags) {