Use block times for 'hard' OP_EVAL switchover, and refactored EvalScript
[novacoin.git] / src / test / multisig_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 #include <boost/tuple/tuple.hpp>
8
9 #include <openssl/ec.h>
10 #include <openssl/err.h>
11
12 #include "keystore.h"
13 #include "main.h"
14 #include "script.h"
15 #include "wallet.h"
16
17 using namespace std;
18 using namespace boost::assign;
19
20 typedef vector<unsigned char> valtype;
21
22 extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
23 extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int& nSigOpCount,
24                          int nHashType, bool fStrictOpEval);
25
26 BOOST_AUTO_TEST_SUITE(multisig_tests)
27
28 CScript
29 sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn)
30 {
31     uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL);
32
33     CScript result;
34     result << OP_0; // CHECKMULTISIG bug workaround
35     BOOST_FOREACH(CKey key, keys)
36     {
37         vector<unsigned char> vchSig;
38         BOOST_CHECK(key.Sign(hash, vchSig));
39         vchSig.push_back((unsigned char)SIGHASH_ALL);
40         result << vchSig;
41     }
42     return result;
43 }
44
45 BOOST_AUTO_TEST_CASE(multisig_verify)
46 {
47     CKey key[4];
48     for (int i = 0; i < 4; i++)
49         key[i].MakeNewKey();
50
51     CScript a_and_b;
52     a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
53
54     CScript a_or_b;
55     a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
56
57     CScript escrow;
58     escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
59
60     CTransaction txFrom;  // Funding transaction
61     txFrom.vout.resize(3);
62     txFrom.vout[0].scriptPubKey = a_and_b;
63     txFrom.vout[1].scriptPubKey = a_or_b;
64     txFrom.vout[2].scriptPubKey = escrow;
65
66     CTransaction txTo[3]; // Spending transaction
67     for (int i = 0; i < 3; i++)
68     {
69         txTo[i].vin.resize(1);
70         txTo[i].vout.resize(1);
71         txTo[i].vin[0].prevout.n = i;
72         txTo[i].vin[0].prevout.hash = txFrom.GetHash();
73         txTo[i].vout[0].nValue = 1;
74     }
75
76     vector<CKey> keys;
77     CScript s;
78     int nUnused = 0;
79
80     // Test a AND b:
81     keys.clear();
82     keys += key[0],key[1]; // magic operator+= from boost.assign
83     s = sign_multisig(a_and_b, keys, txTo[0], 0);
84     BOOST_CHECK(VerifyScript(s, a_and_b, txTo[0], 0, nUnused, 0, true));
85
86     for (int i = 0; i < 4; i++)
87     {
88         keys.clear();
89         keys += key[i];
90         s = sign_multisig(a_and_b, keys, txTo[0], 0);
91         BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, nUnused, 0, true), strprintf("a&b 1: %d", i));
92
93         keys.clear();
94         keys += key[1],key[i];
95         s = sign_multisig(a_and_b, keys, txTo[0], 0);
96         BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, nUnused, 0, true), strprintf("a&b 2: %d", i));
97     }
98
99     // Test a OR b:
100     for (int i = 0; i < 4; i++)
101     {
102         keys.clear();
103         keys += key[i];
104         s = sign_multisig(a_or_b, keys, txTo[1], 0);
105         if (i == 0 || i == 1)
106             BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0, true), strprintf("a|b: %d", i));
107         else
108             BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0, true), strprintf("a|b: %d", i));
109     }
110     s.clear();
111     s << OP_0 << OP_0;
112     BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0, true));
113     s.clear();
114     s << OP_0 << OP_1;
115     BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, nUnused, 0, true));
116
117
118     for (int i = 0; i < 4; i++)
119         for (int j = 0; j < 4; j++)
120         {
121             keys.clear();
122             keys += key[i],key[j];
123             s = sign_multisig(escrow, keys, txTo[2], 0);
124             if (i < j && i < 3 && j < 3)
125                 BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, txTo[2], 0, nUnused, 0, true), strprintf("escrow 1: %d %d", i, j));
126             else
127                 BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, nUnused, 0, true), strprintf("escrow 2: %d %d", i, j));
128         }
129 }
130
131 BOOST_AUTO_TEST_CASE(multisig_IsStandard)
132 {
133     CKey key[4];
134     for (int i = 0; i < 4; i++)
135         key[i].MakeNewKey();
136
137     CScript a_and_b;
138     a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
139     BOOST_CHECK(::IsStandard(a_and_b));
140
141     CScript a_or_b;
142     a_or_b  << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
143     BOOST_CHECK(::IsStandard(a_or_b));
144
145     CScript escrow;
146     escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
147     BOOST_CHECK(::IsStandard(escrow));
148
149     CScript one_of_four;
150     one_of_four << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << key[3].GetPubKey() << OP_4 << OP_CHECKMULTISIG;
151     BOOST_CHECK(!::IsStandard(one_of_four));
152
153     CScript malformed[6];
154     malformed[0] << OP_3 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
155     malformed[1] << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
156     malformed[2] << OP_0 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
157     malformed[3] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_0 << OP_CHECKMULTISIG;
158     malformed[4] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_CHECKMULTISIG;
159     malformed[5] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey();
160
161     for (int i = 0; i < 6; i++)
162         BOOST_CHECK(!::IsStandard(malformed[i]));
163 }
164
165 BOOST_AUTO_TEST_CASE(multisig_Solver1)
166 {
167     // Tests Solver() that returns lists of keys that are
168     // required to satisfy a ScriptPubKey
169     //
170     // Also tests IsMine() and ExtractAddress()
171     //
172     // Note: ExtractAddress for the multisignature transactions
173     // always returns false for this release, even if you have
174     // one key that would satisfy an (a|b) or 2-of-3 keys needed
175     // to spend an escrow transaction.
176     //
177     CBasicKeyStore keystore, emptykeystore;
178     CKey key[3];
179     CBitcoinAddress keyaddr[3];
180     for (int i = 0; i < 3; i++)
181     {
182         key[i].MakeNewKey();
183         keystore.AddKey(key[i]);
184         keyaddr[i].SetPubKey(key[i].GetPubKey());
185     }
186
187     {
188         vector<valtype> solutions;
189         txnouttype whichType;
190         CScript s;
191         s << key[0].GetPubKey() << OP_CHECKSIG;
192         BOOST_CHECK(Solver(s, whichType, solutions));
193         BOOST_CHECK(solutions.size() == 1);
194         CBitcoinAddress addr;
195         BOOST_CHECK(ExtractAddress(s, &keystore, addr));
196         BOOST_CHECK(addr == keyaddr[0]);
197         BOOST_CHECK(IsMine(keystore, s));
198         BOOST_CHECK(!IsMine(emptykeystore, s));
199     }
200     {
201         vector<valtype> solutions;
202         txnouttype whichType;
203         CScript s;
204         s << OP_DUP << OP_HASH160 << Hash160(key[0].GetPubKey()) << OP_EQUALVERIFY << OP_CHECKSIG;
205         BOOST_CHECK(Solver(s, whichType, solutions));
206         BOOST_CHECK(solutions.size() == 1);
207         CBitcoinAddress addr;
208         BOOST_CHECK(ExtractAddress(s, &keystore, addr));
209         BOOST_CHECK(addr == keyaddr[0]);
210         BOOST_CHECK(IsMine(keystore, s));
211         BOOST_CHECK(!IsMine(emptykeystore, s));
212     }
213     {
214         vector<valtype> solutions;
215         txnouttype whichType;
216         CScript s;
217         s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
218         BOOST_CHECK(Solver(s, whichType, solutions));
219         BOOST_CHECK_EQUAL(solutions.size(), 4);
220         CBitcoinAddress addr;
221         BOOST_CHECK(!ExtractAddress(s, &keystore, addr));
222         BOOST_CHECK(IsMine(keystore, s));
223         BOOST_CHECK(!IsMine(emptykeystore, s));
224     }
225     {
226         vector<valtype> solutions;
227         txnouttype whichType;
228         CScript s;
229         s << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
230         BOOST_CHECK(Solver(s, whichType, solutions));
231         BOOST_CHECK_EQUAL(solutions.size(), 4);
232         vector<CBitcoinAddress> addrs;
233         int nRequired;
234         BOOST_CHECK(ExtractAddresses(s, &keystore, whichType, addrs, nRequired));
235         BOOST_CHECK(addrs[0] == keyaddr[0]);
236         BOOST_CHECK(addrs[1] == keyaddr[1]);
237         BOOST_CHECK(nRequired = 1);
238         BOOST_CHECK(IsMine(keystore, s));
239         BOOST_CHECK(!IsMine(emptykeystore, s));
240     }
241     {
242         vector<valtype> solutions;
243         txnouttype whichType;
244         CScript s;
245         s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
246         BOOST_CHECK(Solver(s, whichType, solutions));
247         BOOST_CHECK(solutions.size() == 5);
248     }
249 }
250
251 BOOST_AUTO_TEST_CASE(multisig_Sign)
252 {
253     // Test SignSignature() (and therefore the version of Solver() that signs transactions)
254     CBasicKeyStore keystore;
255     CKey key[4];
256     for (int i = 0; i < 4; i++)
257     {
258         key[i].MakeNewKey();
259         keystore.AddKey(key[i]);
260     }
261
262     CScript a_and_b;
263     a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
264
265     CScript a_or_b;
266     a_or_b  << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
267
268     CScript escrow;
269     escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
270
271     CTransaction txFrom;  // Funding transaction
272     txFrom.vout.resize(3);
273     txFrom.vout[0].scriptPubKey = a_and_b;
274     txFrom.vout[1].scriptPubKey = a_or_b;
275     txFrom.vout[2].scriptPubKey = escrow;
276
277     CTransaction txTo[3]; // Spending transaction
278     for (int i = 0; i < 3; i++)
279     {
280         txTo[i].vin.resize(1);
281         txTo[i].vout.resize(1);
282         txTo[i].vin[0].prevout.n = i;
283         txTo[i].vin[0].prevout.hash = txFrom.GetHash();
284         txTo[i].vout[0].nValue = 1;
285     }
286
287     for (int i = 0; i < 3; i++)
288     {
289         BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
290     }
291 }
292
293
294 BOOST_AUTO_TEST_SUITE_END()