diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1020,8 +1020,11 @@ CleanupScriptCode(scriptCode, vchSig, flags); } + const uint32_t msigflags = + flags & ~SCRIPT_ENABLE_SCHNORR; bool fSuccess = true; while (fSuccess && nSigsCount > 0) { + valtype &vchSig = stacktop(-isig); valtype &vchPubKey = stacktop(-ikey); @@ -1030,8 +1033,8 @@ // CHECKMULTISIG NOT if the STRICTENC flag is set. // See the script_(in)valid tests for details. if (!CheckTransactionSignatureEncoding( - vchSig, flags, serror) || - !CheckPubKeyEncoding(vchPubKey, flags, + vchSig, msigflags, serror) || + !CheckPubKeyEncoding(vchPubKey, msigflags, serror)) { // serror is set return false; @@ -1039,7 +1042,7 @@ // Check signature bool fOk = checker.CheckSig(vchSig, vchPubKey, - scriptCode, flags); + scriptCode, msigflags); if (fOk) { isig++; @@ -1467,7 +1470,11 @@ const CPubKey &pubkey, const uint256 &sighash, uint32_t flags) const { - return pubkey.VerifyECDSA(sighash, vchSig); + if ((flags & SCRIPT_ENABLE_SCHNORR) && (vchSig.size() == 64)) { + return pubkey.VerifySchnorr(sighash, vchSig); + } else { + return pubkey.VerifyECDSA(sighash, vchSig); + } } bool TransactionSignatureChecker::CheckSig( diff --git a/src/script/sigencoding.cpp b/src/script/sigencoding.cpp --- a/src/script/sigencoding.cpp +++ b/src/script/sigencoding.cpp @@ -155,6 +155,10 @@ static bool CheckRawSignatureEncoding(const slicedvaltype &sig, uint32_t flags, ScriptError *serror) { + if ((flags & SCRIPT_ENABLE_SCHNORR) && (sig.size() == 64)) { + // Schnorr signatures have no ambiguity over encoding. + return true; + } if ((flags & (SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC)) && !IsValidSignatureEncoding(sig)) { 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 @@ -2660,6 +2660,391 @@ "PUBKEYTYPE", "CHECKDATASIGVERIFY with invalid hybrid pubkey" ], +[ + "0x41 0x0df4be7f5fe74b2855b92082720e889038e15d8d747334fa3f300ef4ab1db1eea56aa83d1d60809ff6703791736be87cfb6cbc5c4036aeed3b4ea4e6dab3509001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "SCHNORR", + "OK", + "Schnorr P2PK" +], +[ + "0x41 0x0df4be7f5fe74b2855b92082720e889038e15d8d747334fa3f300ef4ab1db1eea56aa83d1d60809ff6703791736be87cfb6cbc5c4036aeed3b4ea4e6dab3509001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "", + "EVAL_FALSE", + "Schnorr P2PK disabled" +], +[ + "0x41 0x0df4be7f5fe74b2855b92082720e889038e15d8d747334fa3f300ef4ab1db1eea56aa83d1d60809ff6703791736be87cfb6cbc5c4036aeed3b4ea4e6dab3509001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "STRICTENC", + "SIG_DER", + "Schnorr P2PK disabled with STRICTENC" +], +[ + "0x41 0x0df4be7f5fe74b2855b92182720e889038e15d8d747334fa3f300ef4ab1db1eea56aa83d1d60809ff6703791736be87cfb6cbc5c4036aeed3b4ea4e6dab3509001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "SCHNORR", + "EVAL_FALSE", + "Schnorr P2PK, bad sig" +], +[ + "0x41 0x4463c103b21e76713571365c4c09224c2a1b343b3cf02e3b56f4f0890a6e7ff96d0bfa2ffa22f8067db3414cc1789abfc48638cb4bc7463907042975f4c84ece01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", + "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG", + "SCHNORR", + "OK", + "Schnorr P2PKH" +], +[ + "0x41 0x4463c103b21e76713571365c4c09224c2a1b343b3cf02e3b56f4f0890a6e7ff96d0bfa2ffa22f8067db3414cc1789abfc48638cb4bc7463907042975f4c84ece01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508", + "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG", + "", + "EVAL_FALSE", + "Schnorr P2PKH disabled" +], +[ + "0x41 0x4723c8bf3cc21309f431a974c93e219b366a2e1af762a4528de7cb1ad775e2a97b93a2c4506e50b81fbec8601b9468bc3619f729303d6679a7b96fca7eba44ed01 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640", + "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG", + "SCHNORR", + "EQUALVERIFY", + "Schnorr P2PKH, bad pubkey" +], +[ + "0x41 0x16c29e0eee68fac2e43aa8702eab218ff3a19b28c138352cd2f5934c088c92871115fb32a82afaee7cfbc7bcf9118fdf7deeccc547d6cb0f5b7bab88ff03ca7901 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", + "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", + "P2SH,SCHNORR", + "OK", + "Schnorr P2SH(P2PK)" +], +[ + "0x41 0x16c29e0eee68fac2e43aa8702eab218ff3a19b28c138352cd2f5934c088c92871115fb32a82afaee7cfbc7bcf9118fdf7deeccc547d6cb0f5b7bab88ff03ca7901 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", + "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", + "P2SH", + "EVAL_FALSE", + "Schnorr P2SH(P2PK) disabled" +], +[ + "0x41 0x16c29e0eee68fac2e43aa8702eab218ff3a19b28c138352cd2f5934c088c92871115fb32a82afaee7cfbc7bcf9118fdf7deeccc547d6cb0f5b7bab88ff03ca7901 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac", + "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL", + "P2SH,SCHNORR", + "EVAL_FALSE", + "Schnorr P2SH(P2PK), bad redeemscript" +], +[ + "0x41 0xef2b7ff608e8e6ec6c0a7247c78baa13e1bfeaed0a40b6cc4b084e0b251d24cdba76eb73a657592c77d0ad0e4194d293bbbb5dbe13caa5a828d19209c3ef998301 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x19 0x76a91491b24bf9f5288532960ac687abb035127b1d28a588ac", + "HASH160 0x14 0x7f67f0521934a57d3039f77f9f32cf313f3ac74b EQUAL", + "P2SH,SCHNORR", + "OK", + "Schnorr P2SH(P2PKH)" +], +[ + "0x41 0xef2b7ff608e8e6ec6c0a7247c78baa13e1bfeaed0a40b6cc4b084e0b251d24cdba76eb73a657592c77d0ad0e4194d293bbbb5dbe13caa5a828d19209c3ef998301 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x19 0x76a91491b24bf9f5288532960ac687abb035127b1d28a588ac", + "HASH160 0x14 0x7f67f0521934a57d3039f77f9f32cf313f3ac74b EQUAL", + "P2SH", + "EVAL_FALSE", + "Schnorr P2SH(P2PKH) disabled" +], +[ + "0 0x41 0x833682d4f60cc916a22a2c263e658fa662c49badb1e2a8c6208987bf99b1abd740498371480069e7a7a6e7471bf78c27bd9a1fd04fb212a92017346250ac187b01 0x41 0xea4a8d20562a950f4695dc24804565482e9fa111704886179d0c348f2b8a15fe691a305cd599c59c131677146661d5b98cb935330989a85f33afc70d0a21add101 0x41 0xce9011d76a4df05d6280b2382b4d91490dbec7c3e72dc826be1fc9b4718f627955190745cac96521ea46d6d324c7376461e225310e6cd605b9f266d170769b7901", + "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", + "SCHNORR", + "EVAL_FALSE", + "Schnorr 3-of-3 illegal" +], +[ + "0 0x47 0x304402204d69d5caa4dbab259f79fce89d3b459bbd91697c1c052a1554ff3b08b2241cbd0220330a8e17a90d51996e363cb8902fce6278c6350fa59ae12832db2f6a44d64dce01 0x47 0x3044022031a1e5289b0d9c33ec182a7f67210b9997187c710f7d3f0f28bdfb618c4e025c02205d95fe63ee83a20ec44159a06f7c0b43b61d5f0c346ca4a2cc7b91878ad1a85001 0x41 0xce9011d76a4df05d6280b2382b4d91490dbec7c3e72dc826be1fc9b4718f627955190745cac96521ea46d6d324c7376461e225310e6cd605b9f266d170769b7901", + "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG", + "SCHNORR", + "EVAL_FALSE", + "Schnorr-mixed 3-of-3 illegal" +], +[ + "0 0x41 0xe34369c1b4227166cf44e161798a962f543de9c0d27b95d92a7b1dd27f97fa935487e3c34af2b3e2f8898cd56a44b461361d96c6a6b3e4c3f17188802075258801 0x41 0x5fbb9b73c4c2cc61b69eac5a84443a56e58bfc20c1fb82da71479dd77a163c2ce9510d122c8f09df94da7e5db506111f7b4596cd94b1089c64d2dca92272804d01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae", + "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL", + "P2SH,SCHNORR", + "EVAL_FALSE", + "Schnorr P2SH(2-of-3) illegal" +], +[ + "0 0x47 0x304402202664735419fa841ee49930f4263d21a3320f7f72873dce81da4f77ea63a8532002206aa7f5d615dfb7e495dafb13751271ec1fc44a6c914ba8fda63289b21e29a70c01", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "", + "OK", + "ECDSA 1-of-1" +], +[ + "0 0x47 0x304402202664735419fa841ee49930f4263d21a3320f7f72873dce81da4f77ea63a8532002206aa7f5d615dfb7e495dafb13751271ec1fc44a6c914ba8fda63289b21e29a70c01", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "SCHNORR", + "OK", + "ECDSA 1-of-1 with schnorr flag" +], +[ + "0 0x41 0x3ec2f999be1f7ba3b5a5080c449af69f86e4ecfa93b8fb8d4436f43de6031db01978d76d51436cb1f822806707d0200c3b203fd75f22404a20f28b29a564e91601", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "SCHNORR", + "EVAL_FALSE", + "Schnorr 1-of-1 illegal" +], +[ + "0 0x41 0x3ec2f999be1f7ba3b5a5080c449af69f86e4ecfa93b8fb8d4436f43de6031db01978d76d51436cb1f822806707d0200c3b203fd75f22404a20f28b29a564e91601", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "", + "EVAL_FALSE", + "Schnorr 1-of-1 illegal disabled" +], +[ + "0 0x41 0x3ec2f999be1f7ba3b5a5080c449af69f86e4ecfa93b8fb8d4436f43de6031db01978d76d51436cb1f822806707d0200c3b203fd75f22404a20f28b29a564e91601", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "SCHNORR,STRICTENC", + "SIG_DER", + "Schnorr 1-of-1 illegal with STRICTENC" +], +[ + "0 0x41 0x3ec2f999be1f7ba3b5a5080c449af69f86e4ecfa93b8fb8d4436f43de6031db01978d76d51436cb1f822806707d0200c3b203fd75f22404a20f28b29a564e91601", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "STRICTENC", + "SIG_DER", + "Schnorr 1-of-1 illegal disabled with STRICTENC" +], +[ + "0x41 0xd211631fdebf4c8376b3d169ef65a1987460eda43c3312e561b0226fa3069f68a68bac0dbf780f77dd60ff602c66186f1da2bb0a31f10187796242f48295ddbe01", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "SCHNORR", + "OK", + "Schnorr P2PK with hybrid pubkey but no STRICTENC" +], +[ + "0x41 0xd211631fdebf4c8376b3d169ef65a1987460eda43c3312e561b0226fa3069f68a68bac0dbf780f77dd60ff602c66186f1da2bb0a31f10187796242f48295ddbe01", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "SCHNORR,STRICTENC", + "PUBKEYTYPE", + "Schnorr P2PK with hybrid pubkey" +], +[ + "0x41 0x078b6b4e7d0689f3a1ef9b5283039c39b7ab3a26c04143017ee7136edbc1ccbcf47173c92c5823b778e4aaba3bf9ef2e988eb54c4cb709dbfa8e62110843c19901", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT", + "SCHNORR", + "OK", + "Schnorr P2PK NOT with invalid hybrid pubkey but no STRICTENC" +], +[ + "0x41 0xa522c6aab80595e0fdaf473c89a32e97978858809949fafd6f851254daae231f45338fe53187f79d8507f08c08f8bd2ee795e6ccaca0a04c4e40c613395a685b05", + "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG", + "SCHNORR,STRICTENC", + "SIG_HASHTYPE", + "Schnorr P2PK with undefined hashtype" +], +[ + "0x41 0x128f02ec5b36057a7f3793c5ffdef9e6cca0ea3200a2f07e5c7189a267daafc4feb2b65a8c7f22b203557fef4c078e98382dc99939666b7c6dbcc62bd25b0bf821 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "DUP HASH160 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5 EQUALVERIFY CHECKSIG", + "SCHNORR", + "OK", + "Schnorr P2PKH with invalid sighashtype" +], +[ + "0x41 0x128f02ec5b36057a7f3793c5ffdef9e6cca0ea3200a2f07e5c7189a267daafc4feb2b65a8c7f22b203557fef4c078e98382dc99939666b7c6dbcc62bd25b0bf821 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "DUP HASH160 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5 EQUALVERIFY CHECKSIG", + "SCHNORR,STRICTENC", + "SIG_HASHTYPE", + "Schnorr P2PKH with invalid sighashtype and STRICTENC" +], +[ + "0x40 0x65c4bceda6ebb49e692180387e72c84be500f3431daac85d08d5d6c527e296f5b8a5b868a681f76aee309ad05e152b4f190732b3e7c46ef788b68c6035f6eab0 0", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", + "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", + "OK", + "Schnorr Standard CHECKDATASIG" +], +[ + "0x40 0x65c4bceda6ebb49e692180387e72c84be500f3431daac85d08d5d6c527e296f5b8a5b868a681f76aee309ad05e152b4f190732b3e7c46ef788b68c6035f6eab0 0", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", + "CHECKDATASIG,NULLFAIL,STRICTENC", + "SIG_DER", + "Schnorr Standard CHECKDATASIG disabled" +], +[ + "0x40 0x65c4bceda6ebb49e692180387e72c84be500f3431daac85d08d5d6c527e296f5b8a5b868a681f76aee309ad05e152b4f190732b3e7c46ef788b68c6035f6eab0 0", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIG", + "CHECKDATASIG", + "EVAL_FALSE", + "Schnorr Standard CHECKDATASIG disabled but no NULLFAIL/STRICTENC" +], +[ + "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5 0", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", + "CHECKDATASIG,NULLFAIL,SCHNORR", + "OK", + "Schnorr CHECKDATASIG with hybrid pubkey but no STRICTENC" +], +[ + "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5 0", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", + "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", + "PUBKEYTYPE", + "Schnorr CHECKDATASIG with hybrid pubkey" +], +[ + "0x40 0x9db0671f61f1fafa84aaaa76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5 0", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG NOT", + "CHECKDATASIG,SCHNORR", + "OK", + "Schnorr CHECKDATASIG with invalid hybrid pubkey but no STRICTENC" +], +[ + "0x40 0x9db0671f61f1fafa84aaaa76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5 0", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIG", + "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", + "PUBKEYTYPE", + "Schnorr CHECKDATASIG with invalid hybrid pubkey" +], +[ + "0x40 0x65c4bceda6ebb49e692180387e72c84be500f3431daac85d08d5d6c527e296f5b8a5b868a681f76aee309ad05e152b4f190732b3e7c46ef788b68c6035f6eab0 0", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY 1", + "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", + "OK", + "Schnorr Standard CHECKDATASIGVERIFY" +], +[ + "0x40 0x65c4bceda6ebb49e692180387e72c84be500f3431daac85d08d5d6c527e296f5b8a5b868a681f76aee309ad05e152b4f190732b3e7c46ef788b68c6035f6eab0 0", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY", + "CHECKDATASIG,NULLFAIL,STRICTENC", + "SIG_DER", + "Schnorr Standard CHECKDATASIGVERIFY disabled" +], +[ + "0x40 0x65c4bceda6ebb49e692180387e72c84be500f3431daac85d08d5d6c527e296f5b8a5b868a681f76aee309ad05e152b4f190732b3e7c46ef788b68c6035f6eab0 0", + "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKDATASIGVERIFY", + "CHECKDATASIG", + "CHECKDATASIGVERIFY", + "Schnorr Standard CHECKDATASIGVERIFY disabled but no NULLFAIL/STRICTENC" +], +[ + "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5 0", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", + "CHECKDATASIG,NULLFAIL,SCHNORR", + "OK", + "Schnorr CHECKDATASIGVERIFY with hybrid pubkey but no STRICTENC" +], +[ + "0x40 0x9db0671f61f1fafa84aaab76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5 0", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", + "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", + "PUBKEYTYPE", + "Schnorr CHECKDATASIGVERIFY with hybrid pubkey" +], +[ + "0x40 0x9db0671f61f1fafa84aaaa76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5 0", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", + "CHECKDATASIG,SCHNORR", + "CHECKDATASIGVERIFY", + "Schnorr CHECKDATASIGVERIFY with invalid hybrid pubkey but no STRICTENC" +], +[ + "0x40 0x9db0671f61f1fafa84aaaa76ad2e070b27cf9ae85338bafc0b947ac9ad8c56ff7b24aa76c95ad86bb13cbff314742dbe1f545869d1a28efa54b411ccd37717e5 0", + "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKDATASIGVERIFY 1", + "CHECKDATASIG,NULLFAIL,SCHNORR,STRICTENC", + "PUBKEYTYPE", + "Schnorr CHECKDATASIGVERIFY with invalid hybrid pubkey" +], +[ + "0x41 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c630220658fee074680c1bcde4c8eb9a5d03537ddf6ae0e1b96add34b97c047416803d4000000000001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "", + "OK", + "64+1-byte ECDSA P2PK" +], +[ + "0x41 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c630220658fee074680c1bcde4c8eb9a5d03537ddf6ae0e1b96add34b97c047416803d4000000000001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "STRICTENC", + "SIG_DER", + "64+1-byte ECDSA P2PK strict" +], +[ + "0x40 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c630220658fee074680c1bcde4c8eb9a5d03537ddf6ae0e1b96add34b97c047416803d40000000001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "SCHNORR", + "OK", + "63+1-byte ECDSA P2PK with Schnorr flag" +], +[ + "0x41 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c630220658fee074680c1bcde4c8eb9a5d03537ddf6ae0e1b96add34b97c047416803d4000000000001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "SCHNORR", + "EVAL_FALSE", + "64+1-byte ECDSA P2PK with Schnorr flag" +], +[ + "0x42 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c630220658fee074680c1bcde4c8eb9a5d03537ddf6ae0e1b96add34b97c047416803d400000000000001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "SCHNORR", + "OK", + "65+1-byte ECDSA P2PK with Schnorr flag" +], +[ + "0x41 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c630220658fee074680c1bcde4c8eb9a5d03537ddf6ae0e1b96add34b97c047416803d4000000000001", + "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", + "SCHNORR,STRICTENC", + "EVAL_FALSE", + "64+1-byte ECDSA P2PK strict with Schnorr" +], +[ + "0 0x40 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c6302205db8cf378ea529068e2d3f43be88c3f1e83a96aecebed07165b00102d7b5543c0000000001", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "", + "OK", + "63+1-byte ECDSA 1-of-1" +], +[ + "0 0x41 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c6302205db8cf378ea529068e2d3f43be88c3f1e83a96aecebed07165b00102d7b5543c000000000001", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "", + "OK", + "64+1-byte ECDSA 1-of-1" +], +[ + "0 0x42 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c6302205db8cf378ea529068e2d3f43be88c3f1e83a96aecebed07165b00102d7b5543c00000000000001", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "", + "OK", + "65+1-byte ECDSA 1-of-1" +], +[ + "0 0x40 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c6302205db8cf378ea529068e2d3f43be88c3f1e83a96aecebed07165b00102d7b5543c0000000001", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "SCHNORR", + "OK", + "63+1-byte ECDSA 1-of-1 with schnorr flag" +], +[ + "0 0x41 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c6302205db8cf378ea529068e2d3f43be88c3f1e83a96aecebed07165b00102d7b5543c000000000001", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "SCHNORR", + "OK", + "64+1-byte ECDSA 1-of-1 with schnorr flag" +], +[ + "0 0x42 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c6302205db8cf378ea529068e2d3f43be88c3f1e83a96aecebed07165b00102d7b5543c00000000000001", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "SCHNORR", + "OK", + "65+1-byte ECDSA 1-of-1 with schnorr flag" +], +[ + "0 0x41 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c6302205db8cf378ea529068e2d3f43be88c3f1e83a96aecebed07165b00102d7b5543c000000000001", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "STRICTENC", + "SIG_DER", + "64+1-byte ECDSA 1-of-1 strict" +], +[ + "0 0x41 0x303902153b78ce563f89a0ed9414f5aa28ad0d96d6795f9c6302205db8cf378ea529068e2d3f43be88c3f1e83a96aecebed07165b00102d7b5543c000000000001", + "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 1 CHECKMULTISIG", + "SCHNORR,STRICTENC", + "SIG_DER", + "64+1-byte ECDSA 1-of-1 strict with schnorr flag" +], ["CHECKSEQUENCEVERIFY tests"], ["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a 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 @@ -233,6 +233,50 @@ } }; +#include +extern "C" { +/* + * nonce function that always returns + * k = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1. + * this nonce is special since kG is the point: + * x = 0x00000000000000000000003b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63 + * y = 0xc0c686408d517dfd67c2367651380d00d126e4229631fd03f8ff35eef1a61e3c + * This lets us make really short ECDSA signatures (~60 bytes) which can be + * beefed up to ~64 bytes by padding garbage at the end. + */ +static int nonce_function_half(unsigned char *nonce32, + const unsigned char *msg32, + const unsigned char *key32, + const unsigned char *algo16, void *data, + unsigned int counter) { + unsigned char noncehalf[32] = { + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0x57, 0x6e, 0x73, 0x57, 0xa4, + 0x50, 0x1d, 0xdf, 0xe9, 0x2f, 0x46, 0x68, 0x1b, 0x20, 0xa1}; + memcpy(nonce32, noncehalf, 32); + return 1; +} +} + +// create short ECDSA signature (<=60 bytes) using above nonce trick +// (based on CKey::SignECDSA) +bool SignECDSA_short(const CKey &key, const uint256 &hash, + std::vector &vchSig) { + vchSig.resize(72); + size_t nSigLen = 72; + secp256k1_ecdsa_signature sig; + secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + int ret = secp256k1_ecdsa_sign(ctx, &sig, hash.begin(), key.begin(), + nonce_function_half, nullptr); + secp256k1_context_destroy(ctx); + assert(ret); + secp256k1_ecdsa_signature_serialize_der(ctx, (uint8_t *)&vchSig[0], + &nSigLen, &sig); + assert(nSigLen <= 60); + vchSig.resize(nSigLen); + return true; +} + class TestBuilder { private: //! Actually executed script @@ -265,6 +309,14 @@ unsigned int lenR = 32, unsigned int lenS = 32) const { std::vector vchSig, r, s; + if (lenR == 21) { + // use above hack to make valid short R + SignECDSA_short(key, hash, vchSig); + // pad it to be length 6 + lenR + lenS -- this leaves garbage at + // end but ecdsa_signature_parse_der_lax doesn't care. + vchSig.resize(6 + lenR + lenS); + return vchSig; + } uint32_t iter = 0; do { key.SignECDSA(hash, vchSig, iter++); @@ -282,6 +334,16 @@ return vchSig; } + std::vector DoSignSchnorr(const CKey &key, + const uint256 &hash) const { + std::vector vchSig; + + // no need to iterate for size; schnorrs are always same size. + key.SignSchnorr(hash, vchSig); + + return vchSig; + } + public: TestBuilder(const CScript &script_, const std::string &comment_, uint32_t flags_, bool P2SH = false, @@ -345,6 +407,18 @@ return *this; } + TestBuilder & + PushSigSchnorr(const CKey &key, SigHashType sigHashType = SigHashType(), + Amount amount = Amount::zero(), + uint32_t sigFlags = SCRIPT_ENABLE_SIGHASH_FORKID) { + uint256 hash = SignatureHash(script, CTransaction(spendTx), 0, + sigHashType, amount, nullptr, sigFlags); + std::vector vchSig = DoSignSchnorr(key, hash); + vchSig.push_back(static_cast(sigHashType.getRawSigHashType())); + DoPush(vchSig); + return *this; + } + TestBuilder &PushDataSig(const CKey &key, const std::vector &data, unsigned int lenR = 32, unsigned int lenS = 32) { std::vector vchHash(32); @@ -354,6 +428,15 @@ return *this; } + TestBuilder &PushDataSigSchnorr(const CKey &key, + const std::vector &data) { + std::vector vchHash(32); + CSHA256().Write(data.data(), data.size()).Finalize(vchHash.data()); + + DoPush(DoSignSchnorr(key, uint256(vchHash))); + return *this; + } + TestBuilder &Push(const CPubKey &pubkey) { DoPush(std::vector(pubkey.begin(), pubkey.end())); return *this; @@ -1531,6 +1614,403 @@ .Num(0) .ScriptError(SCRIPT_ERR_PUBKEYTYPE)); + /* + * Tests that have Schnorr signatures in them: + */ + + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Schnorr P2PK", SCRIPT_ENABLE_SCHNORR) + .PushSigSchnorr(keys.key0)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Schnorr P2PK disabled", 0) + .PushSigSchnorr(keys.key0) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Schnorr P2PK disabled with STRICTENC", + SCRIPT_VERIFY_STRICTENC) + .PushSigSchnorr(keys.key0) + .ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Schnorr P2PK, bad sig", SCRIPT_ENABLE_SCHNORR) + .PushSigSchnorr(keys.key0) + .DamagePush(10) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 + << ToByteVector(keys.pubkey1C.GetID()) + << OP_EQUALVERIFY << OP_CHECKSIG, + "Schnorr P2PKH", SCRIPT_ENABLE_SCHNORR) + .PushSigSchnorr(keys.key1) + .Push(keys.pubkey1C)); + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 + << ToByteVector(keys.pubkey1C.GetID()) + << OP_EQUALVERIFY << OP_CHECKSIG, + "Schnorr P2PKH disabled", 0) + .PushSigSchnorr(keys.key1) + .Push(keys.pubkey1C) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 + << ToByteVector(keys.pubkey2C.GetID()) + << OP_EQUALVERIFY << OP_CHECKSIG, + "Schnorr P2PKH, bad pubkey", + SCRIPT_ENABLE_SCHNORR) + .PushSigSchnorr(keys.key2) + .Push(keys.pubkey2C) + .DamagePush(5) + .ScriptError(SCRIPT_ERR_EQUALVERIFY)); + + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, + "Schnorr P2SH(P2PK)", + SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SCHNORR, true) + .PushSigSchnorr(keys.key0) + .PushRedeem()); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, + "Schnorr P2SH(P2PK) disabled", SCRIPT_VERIFY_P2SH, true) + .PushSigSchnorr(keys.key0) + .PushRedeem() + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, + "Schnorr P2SH(P2PK), bad redeemscript", + SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SCHNORR, true) + .PushSigSchnorr(keys.key0) + .PushRedeem() + .DamagePush(10) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 + << ToByteVector(keys.pubkey0.GetID()) + << OP_EQUALVERIFY << OP_CHECKSIG, + "Schnorr P2SH(P2PKH)", + SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SCHNORR, + true) + .PushSigSchnorr(keys.key0) + .Push(keys.pubkey0) + .PushRedeem()); + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 + << ToByteVector(keys.pubkey0.GetID()) + << OP_EQUALVERIFY << OP_CHECKSIG, + "Schnorr P2SH(P2PKH) disabled", + SCRIPT_VERIFY_P2SH, true) + .PushSigSchnorr(keys.key0) + .Push(keys.pubkey0) + .PushRedeem() + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) + << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << OP_3 + << OP_CHECKMULTISIG, + "Schnorr 3-of-3 illegal", SCRIPT_ENABLE_SCHNORR) + .Num(0) + .PushSigSchnorr(keys.key0) + .PushSigSchnorr(keys.key1) + .PushSigSchnorr(keys.key2) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) + << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << OP_3 + << OP_CHECKMULTISIG, + "Schnorr-mixed 3-of-3 illegal", + SCRIPT_ENABLE_SCHNORR) + .Num(0) + .PushSig(keys.key0) + .PushSig(keys.key1) + .PushSigSchnorr(keys.key2) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) + << ToByteVector(keys.pubkey1C) + << ToByteVector(keys.pubkey2C) << OP_3 + << OP_CHECKMULTISIG, + "Schnorr P2SH(2-of-3) illegal", + SCRIPT_VERIFY_P2SH | SCRIPT_ENABLE_SCHNORR, + true) + .Num(0) + .PushSigSchnorr(keys.key1) + .PushSigSchnorr(keys.key2) + .PushRedeem() + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "ECDSA 1-of-1", 0) + .Num(0) + .PushSig(keys.key1)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "ECDSA 1-of-1 with schnorr flag", + SCRIPT_ENABLE_SCHNORR) + .Num(0) + .PushSig(keys.key1)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "Schnorr 1-of-1 illegal", SCRIPT_ENABLE_SCHNORR) + .Num(0) + .PushSigSchnorr(keys.key1) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "Schnorr 1-of-1 illegal disabled", 0) + .Num(0) + .PushSigSchnorr(keys.key1) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "Schnorr 1-of-1 illegal with STRICTENC", + SCRIPT_ENABLE_SCHNORR | SCRIPT_VERIFY_STRICTENC) + .Num(0) + .PushSigSchnorr(keys.key1) + .ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back( + TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << OP_1 + << OP_CHECKMULTISIG, + "Schnorr 1-of-1 illegal disabled with STRICTENC", + SCRIPT_VERIFY_STRICTENC) + .Num(0) + .PushSigSchnorr(keys.key1) + .ScriptError(SCRIPT_ERR_SIG_DER)); + + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG, + "Schnorr P2PK with hybrid pubkey but no STRICTENC", + SCRIPT_ENABLE_SCHNORR) + .PushSigSchnorr(keys.key0)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG, + "Schnorr P2PK with hybrid pubkey", + SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) + .PushSigSchnorr(keys.key0, SigHashType()) + .ScriptError(SCRIPT_ERR_PUBKEYTYPE)); + tests.push_back( + TestBuilder( + CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT, + "Schnorr P2PK NOT with invalid hybrid pubkey but no STRICTENC", + SCRIPT_ENABLE_SCHNORR) + .PushSigSchnorr(keys.key0) + .DamagePush(10)); + + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "Schnorr P2PK with undefined hashtype", + SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) + .PushSigSchnorr(keys.key1, SigHashType(5)) + .ScriptError(SCRIPT_ERR_SIG_HASHTYPE)); + + tests.push_back( + TestBuilder(CScript() << OP_DUP << OP_HASH160 + << ToByteVector(keys.pubkey0.GetID()) + << OP_EQUALVERIFY << OP_CHECKSIG, + "Schnorr P2PKH with invalid sighashtype", + SCRIPT_ENABLE_SCHNORR) + .PushSigSchnorr(keys.key0, SigHashType(0x21), Amount::zero(), 0) + .Push(keys.pubkey0)); + tests.push_back( + TestBuilder(CScript() << OP_DUP << OP_HASH160 + << ToByteVector(keys.pubkey0.GetID()) + << OP_EQUALVERIFY << OP_CHECKSIG, + "Schnorr P2PKH with invalid sighashtype and STRICTENC", + SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) + .PushSigSchnorr(keys.key0, SigHashType(0x21), Amount::zero(), + SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) + .Push(keys.pubkey0) + // Should fail for STRICTENC + .ScriptError(SCRIPT_ERR_SIG_HASHTYPE)); + + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG, + "Schnorr Standard CHECKDATASIG", checkdatasigschnorrflags) + .PushDataSigSchnorr(keys.key1, {}) + .Num(0)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG, + "Schnorr Standard CHECKDATASIG disabled", checkdatasigflags) + .PushDataSigSchnorr(keys.key1, {}) + .Num(0) + .ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back( + TestBuilder( + CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKDATASIG, + "Schnorr Standard CHECKDATASIG disabled but no NULLFAIL/STRICTENC", + SCRIPT_ENABLE_CHECKDATASIG) + .PushDataSigSchnorr(keys.key1, {}) + .Num(0) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG, + "Schnorr CHECKDATASIG with hybrid pubkey but no STRICTENC", + checkdatasigschnorrflags & ~SCRIPT_VERIFY_STRICTENC) + .PushDataSigSchnorr(keys.key0, {}) + .Num(0)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG, + "Schnorr CHECKDATASIG with hybrid pubkey", + checkdatasigschnorrflags) + .PushDataSigSchnorr(keys.key0, {}) + .Num(0) + .ScriptError(SCRIPT_ERR_PUBKEYTYPE)); + tests.push_back( + TestBuilder( + CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG + << OP_NOT, + "Schnorr CHECKDATASIG with invalid hybrid pubkey but no STRICTENC", + SCRIPT_ENABLE_CHECKDATASIG | SCRIPT_ENABLE_SCHNORR) + .PushDataSigSchnorr(keys.key0, {}) + .DamagePush(10) + .Num(0)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIG, + "Schnorr CHECKDATASIG with invalid hybrid pubkey", + checkdatasigschnorrflags) + .PushDataSigSchnorr(keys.key0, {}) + .DamagePush(10) + .Num(0) + .ScriptError(SCRIPT_ERR_PUBKEYTYPE)); + + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) + << OP_CHECKDATASIGVERIFY << OP_TRUE, + "Schnorr Standard CHECKDATASIGVERIFY", + checkdatasigschnorrflags) + .PushDataSigSchnorr(keys.key1, {}) + .Num(0)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) + << OP_CHECKDATASIGVERIFY, + "Schnorr Standard CHECKDATASIGVERIFY disabled", + checkdatasigflags) + .PushDataSigSchnorr(keys.key1, {}) + .Num(0) + .ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) + << OP_CHECKDATASIGVERIFY, + "Schnorr Standard CHECKDATASIGVERIFY disabled " + "but no NULLFAIL/STRICTENC", + SCRIPT_ENABLE_CHECKDATASIG) + .PushDataSigSchnorr(keys.key1, {}) + .Num(0) + .ScriptError(SCRIPT_ERR_CHECKDATASIGVERIFY)); + tests.push_back( + TestBuilder( + CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKDATASIGVERIFY + << OP_TRUE, + "Schnorr CHECKDATASIGVERIFY with hybrid pubkey but no STRICTENC", + checkdatasigschnorrflags & ~SCRIPT_VERIFY_STRICTENC) + .PushDataSigSchnorr(keys.key0, {}) + .Num(0)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) + << OP_CHECKDATASIGVERIFY << OP_TRUE, + "Schnorr CHECKDATASIGVERIFY with hybrid pubkey", + checkdatasigschnorrflags) + .PushDataSigSchnorr(keys.key0, {}) + .Num(0) + .ScriptError(SCRIPT_ERR_PUBKEYTYPE)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0H) + << OP_CHECKDATASIGVERIFY << OP_TRUE, + "Schnorr CHECKDATASIGVERIFY with invalid hybrid pubkey but " + "no STRICTENC", + SCRIPT_ENABLE_CHECKDATASIG | SCRIPT_ENABLE_SCHNORR) + .PushDataSigSchnorr(keys.key0, {}) + .DamagePush(10) + .Num(0) + .ScriptError(SCRIPT_ERR_CHECKDATASIGVERIFY)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0H) + << OP_CHECKDATASIGVERIFY << OP_TRUE, + "Schnorr CHECKDATASIGVERIFY with invalid hybrid pubkey", + checkdatasigschnorrflags) + .PushDataSigSchnorr(keys.key0, {}) + .DamagePush(10) + .Num(0) + .ScriptError(SCRIPT_ERR_PUBKEYTYPE)); + + // test putting valid short ECDSA sigs (same or close to schnorr length) + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "64+1-byte ECDSA P2PK", 0) + .PushSig(keys.key0, SigHashType(), 21, 37)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "64+1-byte ECDSA P2PK strict", SCRIPT_VERIFY_STRICTENC) + .PushSig(keys.key0, SigHashType(), 21, 37) + .ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "63+1-byte ECDSA P2PK with Schnorr flag", + SCRIPT_ENABLE_SCHNORR) + .PushSig(keys.key0, SigHashType(), 21, 36)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "64+1-byte ECDSA P2PK with Schnorr flag", + SCRIPT_ENABLE_SCHNORR) + .PushSig(keys.key0, SigHashType(), 21, 37) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "65+1-byte ECDSA P2PK with Schnorr flag", + SCRIPT_ENABLE_SCHNORR) + .PushSig(keys.key0, SigHashType(), 21, 38)); + tests.push_back( + TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "64+1-byte ECDSA P2PK strict with Schnorr", + SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) + .PushSig(keys.key0, SigHashType(), 21, 37) + .ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "63+1-byte ECDSA 1-of-1", 0) + .Num(0) + .PushSig(keys.key1, SigHashType(), 21, 36)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "64+1-byte ECDSA 1-of-1", 0) + .Num(0) + .PushSig(keys.key1, SigHashType(), 21, 37)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "65+1-byte ECDSA 1-of-1", 0) + .Num(0) + .PushSig(keys.key1, SigHashType(), 21, 38)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "63+1-byte ECDSA 1-of-1 with schnorr flag", + SCRIPT_ENABLE_SCHNORR) + .Num(0) + .PushSig(keys.key1, SigHashType(), 21, 36)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "64+1-byte ECDSA 1-of-1 with schnorr flag", + SCRIPT_ENABLE_SCHNORR) + .Num(0) + .PushSig(keys.key1, SigHashType(), 21, 37)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "65+1-byte ECDSA 1-of-1 with schnorr flag", + SCRIPT_ENABLE_SCHNORR) + .Num(0) + .PushSig(keys.key1, SigHashType(), 21, 38)); + tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) + << OP_1 << OP_CHECKMULTISIG, + "64+1-byte ECDSA 1-of-1 strict", + SCRIPT_VERIFY_STRICTENC) + .Num(0) + .PushSig(keys.key1, SigHashType(), 21, 37) + .ScriptError(SCRIPT_ERR_SIG_DER)); + tests.push_back( + TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << OP_1 + << OP_CHECKMULTISIG, + "64+1-byte ECDSA 1-of-1 strict with schnorr flag", + SCRIPT_VERIFY_STRICTENC | SCRIPT_ENABLE_SCHNORR) + .Num(0) + .PushSig(keys.key1, SigHashType(), 21, 37) + .ScriptError(SCRIPT_ERR_SIG_DER)); + std::set tests_set; {