]> Git Repo - VerusCoin.git/blob - src/test/sighash_tests.cpp
Merge pull request #5520
[VerusCoin.git] / src / test / sighash_tests.cpp
1 // Copyright (c) 2013 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 "data/sighash.json.h"
6 #include "main.h"
7 #include "random.h"
8 #include "serialize.h"
9 #include "script/script.h"
10 #include "script/interpreter.h"
11 #include "util.h"
12 #include "version.h"
13
14 #include <iostream>
15
16 #include <boost/test/unit_test.hpp>
17 #include "json/json_spirit_reader_template.h"
18 #include "json/json_spirit_utils.h"
19 #include "json/json_spirit_writer_template.h"
20
21 using namespace json_spirit;
22 extern Array read_json(const std::string& jsondata);
23
24 // Old script.cpp SignatureHash function
25 uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
26 {
27     static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
28     if (nIn >= txTo.vin.size())
29     {
30         printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
31         return one;
32     }
33     CMutableTransaction txTmp(txTo);
34
35     // In case concatenating two scripts ends up with two codeseparators,
36     // or an extra one at the end, this prevents all those possible incompatibilities.
37     scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR));
38
39     // Blank out other inputs' signatures
40     for (unsigned int i = 0; i < txTmp.vin.size(); i++)
41         txTmp.vin[i].scriptSig = CScript();
42     txTmp.vin[nIn].scriptSig = scriptCode;
43
44     // Blank out some of the outputs
45     if ((nHashType & 0x1f) == SIGHASH_NONE)
46     {
47         // Wildcard payee
48         txTmp.vout.clear();
49
50         // Let the others update at will
51         for (unsigned int i = 0; i < txTmp.vin.size(); i++)
52             if (i != nIn)
53                 txTmp.vin[i].nSequence = 0;
54     }
55     else if ((nHashType & 0x1f) == SIGHASH_SINGLE)
56     {
57         // Only lock-in the txout payee at same index as txin
58         unsigned int nOut = nIn;
59         if (nOut >= txTmp.vout.size())
60         {
61             printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
62             return one;
63         }
64         txTmp.vout.resize(nOut+1);
65         for (unsigned int i = 0; i < nOut; i++)
66             txTmp.vout[i].SetNull();
67
68         // Let the others update at will
69         for (unsigned int i = 0; i < txTmp.vin.size(); i++)
70             if (i != nIn)
71                 txTmp.vin[i].nSequence = 0;
72     }
73
74     // Blank out other inputs completely, not recommended for open transactions
75     if (nHashType & SIGHASH_ANYONECANPAY)
76     {
77         txTmp.vin[0] = txTmp.vin[nIn];
78         txTmp.vin.resize(1);
79     }
80
81     // Serialize and hash
82     CHashWriter ss(SER_GETHASH, 0);
83     ss << txTmp << nHashType;
84     return ss.GetHash();
85 }
86
87 void static RandomScript(CScript &script) {
88     static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR};
89     script = CScript();
90     int ops = (insecure_rand() % 10);
91     for (int i=0; i<ops; i++)
92         script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))];
93 }
94
95 void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
96     tx.nVersion = insecure_rand();
97     tx.vin.clear();
98     tx.vout.clear();
99     tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0;
100     int ins = (insecure_rand() % 4) + 1;
101     int outs = fSingle ? ins : (insecure_rand() % 4) + 1;
102     for (int in = 0; in < ins; in++) {
103         tx.vin.push_back(CTxIn());
104         CTxIn &txin = tx.vin.back();
105         txin.prevout.hash = GetRandHash();
106         txin.prevout.n = insecure_rand() % 4;
107         RandomScript(txin.scriptSig);
108         txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1;
109     }
110     for (int out = 0; out < outs; out++) {
111         tx.vout.push_back(CTxOut());
112         CTxOut &txout = tx.vout.back();
113         txout.nValue = insecure_rand() % 100000000;
114         RandomScript(txout.scriptPubKey);
115     }
116 }
117
118 BOOST_AUTO_TEST_SUITE(sighash_tests)
119
120 BOOST_AUTO_TEST_CASE(sighash_test)
121 {
122     seed_insecure_rand(false);
123
124     #if defined(PRINT_SIGHASH_JSON)
125     std::cout << "[\n";
126     std::cout << "\t[\"raw_transaction, script, input_index, hashType, signature_hash (result)\"],\n";
127     #endif
128     int nRandomTests = 50000;
129
130     #if defined(PRINT_SIGHASH_JSON)
131     nRandomTests = 500;
132     #endif
133     for (int i=0; i<nRandomTests; i++) {
134         int nHashType = insecure_rand();
135         CMutableTransaction txTo;
136         RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
137         CScript scriptCode;
138         RandomScript(scriptCode);
139         int nIn = insecure_rand() % txTo.vin.size();
140
141         uint256 sh, sho;
142         sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
143         sh = SignatureHash(scriptCode, txTo, nIn, nHashType);
144         #if defined(PRINT_SIGHASH_JSON)
145         CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
146         ss << txTo;
147
148         std::cout << "\t[\"" ;
149         std::cout << HexStr(ss.begin(), ss.end()) << "\", \"";
150         std::cout << HexStr(scriptCode) << "\", ";
151         std::cout << nIn << ", ";
152         std::cout << nHashType << ", \"";
153         std::cout << sho.GetHex() << "\"]";
154         if (i+1 != nRandomTests) {
155           std::cout << ",";
156         }
157         std::cout << "\n";
158         #endif
159         BOOST_CHECK(sh == sho);
160     }
161     #if defined(PRINT_SIGHASH_JSON)
162     std::cout << "]\n";
163     #endif
164 }
165
166 // Goal: check that SignatureHash generates correct hash
167 BOOST_AUTO_TEST_CASE(sighash_from_data)
168 {
169     Array tests = read_json(std::string(json_tests::sighash, json_tests::sighash + sizeof(json_tests::sighash)));
170
171     BOOST_FOREACH(Value& tv, tests)
172     {
173         Array test = tv.get_array();
174         std::string strTest = write_string(tv, false);
175         if (test.size() < 1) // Allow for extra stuff (useful for comments)
176         {
177             BOOST_ERROR("Bad test: " << strTest);
178             continue;
179         }
180         if (test.size() == 1) continue; // comment
181
182         std::string raw_tx, raw_script, sigHashHex;
183         int nIn, nHashType;
184         uint256 sh;
185         CTransaction tx;
186         CScript scriptCode = CScript();
187
188         try {
189           // deserialize test data
190           raw_tx = test[0].get_str();
191           raw_script = test[1].get_str();
192           nIn = test[2].get_int();
193           nHashType = test[3].get_int();
194           sigHashHex = test[4].get_str();
195
196           uint256 sh;
197           CDataStream stream(ParseHex(raw_tx), SER_NETWORK, PROTOCOL_VERSION);
198           stream >> tx;
199
200           CValidationState state;
201           BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
202           BOOST_CHECK(state.IsValid());
203
204           std::vector<unsigned char> raw = ParseHex(raw_script);
205           scriptCode.insert(scriptCode.end(), raw.begin(), raw.end());
206         } catch (...) {
207           BOOST_ERROR("Bad test, couldn't deserialize data: " << strTest);
208           continue;
209         }
210
211         sh = SignatureHash(scriptCode, tx, nIn, nHashType);
212         BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
213     }
214 }
215 BOOST_AUTO_TEST_SUITE_END()
This page took 0.03572 seconds and 4 git commands to generate.