Use standard C99 (and Qt) types for 64-bit integers
[novacoin.git] / src / test / script_op_eval_tests.cpp
1 #include <stdint.h>
2
3 #include <boost/assert.hpp>
4 #include <boost/assign/list_of.hpp>
5 #include <boost/assign/list_inserter.hpp>
6 #include <boost/assign/std/vector.hpp>
7 #include <boost/test/unit_test.hpp>
8 #include <boost/foreach.hpp>
9
10 #include "../main.h"
11 #include "../script.h"
12 #include "../wallet.h"
13
14 using namespace std;
15
16 // Test routines internal to script.cpp:
17 extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
18 extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int& nSigOps,
19                          int nHashType, bool fStrictOpEval);
20
21 BOOST_AUTO_TEST_SUITE(script_op_eval_tests)
22
23 BOOST_AUTO_TEST_CASE(script_op_eval1)
24 {
25     // OP_EVAL looks like this:
26     // scriptSig:    <sig> <sig...> <serialized_script>
27     // scriptPubKey: DUP HASH160 <hash> EQUALVERIFY EVAL
28
29     // Test SignSignature() (and therefore the version of Solver() that signs transactions)
30     CBasicKeyStore keystore;
31     CKey key[4];
32     for (int i = 0; i < 4; i++)
33     {
34         key[i].MakeNewKey();
35         keystore.AddKey(key[i]);
36     }
37
38     // 8 Scripts: checking all combinations of
39     // different keys, straight/EVAL, pubkey/pubkeyhash
40     CScript standardScripts[4];
41     standardScripts[0] << key[0].GetPubKey() << OP_CHECKSIG;
42     standardScripts[1].SetBitcoinAddress(key[1].GetPubKey());
43     standardScripts[2] << key[1].GetPubKey() << OP_CHECKSIG;
44     standardScripts[3].SetBitcoinAddress(key[2].GetPubKey());
45     CScript evalScripts[4];
46     uint160 sigScriptHashes[4];
47     for (int i = 0; i < 4; i++)
48     {
49         sigScriptHashes[i] = Hash160(standardScripts[i]);
50         keystore.AddCScript(sigScriptHashes[i], standardScripts[i]);
51         evalScripts[i] << OP_DUP << OP_HASH160 << sigScriptHashes[i] << OP_EQUALVERIFY << OP_EVAL;
52     }
53
54     CTransaction txFrom;  // Funding transaction:
55     txFrom.vout.resize(8);
56     for (int i = 0; i < 4; i++)
57     {
58         txFrom.vout[i].scriptPubKey = evalScripts[i];
59         txFrom.vout[i+4].scriptPubKey = standardScripts[i];
60     }
61     BOOST_CHECK(txFrom.IsStandard());
62
63     CTransaction txTo[8]; // Spending transactions
64     for (int i = 0; i < 8; i++)
65     {
66         txTo[i].vin.resize(1);
67         txTo[i].vout.resize(1);
68         txTo[i].vin[0].prevout.n = i;
69         txTo[i].vin[0].prevout.hash = txFrom.GetHash();
70         txTo[i].vout[0].nValue = 1;
71         BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
72     }
73     for (int i = 0; i < 8; i++)
74     {
75         BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
76     }
77     // All of the above should be OK, and the txTos have valid signatures
78     // Check to make sure signature verification fails if we use the wrong ScriptSig:
79     for (int i = 0; i < 8; i++)
80         for (int j = 0; j < 8; j++)
81         {
82             CScript sigSave = txTo[i].vin[0].scriptSig;
83             txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
84             int nUnused = 0;
85             bool sigOK = VerifySignature(txFrom, txTo[i], 0, nUnused);
86             if (i == j)
87                 BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
88             else
89                 BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j));
90             txTo[i].vin[0].scriptSig = sigSave;
91         }
92 }
93
94 BOOST_AUTO_TEST_CASE(script_op_eval2)
95 {
96     // Test OP_EVAL edge cases
97
98     CScript recurse;
99     recurse << OP_DUP << OP_EVAL;
100
101     uint160 recurseHash = Hash160(recurse);
102
103     CScript fund;
104     fund << OP_DUP << OP_HASH160 << recurseHash << OP_EQUALVERIFY << OP_EVAL;
105
106     CTransaction txFrom;  // Funding transaction:
107     txFrom.vout.resize(1);
108     txFrom.vout[0].scriptPubKey = fund;
109
110     BOOST_CHECK(txFrom.IsStandard()); // Looks like a standard transaction until you try to spend it
111
112     CTransaction txTo;
113     txTo.vin.resize(1);
114     txTo.vout.resize(1);
115     txTo.vin[0].prevout.n = 0;
116     txTo.vin[0].prevout.hash = txFrom.GetHash();
117     txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(recurse);
118     txTo.vout[0].nValue = 1;
119
120     int nUnused = 0;
121     BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
122     BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused, true));
123 }
124
125 BOOST_AUTO_TEST_CASE(script_op_eval3)
126 {
127     // Test the CScript::Set* methods
128     CBasicKeyStore keystore;
129     CKey key[4];
130     std::vector<CKey> keys;
131     for (int i = 0; i < 4; i++)
132     {
133         key[i].MakeNewKey();
134         keystore.AddKey(key[i]);
135         keys.push_back(key[i]);
136     }
137
138     CScript inner[4];
139     inner[0].SetBitcoinAddress(key[0].GetPubKey());
140     inner[1].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+2));
141     inner[2].SetMultisig(1, std::vector<CKey>(keys.begin(), keys.begin()+2));
142     inner[3].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+3));
143
144     CScript outer[4];
145     for (int i = 0; i < 4; i++)
146     {
147         outer[i].SetEval(inner[i]);
148         keystore.AddCScript(Hash160(inner[i]), inner[i]);
149     }
150
151     CTransaction txFrom;  // Funding transaction:
152     txFrom.vout.resize(4);
153     for (int i = 0; i < 4; i++)
154     {
155         txFrom.vout[i].scriptPubKey = outer[i];
156     }
157     BOOST_CHECK(txFrom.IsStandard());
158
159     CTransaction txTo[4]; // Spending transactions
160     for (int i = 0; i < 4; i++)
161     {
162         txTo[i].vin.resize(1);
163         txTo[i].vout.resize(1);
164         txTo[i].vin[0].prevout.n = i;
165         txTo[i].vin[0].prevout.hash = txFrom.GetHash();
166         txTo[i].vout[0].nValue = 1;
167         txTo[i].vout[0].scriptPubKey = inner[i];
168         BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
169     }
170     for (int i = 0; i < 4; i++)
171     {
172         BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
173         BOOST_CHECK_MESSAGE(txTo[i].IsStandard(), strprintf("txTo[%d].IsStandard", i));
174     }
175 }
176
177 BOOST_AUTO_TEST_CASE(script_op_eval_backcompat1)
178 {
179     // Check backwards-incompatibility-testing code
180     CScript returnsEleven;
181     returnsEleven << OP_11;
182
183     // This should validate on new clients, but will
184     // be invalid on old clients (that interpret OP_EVAL as a no-op)
185     //  ... except there's a special rule that makes new clients reject
186     // it.
187     CScript fund;
188     fund << OP_EVAL << OP_11 << OP_EQUAL;
189
190     CTransaction txFrom;  // Funding transaction:
191     txFrom.vout.resize(1);
192     txFrom.vout[0].scriptPubKey = fund;
193
194     CTransaction txTo;
195     txTo.vin.resize(1);
196     txTo.vout.resize(1);
197     txTo.vin[0].prevout.n = 0;
198     txTo.vin[0].prevout.hash = txFrom.GetHash();
199     txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(returnsEleven);
200     txTo.vout[0].nValue = 1;
201
202     int nUnused = 0;
203     BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
204     BOOST_CHECK(!VerifySignature(txFrom, txTo, 0, nUnused, true));
205 }
206
207 BOOST_AUTO_TEST_CASE(script_op_eval_switchover)
208 {
209     // Test OP_EVAL switchover code
210     CScript notValid;
211     notValid << OP_11 << OP_12 << OP_EQUALVERIFY;
212
213     // This will be valid under old rules, invalid under new:
214     CScript fund;
215     fund << OP_EVAL;
216
217     CTransaction txFrom;  // Funding transaction:
218     txFrom.vout.resize(1);
219     txFrom.vout[0].scriptPubKey = fund;
220
221     CTransaction txTo;
222     txTo.vin.resize(1);
223     txTo.vout.resize(1);
224     txTo.vin[0].prevout.n = 0;
225     txTo.vin[0].prevout.hash = txFrom.GetHash();
226     txTo.vin[0].scriptSig = CScript() << static_cast<std::vector<unsigned char> >(notValid);
227     txTo.vout[0].nValue = 1;
228
229     int nUnused = 0;
230     BOOST_CHECK(VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, false));
231
232     // Under strict op_eval switchover, it should be considered invalid:
233     BOOST_CHECK(!VerifyScript(txTo.vin[0].scriptSig, txFrom.vout[0].scriptPubKey, txTo, 0, nUnused, 0, true));
234 }
235
236 BOOST_AUTO_TEST_SUITE_END()