Remove not-used-anywhere scriptPrereq from SignSignature()
[novacoin.git] / src / test / script_op_eval_tests.cpp
index 857d04b..b1bd52c 100644 (file)
@@ -13,7 +13,8 @@ using namespace std;
 
 // Test routines internal to script.cpp:
 extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
-extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int& nSigOps, int nHashType);
+extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int& nSigOps,
+                         int nHashType, bool fStrictOpEval);
 
 BOOST_AUTO_TEST_SUITE(script_op_eval_tests)
 
@@ -92,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<std::vector<unsigned char> >(recurse);
-    txTo.vout[0].nValue = 1;
+    std::vector<unsigned char> infiniteRecurseSerialized(infiniteRecurse);
 
-    int nUnused = 0;
-    BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0));
-    BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused));
+    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<unsigned char> recurse3Serialized(recurse3);
+    CScript op1Script = CScript() << OP_1;
+    std::vector<unsigned char> 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)
@@ -171,14 +206,16 @@ BOOST_AUTO_TEST_CASE(script_op_eval3)
     }
 }
 
-BOOST_AUTO_TEST_CASE(script_op_eval_backcompat)
+BOOST_AUTO_TEST_CASE(script_op_eval_backcompat1)
 {
     // Check backwards-incompatibility-testing code
     CScript returnsEleven;
     returnsEleven << OP_11;
 
-    // This will validate on new clients, but will
+    // This should validate on new clients, but will
     // be invalid on old clients (that interpret OP_EVAL as a no-op)
+    //  ... except there's a special rule that makes new clients reject
+    // it.
     CScript fund;
     fund << OP_EVAL << OP_11 << OP_EQUAL;
 
@@ -195,9 +232,37 @@ BOOST_AUTO_TEST_CASE(script_op_eval_backcompat)
     txTo.vout[0].nValue = 1;
 
     int nUnused = 0;
-    BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0));
-    BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused));
+    BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
+    BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused, true));
 }
 
+BOOST_AUTO_TEST_CASE(script_op_eval_switchover)
+{
+    // Test OP_EVAL switchover code
+    CScript notValid;
+    notValid << OP_11 << OP_12 << OP_EQUALVERIFY;
+
+    // This will be valid under old rules, invalid under new:
+    CScript fund;
+    fund << OP_EVAL;
+
+    CTransaction txFrom;  // Funding transaction:
+    txFrom.vout.resize(1);
+    txFrom.vout[0].scriptPubKey = fund;
+
+    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<std::vector<unsigned char> >(notValid);
+    txTo.vout[0].nValue = 1;
+
+    int nUnused = 0;
+    BOOST_CHECK(VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, false));
+
+    // Under strict op_eval switchover, it should be considered invalid:
+    BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
+}
 
 BOOST_AUTO_TEST_SUITE_END()