1 #include <boost/assert.hpp>
2 #include <boost/assign/list_of.hpp>
3 #include <boost/assign/list_inserter.hpp>
4 #include <boost/assign/std/vector.hpp>
5 #include <boost/test/unit_test.hpp>
6 #include <boost/foreach.hpp>
7 #include <boost/tuple/tuple.hpp>
9 #include <openssl/ec.h>
10 #include <openssl/err.h>
18 using namespace boost::assign;
20 typedef vector<unsigned char> valtype;
22 extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
23 extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int nHashType);
24 extern bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType);
25 extern bool Solver(const CScript& scriptPubKey, vector<vector<pair<opcodetype, valtype> > >& vSolutionsRet);
27 BOOST_AUTO_TEST_SUITE(multisig_tests)
30 sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn)
32 uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL);
35 result << OP_0; // CHECKMULTISIG bug workaround
36 BOOST_FOREACH(CKey key, keys)
38 vector<unsigned char> vchSig;
39 BOOST_CHECK(key.Sign(hash, vchSig));
40 vchSig.push_back((unsigned char)SIGHASH_ALL);
46 BOOST_AUTO_TEST_CASE(multisig_verify)
49 for (int i = 0; i < 4; i++)
53 a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
56 a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
59 escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
61 CTransaction txFrom; // Funding transaction
62 txFrom.vout.resize(3);
63 txFrom.vout[0].scriptPubKey = a_and_b;
64 txFrom.vout[1].scriptPubKey = a_or_b;
65 txFrom.vout[2].scriptPubKey = escrow;
67 CTransaction txTo[3]; // Spending transaction
68 for (int i = 0; i < 3; i++)
70 txTo[i].vin.resize(1);
71 txTo[i].vout.resize(1);
72 txTo[i].vin[0].prevout.n = i;
73 txTo[i].vin[0].prevout.hash = txFrom.GetHash();
74 txTo[i].vout[0].nValue = 1;
82 keys += key[0],key[1]; // magic operator+= from boost.assign
83 s = sign_multisig(a_and_b, keys, txTo[0], 0);
84 BOOST_CHECK(VerifyScript(s, a_and_b, txTo[0], 0, 0));
86 for (int i = 0; i < 4; i++)
90 s = sign_multisig(a_and_b, keys, txTo[0], 0);
91 BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, 0), strprintf("a&b 1: %d", i));
94 keys += key[1],key[i];
95 s = sign_multisig(a_and_b, keys, txTo[0], 0);
96 BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, 0), strprintf("a&b 2: %d", i));
100 for (int i = 0; i < 4; i++)
104 s = sign_multisig(a_or_b, keys, txTo[1], 0);
105 if (i == 0 || i == 1)
106 BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, txTo[1], 0, 0), strprintf("a|b: %d", i));
108 BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, 0), strprintf("a|b: %d", i));
112 BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, 0));
115 BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, 0));
118 for (int i = 0; i < 4; i++)
119 for (int j = 0; j < 4; j++)
122 keys += key[i],key[j];
123 s = sign_multisig(escrow, keys, txTo[2], 0);
124 if (i < j && i < 3 && j < 3)
125 BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, txTo[2], 0, 0), strprintf("escrow 1: %d %d", i, j));
127 BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, 0), strprintf("escrow 2: %d %d", i, j));
131 BOOST_AUTO_TEST_CASE(multisig_IsStandard)
134 for (int i = 0; i < 3; i++)
138 a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
139 BOOST_CHECK(::IsStandard(a_and_b));
142 a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
143 BOOST_CHECK(::IsStandard(a_or_b));
146 escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
147 BOOST_CHECK(::IsStandard(escrow));
150 BOOST_AUTO_TEST_CASE(multisig_Solver1)
152 // Tests Solver() that returns lists of keys that are
153 // required to satisfy a ScriptPubKey
155 // Also tests IsMine() and ExtractAddress()
157 // Note: ExtractAddress for the multisignature transactions
158 // always returns false for this release, even if you have
159 // one key that would satisfy an (a|b) or 2-of-3 keys needed
160 // to spend an escrow transaction.
162 CBasicKeyStore keystore, emptykeystore;
164 CBitcoinAddress keyaddr[3];
165 for (int i = 0; i < 3; i++)
168 keystore.AddKey(key[i]);
169 keyaddr[i].SetPubKey(key[i].GetPubKey());
173 vector<vector<pair<opcodetype, valtype> > > solutions;
175 s << key[0].GetPubKey() << OP_CHECKSIG;
176 BOOST_CHECK(Solver(s, solutions));
177 BOOST_CHECK(solutions.size() == 1);
178 if (solutions.size() == 1)
179 BOOST_CHECK(solutions[0].size() == 1);
180 CBitcoinAddress addr;
181 BOOST_CHECK(ExtractAddress(s, &keystore, addr));
182 BOOST_CHECK(addr == keyaddr[0]);
183 BOOST_CHECK(IsMine(keystore, s));
184 BOOST_CHECK(!IsMine(emptykeystore, s));
187 vector<vector<pair<opcodetype, valtype> > > solutions;
189 s << OP_DUP << OP_HASH160 << Hash160(key[0].GetPubKey()) << OP_EQUALVERIFY << OP_CHECKSIG;
190 BOOST_CHECK(Solver(s, solutions));
191 BOOST_CHECK(solutions.size() == 1);
192 if (solutions.size() == 1)
193 BOOST_CHECK(solutions[0].size() == 1);
194 CBitcoinAddress addr;
195 BOOST_CHECK(ExtractAddress(s, &keystore, addr));
196 BOOST_CHECK(addr == keyaddr[0]);
197 BOOST_CHECK(IsMine(keystore, s));
198 BOOST_CHECK(!IsMine(emptykeystore, s));
201 vector<vector<pair<opcodetype, valtype> > > solutions;
203 s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
204 BOOST_CHECK(Solver(s, solutions));
205 BOOST_CHECK(solutions.size() == 1);
206 if (solutions.size() == 1)
207 BOOST_CHECK(solutions[0].size() == 2);
208 CBitcoinAddress addr;
209 BOOST_CHECK(!ExtractAddress(s, &keystore, addr));
210 BOOST_CHECK(IsMine(keystore, s));
211 BOOST_CHECK(!IsMine(emptykeystore, s));
214 vector<vector<pair<opcodetype, valtype> > > solutions;
216 s << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
217 BOOST_CHECK(Solver(s, solutions));
218 BOOST_CHECK(solutions.size() == 2);
219 if (solutions.size() == 2)
221 BOOST_CHECK(solutions[0].size() == 1);
222 BOOST_CHECK(solutions[1].size() == 1);
224 CBitcoinAddress addr;
225 BOOST_CHECK(ExtractAddress(s, &keystore, addr));
226 BOOST_CHECK(addr == keyaddr[0]);
227 BOOST_CHECK(IsMine(keystore, s));
228 BOOST_CHECK(!IsMine(emptykeystore, s));
231 vector<vector<pair<opcodetype, valtype> > > solutions;
233 s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
234 BOOST_CHECK(Solver(s, solutions));
235 BOOST_CHECK(solutions.size() == 3);
236 if (solutions.size() == 3)
238 BOOST_CHECK(solutions[0].size() == 2);
239 BOOST_CHECK(solutions[1].size() == 2);
240 BOOST_CHECK(solutions[2].size() == 2);
245 BOOST_AUTO_TEST_CASE(multisig_Sign)
247 // Test SignSignature() (and therefore the version of Solver() that signs transactions)
248 CBasicKeyStore keystore;
250 for (int i = 0; i < 4; i++)
253 keystore.AddKey(key[i]);
257 a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
260 a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
263 escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
265 CTransaction txFrom; // Funding transaction
266 txFrom.vout.resize(3);
267 txFrom.vout[0].scriptPubKey = a_and_b;
268 txFrom.vout[1].scriptPubKey = a_or_b;
269 txFrom.vout[2].scriptPubKey = escrow;
271 CTransaction txTo[3]; // Spending transaction
272 for (int i = 0; i < 3; i++)
274 txTo[i].vin.resize(1);
275 txTo[i].vout.resize(1);
276 txTo[i].vin[0].prevout.n = i;
277 txTo[i].vin[0].prevout.hash = txFrom.GetHash();
278 txTo[i].vout[0].nValue = 1;
281 for (int i = 0; i < 3; i++)
283 BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
288 BOOST_AUTO_TEST_SUITE_END()