Line data Source code
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 "policy/policy.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 1 : BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
27 :
28 : CScript
29 29 : sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn)
30 : {
31 29 : uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL);
32 :
33 : CScript result;
34 29 : result << OP_0; // CHECKMULTISIG bug workaround
35 424 : BOOST_FOREACH(const CKey &key, keys)
36 : {
37 : vector<unsigned char> vchSig;
38 400 : BOOST_CHECK(key.Sign(hash, vchSig));
39 50 : vchSig.push_back((unsigned char)SIGHASH_ALL);
40 50 : result << vchSig;
41 : }
42 29 : return result;
43 : }
44 :
45 6 : BOOST_AUTO_TEST_CASE(multisig_verify)
46 : {
47 1 : unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
48 :
49 : ScriptError err;
50 5 : CKey key[4];
51 4 : for (int i = 0; i < 4; i++)
52 4 : key[i].MakeNewKey(true);
53 :
54 : CScript a_and_b;
55 3 : a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
56 :
57 : CScript a_or_b;
58 3 : a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
59 :
60 : CScript escrow;
61 4 : escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
62 :
63 1 : CMutableTransaction txFrom; // Funding transaction
64 2 : txFrom.vout.resize(3);
65 1 : txFrom.vout[0].scriptPubKey = a_and_b;
66 1 : txFrom.vout[1].scriptPubKey = a_or_b;
67 1 : txFrom.vout[2].scriptPubKey = escrow;
68 :
69 7 : CMutableTransaction txTo[3]; // Spending transaction
70 3 : for (int i = 0; i < 3; i++)
71 : {
72 6 : txTo[i].vin.resize(1);
73 6 : txTo[i].vout.resize(1);
74 3 : txTo[i].vin[0].prevout.n = i;
75 3 : txTo[i].vin[0].prevout.hash = txFrom.GetHash();
76 3 : txTo[i].vout[0].nValue = 1;
77 : }
78 :
79 1 : vector<CKey> keys;
80 : CScript s;
81 :
82 : // Test a AND b:
83 : keys.assign(1,key[0]);
84 1 : keys.push_back(key[1]);
85 5 : s = sign_multisig(a_and_b, keys, txTo[0], 0);
86 8 : BOOST_CHECK(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err));
87 7 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
88 :
89 5 : for (int i = 0; i < 4; i++)
90 : {
91 4 : keys.assign(1,key[i]);
92 20 : s = sign_multisig(a_and_b, keys, txTo[0], 0);
93 32 : BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 1: %d", i));
94 28 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
95 :
96 : keys.assign(1,key[1]);
97 4 : keys.push_back(key[i]);
98 20 : s = sign_multisig(a_and_b, keys, txTo[0], 0);
99 32 : BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0), &err), strprintf("a&b 2: %d", i));
100 28 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
101 : }
102 :
103 : // Test a OR b:
104 5 : for (int i = 0; i < 4; i++)
105 : {
106 4 : keys.assign(1,key[i]);
107 20 : s = sign_multisig(a_or_b, keys, txTo[1], 0);
108 4 : if (i == 0 || i == 1)
109 : {
110 16 : BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
111 14 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
112 : }
113 : else
114 : {
115 16 : BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err), strprintf("a|b: %d", i));
116 14 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
117 : }
118 : }
119 : s.clear();
120 1 : s << OP_0 << OP_1;
121 8 : BOOST_CHECK(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0), &err));
122 7 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
123 :
124 :
125 5 : for (int i = 0; i < 4; i++)
126 20 : for (int j = 0; j < 4; j++)
127 : {
128 16 : keys.assign(1,key[i]);
129 16 : keys.push_back(key[j]);
130 80 : s = sign_multisig(escrow, keys, txTo[2], 0);
131 16 : if (i < j && i < 3 && j < 3)
132 : {
133 24 : BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 1: %d %d", i, j));
134 21 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
135 : }
136 : else
137 : {
138 104 : BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0), &err), strprintf("escrow 2: %d %d", i, j));
139 91 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
140 : }
141 5 : }
142 1 : }
143 :
144 6 : BOOST_AUTO_TEST_CASE(multisig_IsStandard)
145 : {
146 5 : CKey key[4];
147 4 : for (int i = 0; i < 4; i++)
148 4 : key[i].MakeNewKey(true);
149 :
150 : txnouttype whichType;
151 :
152 : CScript a_and_b;
153 3 : a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
154 8 : BOOST_CHECK(::IsStandard(a_and_b, whichType));
155 :
156 : CScript a_or_b;
157 3 : a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
158 8 : BOOST_CHECK(::IsStandard(a_or_b, whichType));
159 :
160 : CScript escrow;
161 4 : escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
162 7 : BOOST_CHECK(::IsStandard(escrow, whichType));
163 :
164 : CScript one_of_four;
165 5 : 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 8 : BOOST_CHECK(!::IsStandard(one_of_four, whichType));
167 :
168 13 : CScript malformed[6];
169 3 : malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
170 3 : malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
171 3 : malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
172 3 : malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0 << OP_CHECKMULTISIG;
173 3 : malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
174 3 : malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
175 :
176 7 : for (int i = 0; i < 6; i++)
177 53 : BOOST_CHECK(!::IsStandard(malformed[i], whichType));
178 1 : }
179 :
180 6 : 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 2 : CBasicKeyStore keystore, emptykeystore, partialkeystore;
193 7 : CKey key[3];
194 7 : CTxDestination keyaddr[3];
195 3 : for (int i = 0; i < 3; i++)
196 : {
197 3 : key[i].MakeNewKey(true);
198 3 : keystore.AddKey(key[i]);
199 6 : keyaddr[i] = key[i].GetPubKey().GetID();
200 : }
201 1 : partialkeystore.AddKey(key[0]);
202 :
203 : {
204 : vector<valtype> solutions;
205 : txnouttype whichType;
206 : CScript s;
207 2 : s << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
208 8 : BOOST_CHECK(Solver(s, whichType, solutions));
209 9 : BOOST_CHECK(solutions.size() == 1);
210 : CTxDestination addr;
211 8 : BOOST_CHECK(ExtractDestination(s, addr));
212 8 : BOOST_CHECK(addr == keyaddr[0]);
213 : #ifdef ENABLE_WALLET
214 8 : BOOST_CHECK(IsMine(keystore, s));
215 9 : BOOST_CHECK(!IsMine(emptykeystore, s));
216 : #endif
217 : }
218 : {
219 : vector<valtype> solutions;
220 : txnouttype whichType;
221 : CScript s;
222 3 : s << OP_DUP << OP_HASH160 << ToByteVector(key[0].GetPubKey().GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
223 8 : BOOST_CHECK(Solver(s, whichType, solutions));
224 9 : BOOST_CHECK(solutions.size() == 1);
225 : CTxDestination addr;
226 8 : BOOST_CHECK(ExtractDestination(s, addr));
227 8 : BOOST_CHECK(addr == keyaddr[0]);
228 : #ifdef ENABLE_WALLET
229 8 : BOOST_CHECK(IsMine(keystore, s));
230 9 : BOOST_CHECK(!IsMine(emptykeystore, s));
231 : #endif
232 : }
233 : {
234 : vector<valtype> solutions;
235 : txnouttype whichType;
236 : CScript s;
237 3 : s << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
238 8 : BOOST_CHECK(Solver(s, whichType, solutions));
239 6 : BOOST_CHECK_EQUAL(solutions.size(), 4U);
240 : CTxDestination addr;
241 8 : BOOST_CHECK(!ExtractDestination(s, addr));
242 : #ifdef ENABLE_WALLET
243 8 : BOOST_CHECK(IsMine(keystore, s));
244 8 : BOOST_CHECK(!IsMine(emptykeystore, s));
245 9 : BOOST_CHECK(!IsMine(partialkeystore, s));
246 : #endif
247 : }
248 : {
249 : vector<valtype> solutions;
250 : txnouttype whichType;
251 : CScript s;
252 3 : s << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
253 8 : BOOST_CHECK(Solver(s, whichType, solutions));
254 6 : BOOST_CHECK_EQUAL(solutions.size(), 4U);
255 1 : vector<CTxDestination> addrs;
256 : int nRequired;
257 8 : BOOST_CHECK(ExtractDestinations(s, whichType, addrs, nRequired));
258 8 : BOOST_CHECK(addrs[0] == keyaddr[0]);
259 9 : BOOST_CHECK(addrs[1] == keyaddr[1]);
260 8 : BOOST_CHECK(nRequired == 1);
261 : #ifdef ENABLE_WALLET
262 8 : BOOST_CHECK(IsMine(keystore, s));
263 8 : BOOST_CHECK(!IsMine(emptykeystore, s));
264 9 : BOOST_CHECK(!IsMine(partialkeystore, s));
265 : #endif
266 : }
267 : {
268 : vector<valtype> solutions;
269 : txnouttype whichType;
270 : CScript s;
271 4 : s << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
272 8 : BOOST_CHECK(Solver(s, whichType, solutions));
273 10 : BOOST_CHECK(solutions.size() == 5);
274 1 : }
275 1 : }
276 :
277 6 : BOOST_AUTO_TEST_CASE(multisig_Sign)
278 : {
279 : // Test SignSignature() (and therefore the version of Solver() that signs transactions)
280 1 : CBasicKeyStore keystore;
281 9 : CKey key[4];
282 4 : for (int i = 0; i < 4; i++)
283 : {
284 4 : key[i].MakeNewKey(true);
285 4 : keystore.AddKey(key[i]);
286 : }
287 :
288 : CScript a_and_b;
289 3 : a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
290 :
291 : CScript a_or_b;
292 3 : a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
293 :
294 : CScript escrow;
295 4 : escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
296 :
297 1 : CMutableTransaction txFrom; // Funding transaction
298 2 : txFrom.vout.resize(3);
299 1 : txFrom.vout[0].scriptPubKey = a_and_b;
300 1 : txFrom.vout[1].scriptPubKey = a_or_b;
301 1 : txFrom.vout[2].scriptPubKey = escrow;
302 :
303 7 : CMutableTransaction txTo[3]; // Spending transaction
304 3 : for (int i = 0; i < 3; i++)
305 : {
306 6 : txTo[i].vin.resize(1);
307 6 : txTo[i].vout.resize(1);
308 3 : txTo[i].vin[0].prevout.n = i;
309 3 : txTo[i].vin[0].prevout.hash = txFrom.GetHash();
310 3 : txTo[i].vout[0].nValue = 1;
311 : }
312 :
313 4 : for (int i = 0; i < 3; i++)
314 : {
315 27 : BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
316 1 : }
317 1 : }
318 :
319 :
320 3 : BOOST_AUTO_TEST_SUITE_END()
|