Line data Source code
1 : // Copyright (c) 2011-2020 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 <policy/policy.h>
7 : #include <script/interpreter.h>
8 : #include <script/script.h>
9 : #include <script/script_error.h>
10 : #include <script/sign.h>
11 : #include <script/signingprovider.h>
12 : #include <test/util/setup_common.h>
13 : #include <tinyformat.h>
14 : #include <uint256.h>
15 :
16 :
17 : #include <boost/test/unit_test.hpp>
18 :
19 89 : BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
20 :
21 : static CScript
22 29 : sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& keys, const CTransaction& transaction, int whichIn)
23 : {
24 29 : uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SigVersion::BASE);
25 :
26 29 : CScript result;
27 29 : result << OP_0; // CHECKMULTISIG bug workaround
28 79 : for (const CKey &key : keys)
29 : {
30 50 : std::vector<unsigned char> vchSig;
31 50 : BOOST_CHECK(key.Sign(hash, vchSig));
32 50 : vchSig.push_back((unsigned char)SIGHASH_ALL);
33 50 : result << vchSig;
34 50 : }
35 : return result;
36 29 : }
37 :
38 95 : BOOST_AUTO_TEST_CASE(multisig_verify)
39 : {
40 : unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
41 :
42 1 : ScriptError err;
43 4 : CKey key[4];
44 1 : CAmount amount = 0;
45 5 : for (int i = 0; i < 4; i++)
46 4 : key[i].MakeNewKey(true);
47 :
48 1 : CScript a_and_b;
49 1 : a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
50 :
51 1 : CScript a_or_b;
52 1 : a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
53 :
54 1 : CScript escrow;
55 1 : escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
56 :
57 1 : CMutableTransaction txFrom; // Funding transaction
58 1 : txFrom.vout.resize(3);
59 1 : txFrom.vout[0].scriptPubKey = a_and_b;
60 1 : txFrom.vout[1].scriptPubKey = a_or_b;
61 1 : txFrom.vout[2].scriptPubKey = escrow;
62 :
63 3 : CMutableTransaction txTo[3]; // Spending transaction
64 4 : for (int i = 0; i < 3; i++)
65 : {
66 3 : txTo[i].vin.resize(1);
67 3 : txTo[i].vout.resize(1);
68 3 : txTo[i].vin[0].prevout.n = i;
69 3 : txTo[i].vin[0].prevout.hash = txFrom.GetHash();
70 3 : txTo[i].vout[0].nValue = 1;
71 : }
72 :
73 1 : std::vector<CKey> keys;
74 1 : CScript s;
75 :
76 : // Test a AND b:
77 1 : keys.assign(1,key[0]);
78 1 : keys.push_back(key[1]);
79 1 : s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
80 1 : BOOST_CHECK(VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err));
81 1 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
82 :
83 5 : for (int i = 0; i < 4; i++)
84 : {
85 4 : keys.assign(1,key[i]);
86 4 : s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
87 4 : BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i));
88 4 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
89 :
90 4 : keys.assign(1,key[1]);
91 4 : keys.push_back(key[i]);
92 4 : s = sign_multisig(a_and_b, keys, CTransaction(txTo[0]), 0);
93 4 : BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i));
94 4 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
95 : }
96 :
97 : // Test a OR b:
98 5 : for (int i = 0; i < 4; i++)
99 : {
100 4 : keys.assign(1,key[i]);
101 4 : s = sign_multisig(a_or_b, keys, CTransaction(txTo[1]), 0);
102 4 : if (i == 0 || i == 1)
103 : {
104 2 : BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
105 2 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
106 : }
107 : else
108 : {
109 2 : BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
110 2 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
111 : }
112 : }
113 1 : s.clear();
114 1 : s << OP_0 << OP_1;
115 1 : BOOST_CHECK(!VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err));
116 1 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
117 :
118 :
119 5 : for (int i = 0; i < 4; i++)
120 20 : for (int j = 0; j < 4; j++)
121 : {
122 16 : keys.assign(1,key[i]);
123 16 : keys.push_back(key[j]);
124 16 : s = sign_multisig(escrow, keys, CTransaction(txTo[2]), 0);
125 16 : if (i < j && i < 3 && j < 3)
126 : {
127 3 : BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j));
128 3 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
129 : }
130 : else
131 : {
132 13 : BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 2: %d %d", i, j));
133 13 : BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
134 : }
135 : }
136 6 : }
137 :
138 95 : BOOST_AUTO_TEST_CASE(multisig_IsStandard)
139 : {
140 4 : CKey key[4];
141 5 : for (int i = 0; i < 4; i++)
142 4 : key[i].MakeNewKey(true);
143 :
144 1 : TxoutType whichType;
145 :
146 1 : CScript a_and_b;
147 1 : a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
148 1 : BOOST_CHECK(::IsStandard(a_and_b, whichType));
149 :
150 1 : CScript a_or_b;
151 1 : a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
152 1 : BOOST_CHECK(::IsStandard(a_or_b, whichType));
153 :
154 1 : CScript escrow;
155 1 : escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
156 1 : BOOST_CHECK(::IsStandard(escrow, whichType));
157 :
158 1 : CScript one_of_four;
159 1 : 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;
160 1 : BOOST_CHECK(!::IsStandard(one_of_four, whichType));
161 :
162 6 : CScript malformed[6];
163 1 : malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
164 1 : malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
165 1 : malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
166 1 : malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0 << OP_CHECKMULTISIG;
167 1 : malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
168 1 : malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
169 :
170 7 : for (int i = 0; i < 6; i++)
171 6 : BOOST_CHECK(!::IsStandard(malformed[i], whichType));
172 9 : }
173 :
174 95 : BOOST_AUTO_TEST_CASE(multisig_Sign)
175 : {
176 : // Test SignSignature() (and therefore the version of Solver() that signs transactions)
177 1 : FillableSigningProvider keystore;
178 4 : CKey key[4];
179 5 : for (int i = 0; i < 4; i++)
180 : {
181 4 : key[i].MakeNewKey(true);
182 4 : BOOST_CHECK(keystore.AddKey(key[i]));
183 : }
184 :
185 1 : CScript a_and_b;
186 1 : a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
187 :
188 1 : CScript a_or_b;
189 1 : a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
190 :
191 1 : CScript escrow;
192 1 : escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
193 :
194 1 : CMutableTransaction txFrom; // Funding transaction
195 1 : txFrom.vout.resize(3);
196 1 : txFrom.vout[0].scriptPubKey = a_and_b;
197 1 : txFrom.vout[1].scriptPubKey = a_or_b;
198 1 : txFrom.vout[2].scriptPubKey = escrow;
199 :
200 3 : CMutableTransaction txTo[3]; // Spending transaction
201 4 : for (int i = 0; i < 3; i++)
202 : {
203 3 : txTo[i].vin.resize(1);
204 3 : txTo[i].vout.resize(1);
205 3 : txTo[i].vin[0].prevout.n = i;
206 3 : txTo[i].vin[0].prevout.hash = txFrom.GetHash();
207 3 : txTo[i].vout[0].nValue = 1;
208 : }
209 :
210 4 : for (int i = 0; i < 3; i++)
211 : {
212 3 : BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom), txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
213 : }
214 6 : }
215 :
216 :
217 89 : BOOST_AUTO_TEST_SUITE_END()
|