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