Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
multisig_tests.cpp
Go to the documentation of this file.
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>
8 
9 #include <openssl/ec.h>
10 #include <openssl/err.h>
11 
12 #include "keystore.h"
13 #include "main.h"
14 #include "script.h"
15 #include "wallet.h"
16 
17 using namespace std;
18 using namespace boost::assign;
19 
20 typedef vector<unsigned char> valtype;
21 
22 extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
23 
24 BOOST_AUTO_TEST_SUITE(multisig_tests)
25 
26 CScript
27 sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn)
28 {
29  uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL);
30 
31  CScript result;
32  result << OP_0; // CHECKMULTISIG bug workaround
33  BOOST_FOREACH(const CKey &key, keys)
34  {
35  vector<unsigned char> vchSig;
36  BOOST_CHECK(key.Sign(hash, vchSig));
37  vchSig.push_back((unsigned char)SIGHASH_ALL);
38  result << vchSig;
39  }
40  return result;
41 }
42 
43 BOOST_AUTO_TEST_CASE(multisig_verify)
44 {
45  unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
46 
47  CKey key[4];
48  for (int i = 0; i < 4; i++)
49  key[i].MakeNewKey(true);
50 
51  CScript a_and_b;
52  a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
53 
54  CScript a_or_b;
55  a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
56 
57  CScript escrow;
58  escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
59 
60  CTransaction txFrom; // Funding transaction
61  txFrom.vout.resize(3);
62  txFrom.vout[0].scriptPubKey = a_and_b;
63  txFrom.vout[1].scriptPubKey = a_or_b;
64  txFrom.vout[2].scriptPubKey = escrow;
65 
66  CTransaction txTo[3]; // Spending transaction
67  for (int i = 0; i < 3; i++)
68  {
69  txTo[i].vin.resize(1);
70  txTo[i].vout.resize(1);
71  txTo[i].vin[0].prevout.n = i;
72  txTo[i].vin[0].prevout.hash = txFrom.GetHash();
73  txTo[i].vout[0].nValue = 1;
74  }
75 
76  vector<CKey> keys;
77  CScript s;
78 
79  // Test a AND b:
80  keys.clear();
81  keys += key[0],key[1]; // magic operator+= from boost.assign
82  s = sign_multisig(a_and_b, keys, txTo[0], 0);
83  BOOST_CHECK(VerifyScript(s, a_and_b, txTo[0], 0, flags, 0));
84 
85  for (int i = 0; i < 4; i++)
86  {
87  keys.clear();
88  keys += key[i];
89  s = sign_multisig(a_and_b, keys, txTo[0], 0);
90  BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, flags, 0), strprintf("a&b 1: %d", i));
91 
92  keys.clear();
93  keys += key[1],key[i];
94  s = sign_multisig(a_and_b, keys, txTo[0], 0);
95  BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, flags, 0), strprintf("a&b 2: %d", i));
96  }
97 
98  // Test a OR b:
99  for (int i = 0; i < 4; i++)
100  {
101  keys.clear();
102  keys += key[i];
103  s = sign_multisig(a_or_b, keys, txTo[1], 0);
104  if (i == 0 || i == 1)
105  BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, txTo[1], 0, flags, 0), strprintf("a|b: %d", i));
106  else
107  BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, flags, 0), strprintf("a|b: %d", i));
108  }
109  s.clear();
110  s << OP_0 << OP_0;
111  BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, flags, 0));
112  s.clear();
113  s << OP_0 << OP_1;
114  BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, flags, 0));
115 
116 
117  for (int i = 0; i < 4; i++)
118  for (int j = 0; j < 4; j++)
119  {
120  keys.clear();
121  keys += key[i],key[j];
122  s = sign_multisig(escrow, keys, txTo[2], 0);
123  if (i < j && i < 3 && j < 3)
124  BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, txTo[2], 0, flags, 0), strprintf("escrow 1: %d %d", i, j));
125  else
126  BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, flags, 0), strprintf("escrow 2: %d %d", i, j));
127  }
128 }
129 
130 BOOST_AUTO_TEST_CASE(multisig_IsStandard)
131 {
132  CKey key[4];
133  for (int i = 0; i < 4; i++)
134  key[i].MakeNewKey(true);
135 
136  CScript a_and_b;
137  a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
138  BOOST_CHECK(::IsStandard(a_and_b));
139 
140  CScript a_or_b;
141  a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
142  BOOST_CHECK(::IsStandard(a_or_b));
143 
144  CScript escrow;
145  escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
146  BOOST_CHECK(::IsStandard(escrow));
147 
148  CScript one_of_four;
149  one_of_four << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << key[3].GetPubKey() << OP_4 << OP_CHECKMULTISIG;
150  BOOST_CHECK(!::IsStandard(one_of_four));
151 
152  CScript malformed[6];
153  malformed[0] << OP_3 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
154  malformed[1] << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
155  malformed[2] << OP_0 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
156  malformed[3] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_0 << OP_CHECKMULTISIG;
157  malformed[4] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_CHECKMULTISIG;
158  malformed[5] << OP_1 << key[0].GetPubKey() << key[1].GetPubKey();
159 
160  for (int i = 0; i < 6; i++)
161  BOOST_CHECK(!::IsStandard(malformed[i]));
162 }
163 
164 BOOST_AUTO_TEST_CASE(multisig_Solver1)
165 {
166  // Tests Solver() that returns lists of keys that are
167  // required to satisfy a ScriptPubKey
168  //
169  // Also tests IsMine() and ExtractAddress()
170  //
171  // Note: ExtractAddress for the multisignature transactions
172  // always returns false for this release, even if you have
173  // one key that would satisfy an (a|b) or 2-of-3 keys needed
174  // to spend an escrow transaction.
175  //
176  CBasicKeyStore keystore, emptykeystore, partialkeystore;
177  CKey key[3];
178  CTxDestination keyaddr[3];
179  for (int i = 0; i < 3; i++)
180  {
181  key[i].MakeNewKey(true);
182  keystore.AddKey(key[i]);
183  keyaddr[i] = key[i].GetPubKey().GetID();
184  }
185  partialkeystore.AddKey(key[0]);
186 
187  {
188  vector<valtype> solutions;
189  txnouttype whichType;
190  CScript s;
191  s << key[0].GetPubKey() << OP_CHECKSIG;
192  BOOST_CHECK(Solver(s, whichType, solutions));
193  BOOST_CHECK(solutions.size() == 1);
194  CTxDestination addr;
195  BOOST_CHECK(ExtractDestination(s, addr));
196  BOOST_CHECK(addr == keyaddr[0]);
197  BOOST_CHECK(IsMine(keystore, s));
198  BOOST_CHECK(!IsMine(emptykeystore, s));
199  }
200  {
201  vector<valtype> solutions;
202  txnouttype whichType;
203  CScript s;
204  s << OP_DUP << OP_HASH160 << key[0].GetPubKey().GetID() << OP_EQUALVERIFY << OP_CHECKSIG;
205  BOOST_CHECK(Solver(s, whichType, solutions));
206  BOOST_CHECK(solutions.size() == 1);
207  CTxDestination addr;
208  BOOST_CHECK(ExtractDestination(s, addr));
209  BOOST_CHECK(addr == keyaddr[0]);
210  BOOST_CHECK(IsMine(keystore, s));
211  BOOST_CHECK(!IsMine(emptykeystore, s));
212  }
213  {
214  vector<valtype> solutions;
215  txnouttype whichType;
216  CScript s;
217  s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
218  BOOST_CHECK(Solver(s, whichType, solutions));
219  BOOST_CHECK_EQUAL(solutions.size(), 4U);
220  CTxDestination addr;
221  BOOST_CHECK(!ExtractDestination(s, addr));
222  BOOST_CHECK(IsMine(keystore, s));
223  BOOST_CHECK(!IsMine(emptykeystore, s));
224  BOOST_CHECK(!IsMine(partialkeystore, s));
225  }
226  {
227  vector<valtype> solutions;
228  txnouttype whichType;
229  CScript s;
230  s << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
231  BOOST_CHECK(Solver(s, whichType, solutions));
232  BOOST_CHECK_EQUAL(solutions.size(), 4U);
233  vector<CTxDestination> addrs;
234  int nRequired;
235  BOOST_CHECK(ExtractDestinations(s, whichType, addrs, nRequired));
236  BOOST_CHECK(addrs[0] == keyaddr[0]);
237  BOOST_CHECK(addrs[1] == keyaddr[1]);
238  BOOST_CHECK(nRequired == 1);
239  BOOST_CHECK(IsMine(keystore, s));
240  BOOST_CHECK(!IsMine(emptykeystore, s));
241  BOOST_CHECK(!IsMine(partialkeystore, s));
242  }
243  {
244  vector<valtype> solutions;
245  txnouttype whichType;
246  CScript s;
247  s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
248  BOOST_CHECK(Solver(s, whichType, solutions));
249  BOOST_CHECK(solutions.size() == 5);
250  }
251 }
252 
253 BOOST_AUTO_TEST_CASE(multisig_Sign)
254 {
255  // Test SignSignature() (and therefore the version of Solver() that signs transactions)
256  CBasicKeyStore keystore;
257  CKey key[4];
258  for (int i = 0; i < 4; i++)
259  {
260  key[i].MakeNewKey(true);
261  keystore.AddKey(key[i]);
262  }
263 
264  CScript a_and_b;
265  a_and_b << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
266 
267  CScript a_or_b;
268  a_or_b << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
269 
270  CScript escrow;
271  escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
272 
273  CTransaction txFrom; // Funding transaction
274  txFrom.vout.resize(3);
275  txFrom.vout[0].scriptPubKey = a_and_b;
276  txFrom.vout[1].scriptPubKey = a_or_b;
277  txFrom.vout[2].scriptPubKey = escrow;
278 
279  CTransaction txTo[3]; // Spending transaction
280  for (int i = 0; i < 3; i++)
281  {
282  txTo[i].vin.resize(1);
283  txTo[i].vout.resize(1);
284  txTo[i].vin[0].prevout.n = i;
285  txTo[i].vin[0].prevout.hash = txFrom.GetHash();
286  txTo[i].vout[0].nValue = 1;
287  }
288 
289  for (int i = 0; i < 3; i++)
290  {
291  BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
292  }
293 }
294 
295 
296 BOOST_AUTO_TEST_SUITE_END()
Definition: script.h:81
#define strprintf(format,...)
Definition: util.h:169
Definition: script.h:79
bool VerifyScript(const CScript &scriptSig, const CScript &scriptPubKey, const CTransaction &txTo, unsigned int nIn, unsigned int flags, int nHashType)
Definition: script.cpp:1477
bool SignSignature(const CKeyStore &keystore, const CScript &fromPubKey, CTransaction &txTo, unsigned int nIn, int nHashType)
Definition: script.cpp:1519
Definition: script.h:80
uint256 GetHash() const
Definition: main.h:515
bool Sign(const uint256 &hash, std::vector< unsigned char > &vchSig) const
Definition: key.cpp:321
uint256 SignatureHash(CScript scriptCode, const CTransaction &txTo, unsigned int nIn, int nHashType)
Definition: script.cpp:966
CPubKey GetPubKey() const
Definition: key.cpp:312
std::vector< CTxOut > vout
Definition: main.h:485
txnouttype
Definition: script.h:40
std::vector< CTxIn > vin
Definition: main.h:484
Definition: script.h:77
void MakeNewKey(bool fCompressed)
Definition: key.cpp:285
bool Solver(const CScript &scriptPubKey, txnouttype &typeRet, vector< vector< unsigned char > > &vSolutionsRet)
Definition: script.cpp:1127
virtual bool AddKey(const CKey &key)
Definition: keystore.cpp:18
CScript sign_multisig(CScript scriptPubKey, vector< CKey > keys, CTransaction transaction, int whichIn)
256-bit unsigned integer
Definition: uint256.h:537
bool ExtractDestinations(const CScript &scriptPubKey, txnouttype &typeRet, vector< CTxDestination > &addressRet, int &nRequiredRet)
Definition: script.cpp:1448
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:244
bool IsMine(const CKeyStore &keystore, const CTxDestination &dest)
Definition: script.cpp:1378
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Definition: script.cpp:1422
bool IsStandard(const CScript &scriptPubKey)
Definition: script.cpp:1332
BOOST_AUTO_TEST_CASE(multisig_verify)
vector< unsigned char > valtype
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
Definition: script.h:62
An encapsulated private key.
Definition: key.h:172
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: main.h:477
CKeyID GetID() const
Definition: key.h:129
Definition: script.h:70
uint32_t hash
Definition: cache.cc:34
Basic key store, that keeps keys in an address->secret map.
Definition: keystore.h:43
Definition: script.h:119