diff --git a/src/script.cpp b/src/script.cpp index c103d57510..e60399120f 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1014,6 +1014,18 @@ bool EvalScriptInner(vector >& stack, const CScript& scrip case OP_EVAL: { + // This code should be removed when OP_EVAL has + // a majority of hashing power on the network. + // OP_EVAL behaves just like OP_NOP until + // opevaltime : + if (!fTestNet || fDebug) + { + // 1328054400 is Feb 1, 2012 + int64 nEvalSwitchTime = GetArg("opevaltime", 1328054400); + if (GetTime() < nEvalSwitchTime) + break; + } + // Evaluate the top item on the stack as a Script // [serialized script ] -- [result(s) of executing script] if (stack.size() < 1) diff --git a/src/test/script_op_eval_tests.cpp b/src/test/script_op_eval_tests.cpp index 857d04bc6d..6c683b5729 100644 --- a/src/test/script_op_eval_tests.cpp +++ b/src/test/script_op_eval_tests.cpp @@ -15,7 +15,22 @@ using namespace std; 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); -BOOST_AUTO_TEST_SUITE(script_op_eval_tests) +static const int64 nEvalSwitchover = 1328054400; + +struct CEvalFixture { + CEvalFixture() + { + // Set mock time to AFTER OP_EVAL deployed + SetMockTime(nEvalSwitchover+1); + } + ~CEvalFixture() + { + // Reset back to use-real-time + SetMockTime(0); + } +}; + +BOOST_FIXTURE_TEST_SUITE(script_op_eval_tests, CEvalFixture) BOOST_AUTO_TEST_CASE(script_op_eval1) { @@ -171,14 +186,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; @@ -199,5 +216,36 @@ BOOST_AUTO_TEST_CASE(script_op_eval_backcompat) BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused)); } +BOOST_AUTO_TEST_CASE(script_op_eval_switchover) +{ + // Use SetMockTime to 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 >(notValid); + txTo.vout[0].nValue = 1; + + SetMockTime(nEvalSwitchover-1); + + int nUnused = 0; + BOOST_CHECK(VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0)); + + // After eval switchover time, it should validate: + SetMockTime(nEvalSwitchover); + BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0)); +} BOOST_AUTO_TEST_SUITE_END()