|
|
|
@ -93,31 +93,65 @@ BOOST_AUTO_TEST_CASE(script_op_eval2)
@@ -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<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, 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<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) |
|
|
|
|