]> Git Repo - VerusCoin.git/blob - src/test/multisig_tests.cpp
cc6f6acbf82481b75db3503ab0e6246b4db87b33
[VerusCoin.git] / src / test / multisig_tests.cpp
1 // Copyright (c) 2011-2013 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #include "key.h"
6 #include "keystore.h"
7 #include "main.h"
8 #include "script/script.h"
9 #include "script/script_error.h"
10 #include "script/interpreter.h"
11 #include "script/sign.h"
12 #include "uint256.h"
13 #include "test/test_bitcoin.h"
14
15 #ifdef ENABLE_WALLET
16 #include "wallet/wallet_ismine.h"
17 #endif
18
19 #include <boost/foreach.hpp>
20 #include <boost/test/unit_test.hpp>
21
22 using namespace std;
23
24 typedef vector<unsigned char> valtype;
25
26 BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
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(const 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     unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
48
49     ScriptError err;
50     CKey key[4];
51     for (int i = 0; i < 4; i++)
52         key[i].MakeNewKey(true);
53
54     CScript a_and_b;
55     a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
56
57     CScript a_or_b;
58     a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
59
60     CScript escrow;
61     escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
62
63     CMutableTransaction txFrom;  // Funding transaction
64     txFrom.vout.resize(3);
65     txFrom.vout[0].scriptPubKey = a_and_b;
66     txFrom.vout[1].scriptPubKey = a_or_b;
67     txFrom.vout[2].scriptPubKey = escrow;
68
69     CMutableTransaction txTo[3]; // Spending transaction
70     for (int i = 0; i < 3; i++)
71     {
72         txTo[i].vin.resize(1);
73         txTo[i].vout.resize(1);
74         txTo[i].vin[0].prevout.n = i;
75         txTo[i].vin[0].prevout.hash = txFrom.GetTxid();
76         txTo[i].vout[0].nValue = 1;
77     }
78
79     vector<CKey> keys;
80     CScript s;
81
82     // Test a AND b:
83     keys.assign(1,key[0]);
84     keys.push_back(key[1]);
85     s = sign_multisig(a_and_b, keys, txTo[0], 0);
86     BOOST_CHECK(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err));
87     BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
88
89     for (int i = 0; i < 4; i++)
90     {
91         keys.assign(1,key[i]);
92         s = sign_multisig(a_and_b, keys, txTo[0], 0);
93         BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 1: %d", i));
94         BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
95
96         keys.assign(1,key[1]);
97         keys.push_back(key[i]);
98         s = sign_multisig(a_and_b, keys, txTo[0], 0);
99         BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 2: %d", i));
100         BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
101     }
102
103     // Test a OR b:
104     for (int i = 0; i < 4; i++)
105     {
106         keys.assign(1,key[i]);
107         s = sign_multisig(a_or_b, keys, txTo[1], 0);
108         if (i == 0 || i == 1)
109         {
110             BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
111             BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
112         }
113         else
114         {
115             BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
116             BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
117         }
118     }
119     s.clear();
120     s << OP_0 << OP_1;
121     BOOST_CHECK(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err));
122     BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
123
124
125     for (int i = 0; i < 4; i++)
126         for (int j = 0; j < 4; j++)
127         {
128             keys.assign(1,key[i]);
129             keys.push_back(key[j]);
130             s = sign_multisig(escrow, keys, txTo[2], 0);
131             if (i < j && i < 3 && j < 3)
132             {
133                 BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j));
134                 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
135             }
136             else
137             {
138                 BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j));
139                 BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
140             }
141         }
142 }
143
144 BOOST_AUTO_TEST_CASE(multisig_IsStandard)
145 {
146     CKey key[4];
147     for (int i = 0; i < 4; i++)
148         key[i].MakeNewKey(true);
149
150     txnouttype whichType;
151
152     CScript a_and_b;
153     a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
154     BOOST_CHECK(::IsStandard(a_and_b, whichType));
155
156     CScript a_or_b;
157     a_or_b  << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
158     BOOST_CHECK(::IsStandard(a_or_b, whichType));
159
160     CScript escrow;
161     escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
162     BOOST_CHECK(::IsStandard(escrow, whichType));
163
164     CScript one_of_four;
165     one_of_four << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << ToByteVector(key[3].GetPubKey()) << OP_4 << OP_CHECKMULTISIG;
166     BOOST_CHECK(!::IsStandard(one_of_four, whichType));
167
168     CScript malformed[6];
169     malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
170     malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
171     malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
172     malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0 << OP_CHECKMULTISIG;
173     malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
174     malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
175
176     for (int i = 0; i < 6; i++)
177         BOOST_CHECK(!::IsStandard(malformed[i], whichType));
178 }
179
180 BOOST_AUTO_TEST_CASE(multisig_Solver1)
181 {
182     // Tests Solver() that returns lists of keys that are
183     // required to satisfy a ScriptPubKey
184     //
185     // Also tests IsMine() and ExtractDestination()
186     //
187     // Note: ExtractDestination for the multisignature transactions
188     // always returns false for this release, even if you have
189     // one key that would satisfy an (a|b) or 2-of-3 keys needed
190     // to spend an escrow transaction.
191     //
192     CBasicKeyStore keystore, emptykeystore, partialkeystore;
193     CKey key[3];
194     CTxDestination keyaddr[3];
195     for (int i = 0; i < 3; i++)
196     {
197         key[i].MakeNewKey(true);
198         keystore.AddKey(key[i]);
199         keyaddr[i] = key[i].GetPubKey().GetID();
200     }
201     partialkeystore.AddKey(key[0]);
202
203     {
204         vector<valtype> solutions;
205         txnouttype whichType;
206         CScript s;
207         s << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
208         BOOST_CHECK(Solver(s, whichType, solutions));
209         BOOST_CHECK(solutions.size() == 1);
210         CTxDestination addr;
211         BOOST_CHECK(ExtractDestination(s, addr));
212         BOOST_CHECK(addr == keyaddr[0]);
213 #ifdef ENABLE_WALLET
214         BOOST_CHECK(IsMine(keystore, s));
215         BOOST_CHECK(!IsMine(emptykeystore, s));
216 #endif
217     }
218     {
219         vector<valtype> solutions;
220         txnouttype whichType;
221         CScript s;
222         s << OP_DUP << OP_HASH160 << ToByteVector(key[0].GetPubKey().GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
223         BOOST_CHECK(Solver(s, whichType, solutions));
224         BOOST_CHECK(solutions.size() == 1);
225         CTxDestination addr;
226         BOOST_CHECK(ExtractDestination(s, addr));
227         BOOST_CHECK(addr == keyaddr[0]);
228 #ifdef ENABLE_WALLET
229         BOOST_CHECK(IsMine(keystore, s));
230         BOOST_CHECK(!IsMine(emptykeystore, s));
231 #endif
232     }
233     {
234         vector<valtype> solutions;
235         txnouttype whichType;
236         CScript s;
237         s << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
238         BOOST_CHECK(Solver(s, whichType, solutions));
239         BOOST_CHECK_EQUAL(solutions.size(), 4U);
240         CTxDestination addr;
241         BOOST_CHECK(!ExtractDestination(s, addr));
242 #ifdef ENABLE_WALLET
243         BOOST_CHECK(IsMine(keystore, s));
244         BOOST_CHECK(!IsMine(emptykeystore, s));
245         BOOST_CHECK(!IsMine(partialkeystore, s));
246 #endif
247     }
248     {
249         vector<valtype> solutions;
250         txnouttype whichType;
251         CScript s;
252         s << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
253         BOOST_CHECK(Solver(s, whichType, solutions));
254         BOOST_CHECK_EQUAL(solutions.size(), 4U);
255         vector<CTxDestination> addrs;
256         int nRequired;
257         BOOST_CHECK(ExtractDestinations(s, whichType, addrs, nRequired));
258         BOOST_CHECK(addrs[0] == keyaddr[0]);
259         BOOST_CHECK(addrs[1] == keyaddr[1]);
260         BOOST_CHECK(nRequired == 1);
261 #ifdef ENABLE_WALLET
262         BOOST_CHECK(IsMine(keystore, s));
263         BOOST_CHECK(!IsMine(emptykeystore, s));
264         BOOST_CHECK(!IsMine(partialkeystore, s));
265 #endif
266     }
267     {
268         vector<valtype> solutions;
269         txnouttype whichType;
270         CScript s;
271         s << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
272         BOOST_CHECK(Solver(s, whichType, solutions));
273         BOOST_CHECK(solutions.size() == 5);
274     }
275 }
276
277 BOOST_AUTO_TEST_CASE(multisig_Sign)
278 {
279     // Test SignSignature() (and therefore the version of Solver() that signs transactions)
280     CBasicKeyStore keystore;
281     CKey key[4];
282     for (int i = 0; i < 4; i++)
283     {
284         key[i].MakeNewKey(true);
285         keystore.AddKey(key[i]);
286     }
287
288     CScript a_and_b;
289     a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
290
291     CScript a_or_b;
292     a_or_b  << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
293
294     CScript escrow;
295     escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
296
297     CMutableTransaction txFrom;  // Funding transaction
298     txFrom.vout.resize(3);
299     txFrom.vout[0].scriptPubKey = a_and_b;
300     txFrom.vout[1].scriptPubKey = a_or_b;
301     txFrom.vout[2].scriptPubKey = escrow;
302
303     CMutableTransaction txTo[3]; // Spending transaction
304     for (int i = 0; i < 3; i++)
305     {
306         txTo[i].vin.resize(1);
307         txTo[i].vout.resize(1);
308         txTo[i].vin[0].prevout.n = i;
309         txTo[i].vin[0].prevout.hash = txFrom.GetTxid();
310         txTo[i].vout[0].nValue = 1;
311     }
312
313     for (int i = 0; i < 3; i++)
314     {
315         BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
316     }
317 }
318
319
320 BOOST_AUTO_TEST_SUITE_END()
This page took 0.034335 seconds and 2 git commands to generate.