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, int nHashType);
18 static const int64 nEvalSwitchover = 1328054400;
23 // Set mock time to AFTER OP_EVAL deployed
24 SetMockTime(nEvalSwitchover+1);
28 // Reset back to use-real-time
33 BOOST_FIXTURE_TEST_SUITE(script_op_eval_tests, CEvalFixture)
35 BOOST_AUTO_TEST_CASE(script_op_eval1)
37 // OP_EVAL looks like this:
38 // scriptSig: <sig> <sig...> <serialized_script>
39 // scriptPubKey: DUP HASH160 <hash> EQUALVERIFY EVAL
41 // Test SignSignature() (and therefore the version of Solver() that signs transactions)
42 CBasicKeyStore keystore;
44 for (int i = 0; i < 4; i++)
47 keystore.AddKey(key[i]);
50 // 8 Scripts: checking all combinations of
51 // different keys, straight/EVAL, pubkey/pubkeyhash
52 CScript standardScripts[4];
53 standardScripts[0] << key[0].GetPubKey() << OP_CHECKSIG;
54 standardScripts[1].SetBitcoinAddress(key[1].GetPubKey());
55 standardScripts[2] << key[1].GetPubKey() << OP_CHECKSIG;
56 standardScripts[3].SetBitcoinAddress(key[2].GetPubKey());
57 CScript evalScripts[4];
58 uint160 sigScriptHashes[4];
59 for (int i = 0; i < 4; i++)
61 sigScriptHashes[i] = Hash160(standardScripts[i]);
62 keystore.AddCScript(sigScriptHashes[i], standardScripts[i]);
63 evalScripts[i] << OP_DUP << OP_HASH160 << sigScriptHashes[i] << OP_EQUALVERIFY << OP_EVAL;
66 CTransaction txFrom; // Funding transaction:
67 txFrom.vout.resize(8);
68 for (int i = 0; i < 4; i++)
70 txFrom.vout[i].scriptPubKey = evalScripts[i];
71 txFrom.vout[i+4].scriptPubKey = standardScripts[i];
73 BOOST_CHECK(txFrom.IsStandard());
75 CTransaction txTo[8]; // Spending transactions
76 for (int i = 0; i < 8; i++)
78 txTo[i].vin.resize(1);
79 txTo[i].vout.resize(1);
80 txTo[i].vin[0].prevout.n = i;
81 txTo[i].vin[0].prevout.hash = txFrom.GetHash();
82 txTo[i].vout[0].nValue = 1;
83 BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
85 for (int i = 0; i < 8; i++)
87 BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
89 // All of the above should be OK, and the txTos have valid signatures
90 // Check to make sure signature verification fails if we use the wrong ScriptSig:
91 for (int i = 0; i < 8; i++)
92 for (int j = 0; j < 8; j++)
94 CScript sigSave = txTo[i].vin[0].scriptSig;
95 txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
97 bool sigOK = VerifySignature(txFrom, txTo[i], 0, nUnused);
99 BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
101 BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j));
102 txTo[i].vin[0].scriptSig = sigSave;
106 BOOST_AUTO_TEST_CASE(script_op_eval2)
108 // Test OP_EVAL edge cases
111 recurse << OP_DUP << OP_EVAL;
113 uint160 recurseHash = Hash160(recurse);
116 fund << OP_DUP << OP_HASH160 << recurseHash << OP_EQUALVERIFY << OP_EVAL;
118 CTransaction txFrom; // Funding transaction:
119 txFrom.vout.resize(1);
120 txFrom.vout[0].scriptPubKey = fund;
122 BOOST_CHECK(txFrom.IsStandard()); // Looks like a standard transaction until you try to spend it
127 txTo.vin[0].prevout.n = 0;
128 txTo.vin[0].prevout.hash = txFrom.GetHash();
129 txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(recurse);
130 txTo.vout[0].nValue = 1;
133 BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0));
134 BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused));
137 BOOST_AUTO_TEST_CASE(script_op_eval3)
139 // Test the CScript::Set* methods
140 CBasicKeyStore keystore;
142 std::vector<CKey> keys;
143 for (int i = 0; i < 4; i++)
146 keystore.AddKey(key[i]);
147 keys.push_back(key[i]);
151 inner[0].SetBitcoinAddress(key[0].GetPubKey());
152 inner[1].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+2));
153 inner[2].SetMultisig(1, std::vector<CKey>(keys.begin(), keys.begin()+2));
154 inner[3].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+3));
157 for (int i = 0; i < 4; i++)
159 outer[i].SetEval(inner[i]);
160 keystore.AddCScript(Hash160(inner[i]), inner[i]);
163 CTransaction txFrom; // Funding transaction:
164 txFrom.vout.resize(4);
165 for (int i = 0; i < 4; i++)
167 txFrom.vout[i].scriptPubKey = outer[i];
169 BOOST_CHECK(txFrom.IsStandard());
171 CTransaction txTo[4]; // Spending transactions
172 for (int i = 0; i < 4; i++)
174 txTo[i].vin.resize(1);
175 txTo[i].vout.resize(1);
176 txTo[i].vin[0].prevout.n = i;
177 txTo[i].vin[0].prevout.hash = txFrom.GetHash();
178 txTo[i].vout[0].nValue = 1;
179 txTo[i].vout[0].scriptPubKey = inner[i];
180 BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
182 for (int i = 0; i < 4; i++)
184 BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
185 BOOST_CHECK_MESSAGE(txTo[i].IsStandard(), strprintf("txTo[%d].IsStandard", i));
189 BOOST_AUTO_TEST_CASE(script_op_eval_backcompat1)
191 // Check backwards-incompatibility-testing code
192 CScript returnsEleven;
193 returnsEleven << OP_11;
195 // This should validate on new clients, but will
196 // be invalid on old clients (that interpret OP_EVAL as a no-op)
197 // ... except there's a special rule that makes new clients reject
200 fund << OP_EVAL << OP_11 << OP_EQUAL;
202 CTransaction txFrom; // Funding transaction:
203 txFrom.vout.resize(1);
204 txFrom.vout[0].scriptPubKey = fund;
209 txTo.vin[0].prevout.n = 0;
210 txTo.vin[0].prevout.hash = txFrom.GetHash();
211 txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(returnsEleven);
212 txTo.vout[0].nValue = 1;
215 BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0));
216 BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused));
219 BOOST_AUTO_TEST_CASE(script_op_eval_switchover)
221 // Use SetMockTime to test OP_EVAL switchover code
223 notValid << OP_11 << OP_12 << OP_EQUALVERIFY;
225 // This will be valid under old rules, invalid under new:
229 CTransaction txFrom; // Funding transaction:
230 txFrom.vout.resize(1);
231 txFrom.vout[0].scriptPubKey = fund;
236 txTo.vin[0].prevout.n = 0;
237 txTo.vin[0].prevout.hash = txFrom.GetHash();
238 txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(notValid);
239 txTo.vout[0].nValue = 1;
241 SetMockTime(nEvalSwitchover-1);
244 BOOST_CHECK(VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0));
246 // After eval switchover time, it should validate:
247 SetMockTime(nEvalSwitchover);
248 BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0));
251 BOOST_AUTO_TEST_SUITE_END()