3d1c218700d9856e29fb6d09bdca559a57d5a222
[novacoin.git] / src / test / script_tests.cpp
1 #include <vector>
2 #include <boost/test/unit_test.hpp>
3 #include <boost/foreach.hpp>
4
5 #include "main.h"
6 #include "wallet.h"
7
8 using namespace std;
9 extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
10 extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int& nSigOps, int nHashType);
11 extern bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType);
12
13 BOOST_AUTO_TEST_SUITE(script_tests)
14
15 BOOST_AUTO_TEST_CASE(script_PushData)
16 {
17     // Check that PUSHDATA1, PUSHDATA2, and PUSHDATA4 create the same value on
18     // the stack as the 1-75 opcodes do.
19     static const unsigned char direct[] = { 1, 0x5a };
20     static const unsigned char pushdata1[] = { OP_PUSHDATA1, 1, 0x5a };
21     static const unsigned char pushdata2[] = { OP_PUSHDATA2, 1, 0, 0x5a };
22     static const unsigned char pushdata4[] = { OP_PUSHDATA4, 1, 0, 0, 0, 0x5a };
23
24     int nUnused = 0;
25
26     vector<vector<unsigned char> > directStack;
27     BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), CTransaction(), 0, 0, nUnused));
28
29     vector<vector<unsigned char> > pushdata1Stack;
30     BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), CTransaction(), 0, 0, nUnused));
31     BOOST_CHECK(pushdata1Stack == directStack);
32
33     vector<vector<unsigned char> > pushdata2Stack;
34     BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), CTransaction(), 0, 0, nUnused));
35     BOOST_CHECK(pushdata2Stack == directStack);
36
37     vector<vector<unsigned char> > pushdata4Stack;
38     BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), CTransaction(), 0, 0, nUnused));
39     BOOST_CHECK(pushdata4Stack == directStack);
40 }
41
42 CScript
43 sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction)
44 {
45     uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL);
46
47     CScript result;
48     //
49     // NOTE: CHECKMULTISIG has an unfortunate bug; it requires
50     // one extra item on the stack, before the signatures.
51     // Putting OP_0 on the stack is the workaround;
52     // fixing the bug would mean splitting the blockchain (old
53     // clients would not accept new CHECKMULTISIG transactions,
54     // and vice-versa)
55     //
56     result << OP_0;
57     BOOST_FOREACH(CKey key, keys)
58     {
59         vector<unsigned char> vchSig;
60         BOOST_CHECK(key.Sign(hash, vchSig));
61         vchSig.push_back((unsigned char)SIGHASH_ALL);
62         result << vchSig;
63     }
64     return result;
65 }
66 CScript
67 sign_multisig(CScript scriptPubKey, CKey key, CTransaction transaction)
68 {
69     std::vector<CKey> keys;
70     keys.push_back(key);
71     return sign_multisig(scriptPubKey, keys, transaction);
72 }
73
74 BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
75 {
76     int nUnused = 0;
77     CKey key1, key2, key3;
78     key1.MakeNewKey();
79     key2.MakeNewKey();
80     key3.MakeNewKey();
81
82     CScript scriptPubKey12;
83     scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG;
84
85     CTransaction txFrom12;
86     txFrom12.vout.resize(1);
87     txFrom12.vout[0].scriptPubKey = scriptPubKey12;
88
89     CTransaction txTo12;
90     txTo12.vin.resize(1);
91     txTo12.vout.resize(1);
92     txTo12.vin[0].prevout.n = 0;
93     txTo12.vin[0].prevout.hash = txFrom12.GetHash();
94     txTo12.vout[0].nValue = 1;
95
96     CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
97     BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, nUnused, 0));
98     txTo12.vout[0].nValue = 2;
99     BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, nUnused, 0));
100
101     CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
102     BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, nUnused, 0));
103
104     CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
105     BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, nUnused, 0));
106 }
107
108 BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
109 {
110     int nUnused = 0;
111     CKey key1, key2, key3, key4;
112     key1.MakeNewKey();
113     key2.MakeNewKey();
114     key3.MakeNewKey();
115     key4.MakeNewKey();
116
117     CScript scriptPubKey23;
118     scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG;
119
120     CTransaction txFrom23;
121     txFrom23.vout.resize(1);
122     txFrom23.vout[0].scriptPubKey = scriptPubKey23;
123
124     CTransaction txTo23;
125     txTo23.vin.resize(1);
126     txTo23.vout.resize(1);
127     txTo23.vin[0].prevout.n = 0;
128     txTo23.vin[0].prevout.hash = txFrom23.GetHash();
129     txTo23.vout[0].nValue = 1;
130
131     std::vector<CKey> keys;
132     keys.push_back(key1); keys.push_back(key2);
133     CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
134     BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, nUnused, 0));
135
136     keys.clear();
137     keys.push_back(key1); keys.push_back(key3);
138     CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
139     BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, nUnused, 0));
140
141     keys.clear();
142     keys.push_back(key2); keys.push_back(key3);
143     CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
144     BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, nUnused, 0));
145
146     keys.clear();
147     keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
148     CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
149     BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, nUnused, 0));
150
151     keys.clear();
152     keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
153     CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
154     BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, nUnused, 0));
155
156     keys.clear();
157     keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
158     CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
159     BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, nUnused, 0));
160
161     keys.clear();
162     keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
163     CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
164     BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, nUnused, 0));
165
166     keys.clear();
167     keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
168     CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
169     BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, nUnused, 0));
170
171     keys.clear(); // Must have signatures
172     CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
173     BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, nUnused, 0));
174 }    
175
176
177 BOOST_AUTO_TEST_SUITE_END()