diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index f6ee7ade4..4311b0923 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1834,6 +1834,138 @@ "OK", "P2SH with CLEANSTACK" ], +[ + [ + "3044022039105b995a5f448639a997a5c90fda06f50b49df30c3bdb6663217bf79323db002206fecd54269dec569fcc517178880eb58bb40f381a282bb75766ff3637d5f4b4301", + "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac" + ], + "", + "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", + "P2SH,WITNESS", + "OK", + "Basic P2WSH" +], +[ + [ + "304402201a96950593cb0af32d080b0f193517f4559241a8ebd1e95e414533ad64a3f423022047f4f6d3095c23235bdff3aeff480d0529c027a3f093cb265b7cbf148553b85101", + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + ], + "", + "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5", + "P2SH,WITNESS", + "OK", + "Basic P2WPKH" +], +[ + [ + "3044022061fc1a144e221ec77a58a4281936eb6a1b715b9349e446e74d106ec26c8633ba022008064a0d112e8ad514440fcdfaa1006e48305d6844f50a65873fb4b2cf9c035f01", + "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac" + ], + "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64", + "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL", + "P2SH,WITNESS", + "OK", + "Basic P2SH(P2WSH)" +], +[ + [ + "3044022014e69768e174972f21d32d93002ca6fc26133cb9e819ceef7efb970798bde7b4022078b86849dbbec692ec9355aa2a763fce7ea11bf72fdd8ea5ea8083de6f8a77fe01", + "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + ], + "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5", + "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL", + "P2SH,WITNESS", + "OK", + "Basic P2SH(P2WPKH)" +], +[ + [ + "304402202589f0512cb2408fb08ed9bd24f85eb3059744d9e4f2262d0b7f1338cff6e8b902206c0978f449693e0578c71bc543b11079fd0baae700ee5e9a6bee94db490af9fc01", + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + ], + "", + "0 0x20 0xac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2WSH with the wrong key" +], +[ + [ + "304402206ef7fdb2986325d37c6eb1a8bb24aeb46dede112ed8fc76c7d7500b9b83c0d3d02201edc2322c794fe2d6b0bd73ed319e714aa9b86d8891961530d5c9b7156b60d4e01", + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + ], + "", + "0 0x14 0x7cf9c846cd4882efec4bf07e44ebdad495c94f4b", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2WPKH with the wrong key" +], +[ + [ + "30440220069ea3581afaf8187f63feee1fd2bd1f9c0dc71ea7d6e8a8b07ee2ebcf824bf402201a4fdef4c532eae59223be1eda6a397fc835142d4ddc6c74f4aa85b766a5c16f01", + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + ], + "0x22 0x0020ac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", + "HASH160 0x14 0x61039a003883787c0d6ebc66d97fdabe8e31449d EQUAL", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2SH(P2WSH) with the wrong key" +], +[ + [ + "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001", + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + ], + "0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b", + "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL", + "P2SH,WITNESS", + "EVAL_FALSE", + "Basic P2SH(P2WPKH) with the wrong key" +], +[ + [ + "304402202589f0512cb2408fb08ed9bd24f85eb3059744d9e4f2262d0b7f1338cff6e8b902206c0978f449693e0578c71bc543b11079fd0baae700ee5e9a6bee94db490af9fc01", + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + ], + "", + "0 0x20 0xac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", + "P2SH", + "OK", + "Basic P2WSH with the wrong key but no WITNESS" +], +[ + [ + "304402206ef7fdb2986325d37c6eb1a8bb24aeb46dede112ed8fc76c7d7500b9b83c0d3d02201edc2322c794fe2d6b0bd73ed319e714aa9b86d8891961530d5c9b7156b60d4e01", + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + ], + "", + "0 0x14 0x7cf9c846cd4882efec4bf07e44ebdad495c94f4b", + "P2SH", + "OK", + "Basic P2WPKH with the wrong key but no WITNESS" +], +[ + [ + "30440220069ea3581afaf8187f63feee1fd2bd1f9c0dc71ea7d6e8a8b07ee2ebcf824bf402201a4fdef4c532eae59223be1eda6a397fc835142d4ddc6c74f4aa85b766a5c16f01", + "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac" + ], + "0x22 0x0020ac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610", + "HASH160 0x14 0x61039a003883787c0d6ebc66d97fdabe8e31449d EQUAL", + "P2SH", + "OK", + "Basic P2SH(P2WSH) with the wrong key but no WITNESS" +], +[ + [ + "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001", + "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf" + ], + "0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b", + "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL", + "P2SH", + "OK", + "Basic P2SH(P2WPKH) with the wrong key but no WITNESS" +], ["CHECKSEQUENCEVERIFY tests"], ["", "NOP3", "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 index 88f1562b1..ab373edc9 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -167,7 +167,7 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScript BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message); BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message); #if defined(HAVE_CONSENSUS_LIB) - CDataStream stream(SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_WITNESS); + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); stream << tx2; if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) { BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(begin_ptr(scriptPubKey), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect, message); @@ -253,11 +253,22 @@ struct KeyData } }; +enum WitnessMode { + WITNESS_NONE, + WITNESS_PKH, + WITNESS_SH +}; class TestBuilder { private: - CScript scriptPubKey; + //! Actually executed script + CScript script; + //! The P2SH redeemscript + CScript redeemscript; + //! The Witness embedded script + CScript witscript; + CScriptWitness scriptWitness; CTransaction creditTx; CMutableTransaction spendTx; bool havePush; @@ -282,13 +293,25 @@ private: } public: - TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK) + TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false, WitnessMode wm = WITNESS_NONE) : script(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK) { - if (P2SH) { - creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL); - } else { - creditTx = BuildCreditingTransaction(redeemScript); + CScript scriptPubKey = script; + if (wm == WITNESS_PKH) { + uint160 hash; + CHash160().Write(&script[1], script.size() - 1).Finalize(hash.begin()); + script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(hash) << OP_EQUALVERIFY << OP_CHECKSIG; + scriptPubKey = CScript() << OP_0 << ToByteVector(hash); + } else if (wm == WITNESS_SH) { + witscript = scriptPubKey; + uint256 hash; + CSHA256().Write(&witscript[0], witscript.size()).Finalize(hash.begin()); + scriptPubKey = CScript() << OP_0 << ToByteVector(hash); } + if (P2SH) { + redeemscript = scriptPubKey; + scriptPubKey = CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemscript)) << OP_EQUAL; + } + creditTx = BuildCreditingTransaction(scriptPubKey); spendTx = BuildSpendingTransaction(CScript(), CScriptWitness(), creditTx); } @@ -318,9 +341,9 @@ public: return *this; } - TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32) + TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_BASE) { - uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType, 0, SIGVERSION_BASE); + uint256 hash = SignatureHash(script, spendTx, 0, nHashType, 0, sigversion); std::vector vchSig, r, s; uint32_t iter = 0; do { @@ -336,6 +359,11 @@ public: return *this; } + TestBuilder& PushWitSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SIGVERSION_WITNESS_V0) + { + return PushSig(key, nHashType, lenR, lenS, sigversion).AsWit(); + } + TestBuilder& Push(const CPubKey& pubkey) { DoPush(std::vector(pubkey.begin(), pubkey.end())); @@ -344,10 +372,16 @@ public: TestBuilder& PushRedeem() { - DoPush(std::vector(scriptPubKey.begin(), scriptPubKey.end())); + DoPush(std::vector(redeemscript.begin(), redeemscript.end())); return *this; } + TestBuilder& PushWitRedeem() + { + DoPush(std::vector(witscript.begin(), witscript.end())); + return AsWit(); + } + TestBuilder& EditPush(unsigned int pos, const std::string& hexin, const std::string& hexout) { assert(havePush); @@ -372,15 +406,30 @@ public: { TestBuilder copy = *this; // Make a copy so we can rollback the push. DoPush(); - DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, CScriptWitness(), flags, comment, scriptError); + DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, scriptWitness, flags, comment, scriptError); *this = copy; return *this; } + TestBuilder& AsWit() + { + assert(havePush); + scriptWitness.stack.push_back(push); + havePush = false; + return *this; + } + UniValue GetJSON() { DoPush(); UniValue array(UniValue::VARR); + if (!scriptWitness.stack.empty()) { + UniValue wit(UniValue::VARR); + for (unsigned i = 0; i < scriptWitness.stack.size(); i++) { + wit.push_back(HexStr(scriptWitness.stack[i])); + } + array.push_back(wit); + } array.push_back(FormatScript(spendTx.vin[0].scriptSig)); array.push_back(FormatScript(creditTx.vout[0].scriptPubKey)); array.push_back(FormatScriptFlags(flags)); @@ -679,6 +728,42 @@ BOOST_AUTO_TEST_CASE(script_build) "P2SH with CLEANSTACK", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true ).PushSig(keys.key0).PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, + "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0), + "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "Basic P2WSH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1), + "Basic P2WPKH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "Basic P2SH(P2WSH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1), + "Basic P2SH(P2WPKH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE)); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "Basic P2WSH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1), + "Basic P2WPKH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG, + "Basic P2SH(P2WSH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_SH + ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem()); + tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1), + "Basic P2SH(P2WPKH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WITNESS_PKH + ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem()); std::set tests_set;