From 6d6d392b2238a4c6469f7e4d70071f17841197eb Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Tue, 27 Dec 2011 16:41:56 -0500 Subject: [PATCH] Fixed OP_EVAL recursion unit test, checks for both infinite and exactly-3-deep recursion --- src/test/script_op_eval_tests.cpp | 72 +++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/src/test/script_op_eval_tests.cpp b/src/test/script_op_eval_tests.cpp index c44642c6..b1bd52c5 100644 --- a/src/test/script_op_eval_tests.cpp +++ b/src/test/script_op_eval_tests.cpp @@ -93,31 +93,65 @@ BOOST_AUTO_TEST_CASE(script_op_eval2) { // Test OP_EVAL edge cases - CScript recurse; - recurse << OP_DUP << OP_EVAL; + // Make sure infinite recursion fails to validate: + CScript infiniteRecurse; + infiniteRecurse << OP_DUP << OP_EVAL; - uint160 recurseHash = Hash160(recurse); + uint160 infiniteRecurseHash = Hash160(infiniteRecurse); - CScript fund; - fund << OP_DUP << OP_HASH160 << recurseHash << OP_EQUALVERIFY << OP_EVAL; + CScript fund1; + fund1 << OP_DUP << OP_HASH160 << infiniteRecurseHash << OP_EQUALVERIFY << OP_EVAL; - CTransaction txFrom; // Funding transaction: - txFrom.vout.resize(1); - txFrom.vout[0].scriptPubKey = fund; + CTransaction txFrom1; // Funding transaction: + txFrom1.vout.resize(1); + txFrom1.vout[0].scriptPubKey = fund1; - BOOST_CHECK(txFrom.IsStandard()); // Looks like a standard transaction until you try to spend it + BOOST_CHECK(txFrom1.IsStandard()); // Looks like a standard transaction until you try to spend it - CTransaction txTo; - txTo.vin.resize(1); - txTo.vout.resize(1); - txTo.vin[0].prevout.n = 0; - txTo.vin[0].prevout.hash = txFrom.GetHash(); - txTo.vin[0].scriptSig = CScript() << static_cast >(recurse); - txTo.vout[0].nValue = 1; + std::vector infiniteRecurseSerialized(infiniteRecurse); - int nUnused = 0; - BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true)); - BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused, true)); + CTransaction txTo1; + txTo1.vin.resize(1); + txTo1.vout.resize(1); + txTo1.vin[0].prevout.n = 0; + txTo1.vin[0].prevout.hash = txFrom1.GetHash(); + txTo1.vin[0].scriptSig = CScript() << infiniteRecurseSerialized << infiniteRecurseSerialized; + txTo1.vout[0].nValue = 1; + + int nUnused1 = 0; + BOOST_CHECK(!VerifyScript(txTo1.vin[0].scriptSig, txFrom1.vout[0].scriptPubKey, txTo1, 0, nUnused1, 0, true)); + BOOST_CHECK(!VerifySignature(txFrom1, txTo1, 0, nUnused1, true)); + + // Make sure 3-level-deep recursion fails to validate: + CScript recurse3; + recurse3 << OP_EVAL; + + uint160 recurse3Hash = Hash160(recurse3); + + CScript fund2; + fund2 << OP_DUP << OP_HASH160 << recurse3Hash << OP_EQUALVERIFY << OP_EVAL; + + CTransaction txFrom2; // Funding transaction: + txFrom2.vout.resize(1); + txFrom2.vout[0].scriptPubKey = fund2; + + BOOST_CHECK(txFrom2.IsStandard()); // Looks like a standard transaction until you try to spend it + + std::vector recurse3Serialized(recurse3); + CScript op1Script = CScript() << OP_1; + std::vector op1Serialized(op1Script); + + CTransaction txTo2; + txTo2.vin.resize(1); + txTo2.vout.resize(1); + txTo2.vin[0].prevout.n = 0; + txTo2.vin[0].prevout.hash = txFrom2.GetHash(); + txTo2.vin[0].scriptSig = CScript() << op1Serialized << recurse3Serialized << recurse3Serialized; + txTo2.vout[0].nValue = 1; + + int nUnused2 = 0; + BOOST_CHECK(!VerifyScript(txTo2.vin[0].scriptSig, txFrom2.vout[0].scriptPubKey, txTo2, 0, nUnused2, 0, true)); + BOOST_CHECK(!VerifySignature(txFrom2, txTo2, 0, nUnused2, true)); } BOOST_AUTO_TEST_CASE(script_op_eval3)