1 #include <boost/assert.hpp>
2 #include <boost/assign/list_of.hpp>
3 #include <boost/assign/list_inserter.hpp>
4 #include <boost/assign/std/vector.hpp>
5 #include <boost/test/unit_test.hpp>
6 #include <boost/foreach.hpp>
10 #include "../wallet.h"
14 // Test routines internal to script.cpp:
15 extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
16 extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int& nSigOps,
17 int nHashType, bool fStrictOpEval);
19 BOOST_AUTO_TEST_SUITE(script_op_eval_tests)
21 BOOST_AUTO_TEST_CASE(script_op_eval1)
23 // OP_EVAL looks like this:
24 // scriptSig: <sig> <sig...> <serialized_script>
25 // scriptPubKey: DUP HASH160 <hash> EQUALVERIFY EVAL
27 // Test SignSignature() (and therefore the version of Solver() that signs transactions)
28 CBasicKeyStore keystore;
30 for (int i = 0; i < 4; i++)
33 keystore.AddKey(key[i]);
36 // 8 Scripts: checking all combinations of
37 // different keys, straight/EVAL, pubkey/pubkeyhash
38 CScript standardScripts[4];
39 standardScripts[0] << key[0].GetPubKey() << OP_CHECKSIG;
40 standardScripts[1].SetBitcoinAddress(key[1].GetPubKey());
41 standardScripts[2] << key[1].GetPubKey() << OP_CHECKSIG;
42 standardScripts[3].SetBitcoinAddress(key[2].GetPubKey());
43 CScript evalScripts[4];
44 uint160 sigScriptHashes[4];
45 for (int i = 0; i < 4; i++)
47 sigScriptHashes[i] = Hash160(standardScripts[i]);
48 keystore.AddCScript(sigScriptHashes[i], standardScripts[i]);
49 evalScripts[i] << OP_DUP << OP_HASH160 << sigScriptHashes[i] << OP_EQUALVERIFY << OP_EVAL;
52 CTransaction txFrom; // Funding transaction:
53 txFrom.vout.resize(8);
54 for (int i = 0; i < 4; i++)
56 txFrom.vout[i].scriptPubKey = evalScripts[i];
57 txFrom.vout[i+4].scriptPubKey = standardScripts[i];
59 BOOST_CHECK(txFrom.IsStandard());
61 CTransaction txTo[8]; // Spending transactions
62 for (int i = 0; i < 8; i++)
64 txTo[i].vin.resize(1);
65 txTo[i].vout.resize(1);
66 txTo[i].vin[0].prevout.n = i;
67 txTo[i].vin[0].prevout.hash = txFrom.GetHash();
68 txTo[i].vout[0].nValue = 1;
69 BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
71 for (int i = 0; i < 8; i++)
73 BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
75 // All of the above should be OK, and the txTos have valid signatures
76 // Check to make sure signature verification fails if we use the wrong ScriptSig:
77 for (int i = 0; i < 8; i++)
78 for (int j = 0; j < 8; j++)
80 CScript sigSave = txTo[i].vin[0].scriptSig;
81 txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
83 bool sigOK = VerifySignature(txFrom, txTo[i], 0, nUnused);
85 BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
87 BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j));
88 txTo[i].vin[0].scriptSig = sigSave;
92 BOOST_AUTO_TEST_CASE(script_op_eval2)
94 // Test OP_EVAL edge cases
96 // Make sure infinite recursion fails to validate:
97 CScript infiniteRecurse;
98 infiniteRecurse << OP_DUP << OP_EVAL;
100 uint160 infiniteRecurseHash = Hash160(infiniteRecurse);
103 fund1 << OP_DUP << OP_HASH160 << infiniteRecurseHash << OP_EQUALVERIFY << OP_EVAL;
105 CTransaction txFrom1; // Funding transaction:
106 txFrom1.vout.resize(1);
107 txFrom1.vout[0].scriptPubKey = fund1;
109 BOOST_CHECK(txFrom1.IsStandard()); // Looks like a standard transaction until you try to spend it
111 std::vector<unsigned char> infiniteRecurseSerialized(infiniteRecurse);
115 txTo1.vout.resize(1);
116 txTo1.vin[0].prevout.n = 0;
117 txTo1.vin[0].prevout.hash = txFrom1.GetHash();
118 txTo1.vin[0].scriptSig = CScript() << infiniteRecurseSerialized << infiniteRecurseSerialized;
119 txTo1.vout[0].nValue = 1;
122 BOOST_CHECK(!VerifyScript(txTo1.vin[0].scriptSig, txFrom1.vout[0].scriptPubKey, txTo1, 0, nUnused1, 0, true));
123 BOOST_CHECK(!VerifySignature(txFrom1, txTo1, 0, nUnused1, true));
125 // Make sure 3-level-deep recursion fails to validate:
129 uint160 recurse3Hash = Hash160(recurse3);
132 fund2 << OP_DUP << OP_HASH160 << recurse3Hash << OP_EQUALVERIFY << OP_EVAL;
134 CTransaction txFrom2; // Funding transaction:
135 txFrom2.vout.resize(1);
136 txFrom2.vout[0].scriptPubKey = fund2;
138 BOOST_CHECK(txFrom2.IsStandard()); // Looks like a standard transaction until you try to spend it
140 std::vector<unsigned char> recurse3Serialized(recurse3);
141 CScript op1Script = CScript() << OP_1;
142 std::vector<unsigned char> op1Serialized(op1Script);
146 txTo2.vout.resize(1);
147 txTo2.vin[0].prevout.n = 0;
148 txTo2.vin[0].prevout.hash = txFrom2.GetHash();
149 txTo2.vin[0].scriptSig = CScript() << op1Serialized << recurse3Serialized << recurse3Serialized;
150 txTo2.vout[0].nValue = 1;
153 BOOST_CHECK(!VerifyScript(txTo2.vin[0].scriptSig, txFrom2.vout[0].scriptPubKey, txTo2, 0, nUnused2, 0, true));
154 BOOST_CHECK(!VerifySignature(txFrom2, txTo2, 0, nUnused2, true));
157 BOOST_AUTO_TEST_CASE(script_op_eval3)
159 // Test the CScript::Set* methods
160 CBasicKeyStore keystore;
162 std::vector<CKey> keys;
163 for (int i = 0; i < 4; i++)
166 keystore.AddKey(key[i]);
167 keys.push_back(key[i]);
171 inner[0].SetBitcoinAddress(key[0].GetPubKey());
172 inner[1].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+2));
173 inner[2].SetMultisig(1, std::vector<CKey>(keys.begin(), keys.begin()+2));
174 inner[3].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+3));
177 for (int i = 0; i < 4; i++)
179 outer[i].SetEval(inner[i]);
180 keystore.AddCScript(Hash160(inner[i]), inner[i]);
183 CTransaction txFrom; // Funding transaction:
184 txFrom.vout.resize(4);
185 for (int i = 0; i < 4; i++)
187 txFrom.vout[i].scriptPubKey = outer[i];
189 BOOST_CHECK(txFrom.IsStandard());
191 CTransaction txTo[4]; // Spending transactions
192 for (int i = 0; i < 4; i++)
194 txTo[i].vin.resize(1);
195 txTo[i].vout.resize(1);
196 txTo[i].vin[0].prevout.n = i;
197 txTo[i].vin[0].prevout.hash = txFrom.GetHash();
198 txTo[i].vout[0].nValue = 1;
199 txTo[i].vout[0].scriptPubKey = inner[i];
200 BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
202 for (int i = 0; i < 4; i++)
204 BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
205 BOOST_CHECK_MESSAGE(txTo[i].IsStandard(), strprintf("txTo[%d].IsStandard", i));
209 BOOST_AUTO_TEST_CASE(script_op_eval_backcompat1)
211 // Check backwards-incompatibility-testing code
212 CScript returnsEleven;
213 returnsEleven << OP_11;
215 // This should validate on new clients, but will
216 // be invalid on old clients (that interpret OP_EVAL as a no-op)
217 // ... except there's a special rule that makes new clients reject
220 fund << OP_EVAL << OP_11 << OP_EQUAL;
222 CTransaction txFrom; // Funding transaction:
223 txFrom.vout.resize(1);
224 txFrom.vout[0].scriptPubKey = fund;
229 txTo.vin[0].prevout.n = 0;
230 txTo.vin[0].prevout.hash = txFrom.GetHash();
231 txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(returnsEleven);
232 txTo.vout[0].nValue = 1;
235 BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
236 BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused, true));
239 BOOST_AUTO_TEST_CASE(script_op_eval_switchover)
241 // Test OP_EVAL switchover code
243 notValid << OP_11 << OP_12 << OP_EQUALVERIFY;
245 // This will be valid under old rules, invalid under new:
249 CTransaction txFrom; // Funding transaction:
250 txFrom.vout.resize(1);
251 txFrom.vout[0].scriptPubKey = fund;
256 txTo.vin[0].prevout.n = 0;
257 txTo.vin[0].prevout.hash = txFrom.GetHash();
258 txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(notValid);
259 txTo.vout[0].nValue = 1;
262 BOOST_CHECK(VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, false));
264 // Under strict op_eval switchover, it should be considered invalid:
265 BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
268 BOOST_AUTO_TEST_SUITE_END()