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