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