Projects : bitcoin : bitcoin_dumpblock_no_losers
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 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 | vector<vector<unsigned char> > directStack; |
25 | BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), CTransaction(), 0, 0)); |
26 | |
27 | vector<vector<unsigned char> > pushdata1Stack; |
28 | BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), CTransaction(), 0, 0)); |
29 | BOOST_CHECK(pushdata1Stack == directStack); |
30 | |
31 | vector<vector<unsigned char> > pushdata2Stack; |
32 | BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), CTransaction(), 0, 0)); |
33 | BOOST_CHECK(pushdata2Stack == directStack); |
34 | |
35 | vector<vector<unsigned char> > pushdata4Stack; |
36 | BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), CTransaction(), 0, 0)); |
37 | BOOST_CHECK(pushdata4Stack == directStack); |
38 | } |
39 | |
40 | CScript |
41 | sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction) |
42 | { |
43 | uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL); |
44 | |
45 | CScript result; |
46 | // |
47 | // NOTE: CHECKMULTISIG has an unfortunate bug; it requires |
48 | // one extra item on the stack, before the signatures. |
49 | // Putting OP_0 on the stack is the workaround; |
50 | // fixing the bug would mean splitting the blockchain (old |
51 | // clients would not accept new CHECKMULTISIG transactions, |
52 | // and vice-versa) |
53 | // |
54 | result << OP_0; |
55 | BOOST_FOREACH(CKey key, keys) |
56 | { |
57 | vector<unsigned char> vchSig; |
58 | BOOST_CHECK(key.Sign(hash, vchSig)); |
59 | vchSig.push_back((unsigned char)SIGHASH_ALL); |
60 | result << vchSig; |
61 | } |
62 | return result; |
63 | } |
64 | CScript |
65 | sign_multisig(CScript scriptPubKey, CKey key, CTransaction transaction) |
66 | { |
67 | std::vector<CKey> keys; |
68 | keys.push_back(key); |
69 | return sign_multisig(scriptPubKey, keys, transaction); |
70 | } |
71 | |
72 | BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) |
73 | { |
74 | CKey key1, key2, key3; |
75 | key1.MakeNewKey(); |
76 | key2.MakeNewKey(); |
77 | key3.MakeNewKey(); |
78 | |
79 | CScript scriptPubKey12; |
80 | scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG; |
81 | |
82 | CTransaction txFrom12; |
83 | txFrom12.vout.resize(1); |
84 | txFrom12.vout[0].scriptPubKey = scriptPubKey12; |
85 | |
86 | CTransaction txTo12; |
87 | txTo12.vin.resize(1); |
88 | txTo12.vout.resize(1); |
89 | txTo12.vin[0].prevout.n = 0; |
90 | txTo12.vin[0].prevout.hash = txFrom12.GetHash(); |
91 | txTo12.vout[0].nValue = 1; |
92 | |
93 | CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); |
94 | BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, 0)); |
95 | txTo12.vout[0].nValue = 2; |
96 | BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, 0)); |
97 | |
98 | CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); |
99 | BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, 0)); |
100 | |
101 | CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12); |
102 | BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, 0)); |
103 | } |
104 | |
105 | BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) |
106 | { |
107 | CKey key1, key2, key3, key4; |
108 | key1.MakeNewKey(); |
109 | key2.MakeNewKey(); |
110 | key3.MakeNewKey(); |
111 | key4.MakeNewKey(); |
112 | |
113 | CScript scriptPubKey23; |
114 | scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG; |
115 | |
116 | CTransaction txFrom23; |
117 | txFrom23.vout.resize(1); |
118 | txFrom23.vout[0].scriptPubKey = scriptPubKey23; |
119 | |
120 | CTransaction txTo23; |
121 | txTo23.vin.resize(1); |
122 | txTo23.vout.resize(1); |
123 | txTo23.vin[0].prevout.n = 0; |
124 | txTo23.vin[0].prevout.hash = txFrom23.GetHash(); |
125 | txTo23.vout[0].nValue = 1; |
126 | |
127 | std::vector<CKey> keys; |
128 | keys.push_back(key1); keys.push_back(key2); |
129 | CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); |
130 | BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, 0)); |
131 | |
132 | keys.clear(); |
133 | keys.push_back(key1); keys.push_back(key3); |
134 | CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23); |
135 | BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, 0)); |
136 | |
137 | keys.clear(); |
138 | keys.push_back(key2); keys.push_back(key3); |
139 | CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23); |
140 | BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, 0)); |
141 | |
142 | keys.clear(); |
143 | keys.push_back(key2); keys.push_back(key2); // Can't re-use sig |
144 | CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); |
145 | BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, 0)); |
146 | |
147 | keys.clear(); |
148 | keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order |
149 | CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23); |
150 | BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, 0)); |
151 | |
152 | keys.clear(); |
153 | keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order |
154 | CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23); |
155 | BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, 0)); |
156 | |
157 | keys.clear(); |
158 | keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys |
159 | CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23); |
160 | BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, 0)); |
161 | |
162 | keys.clear(); |
163 | keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys |
164 | CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23); |
165 | BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, 0)); |
166 | |
167 | keys.clear(); // Must have signatures |
168 | CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); |
169 | BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, 0)); |
170 | } |
171 | |
172 | |
173 | BOOST_AUTO_TEST_SUITE_END() |