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