1 // Copyright (c) 2013-2016 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.
5 #include "consensus/validation.h"
6 #include "data/sighash.json.h"
8 #include "validation.h" // For CheckTransaction
9 #include "script/interpreter.h"
10 #include "script/script.h"
11 #include "serialize.h"
13 #include "test/test_bitcoin.h"
14 #include "test/test_random.h"
16 #include "utilstrencodings.h"
21 #include <boost/test/unit_test.hpp>
25 extern UniValue
read_json(const std::string
& jsondata
);
27 // Old script.cpp SignatureHash function
28 uint256
static SignatureHashOld(CScript scriptCode
, const CTransaction
& txTo
, unsigned int nIn
, int nHashType
)
30 static const uint256
one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
31 if (nIn
>= txTo
.vin
.size())
33 printf("ERROR: SignatureHash(): nIn=%d out of range\n", nIn
);
36 CMutableTransaction
txTmp(txTo
);
38 // In case concatenating two scripts ends up with two codeseparators,
39 // or an extra one at the end, this prevents all those possible incompatibilities.
40 scriptCode
.FindAndDelete(CScript(OP_CODESEPARATOR
));
42 // Blank out other inputs' signatures
43 for (unsigned int i
= 0; i
< txTmp
.vin
.size(); i
++)
44 txTmp
.vin
[i
].scriptSig
= CScript();
45 txTmp
.vin
[nIn
].scriptSig
= scriptCode
;
47 // Blank out some of the outputs
48 if ((nHashType
& 0x1f) == SIGHASH_NONE
)
53 // Let the others update at will
54 for (unsigned int i
= 0; i
< txTmp
.vin
.size(); i
++)
56 txTmp
.vin
[i
].nSequence
= 0;
58 else if ((nHashType
& 0x1f) == SIGHASH_SINGLE
)
60 // Only lock-in the txout payee at same index as txin
61 unsigned int nOut
= nIn
;
62 if (nOut
>= txTmp
.vout
.size())
64 printf("ERROR: SignatureHash(): nOut=%d out of range\n", nOut
);
67 txTmp
.vout
.resize(nOut
+1);
68 for (unsigned int i
= 0; i
< nOut
; i
++)
69 txTmp
.vout
[i
].SetNull();
71 // Let the others update at will
72 for (unsigned int i
= 0; i
< txTmp
.vin
.size(); i
++)
74 txTmp
.vin
[i
].nSequence
= 0;
77 // Blank out other inputs completely, not recommended for open transactions
78 if (nHashType
& SIGHASH_ANYONECANPAY
)
80 txTmp
.vin
[0] = txTmp
.vin
[nIn
];
85 CHashWriter
ss(SER_GETHASH
, SERIALIZE_TRANSACTION_NO_WITNESS
);
86 ss
<< txTmp
<< nHashType
;
90 void static RandomScript(CScript
&script
) {
91 static const opcodetype oplist
[] = {OP_FALSE
, OP_1
, OP_2
, OP_3
, OP_CHECKSIG
, OP_IF
, OP_VERIF
, OP_RETURN
, OP_CODESEPARATOR
};
93 int ops
= (insecure_rand() % 10);
94 for (int i
=0; i
<ops
; i
++)
95 script
<< oplist
[insecure_rand() % (sizeof(oplist
)/sizeof(oplist
[0]))];
98 void static RandomTransaction(CMutableTransaction
&tx
, bool fSingle
) {
99 tx
.nVersion
= insecure_rand();
102 tx
.nLockTime
= (insecure_rand() % 2) ? insecure_rand() : 0;
103 int ins
= (insecure_rand() % 4) + 1;
104 int outs
= fSingle
? ins
: (insecure_rand() % 4) + 1;
105 for (int in
= 0; in
< ins
; in
++) {
106 tx
.vin
.push_back(CTxIn());
107 CTxIn
&txin
= tx
.vin
.back();
108 txin
.prevout
.hash
= GetRandHash();
109 txin
.prevout
.n
= insecure_rand() % 4;
110 RandomScript(txin
.scriptSig
);
111 txin
.nSequence
= (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1;
113 for (int out
= 0; out
< outs
; out
++) {
114 tx
.vout
.push_back(CTxOut());
115 CTxOut
&txout
= tx
.vout
.back();
116 txout
.nValue
= insecure_rand() % 100000000;
117 RandomScript(txout
.scriptPubKey
);
121 BOOST_FIXTURE_TEST_SUITE(sighash_tests
, BasicTestingSetup
)
123 BOOST_AUTO_TEST_CASE(sighash_test
)
125 seed_insecure_rand(false);
127 #if defined(PRINT_SIGHASH_JSON)
129 std::cout
<< "\t[\"raw_transaction, script, input_index, hashType, signature_hash (result)\"],\n";
131 int nRandomTests
= 50000;
133 #if defined(PRINT_SIGHASH_JSON)
136 for (int i
=0; i
<nRandomTests
; i
++) {
137 int nHashType
= insecure_rand();
138 CMutableTransaction txTo
;
139 RandomTransaction(txTo
, (nHashType
& 0x1f) == SIGHASH_SINGLE
);
141 RandomScript(scriptCode
);
142 int nIn
= insecure_rand() % txTo
.vin
.size();
145 sho
= SignatureHashOld(scriptCode
, txTo
, nIn
, nHashType
);
146 sh
= SignatureHash(scriptCode
, txTo
, nIn
, nHashType
, 0, SIGVERSION_BASE
);
147 #if defined(PRINT_SIGHASH_JSON)
148 CDataStream
ss(SER_NETWORK
, PROTOCOL_VERSION
);
151 std::cout
<< "\t[\"" ;
152 std::cout
<< HexStr(ss
.begin(), ss
.end()) << "\", \"";
153 std::cout
<< HexStr(scriptCode
) << "\", ";
154 std::cout
<< nIn
<< ", ";
155 std::cout
<< nHashType
<< ", \"";
156 std::cout
<< sho
.GetHex() << "\"]";
157 if (i
+1 != nRandomTests
) {
162 BOOST_CHECK(sh
== sho
);
164 #if defined(PRINT_SIGHASH_JSON)
169 // Goal: check that SignatureHash generates correct hash
170 BOOST_AUTO_TEST_CASE(sighash_from_data
)
172 UniValue tests
= read_json(std::string(json_tests::sighash
, json_tests::sighash
+ sizeof(json_tests::sighash
)));
174 for (unsigned int idx
= 0; idx
< tests
.size(); idx
++) {
175 UniValue test
= tests
[idx
];
176 std::string strTest
= test
.write();
177 if (test
.size() < 1) // Allow for extra stuff (useful for comments)
179 BOOST_ERROR("Bad test: " << strTest
);
182 if (test
.size() == 1) continue; // comment
184 std::string raw_tx
, raw_script
, sigHashHex
;
188 CScript scriptCode
= CScript();
191 // deserialize test data
192 raw_tx
= test
[0].get_str();
193 raw_script
= test
[1].get_str();
194 nIn
= test
[2].get_int();
195 nHashType
= test
[3].get_int();
196 sigHashHex
= test
[4].get_str();
198 CDataStream
stream(ParseHex(raw_tx
), SER_NETWORK
, PROTOCOL_VERSION
);
201 CValidationState state
;
202 BOOST_CHECK_MESSAGE(CheckTransaction(*tx
, state
), strTest
);
203 BOOST_CHECK(state
.IsValid());
205 std::vector
<unsigned char> raw
= ParseHex(raw_script
);
206 scriptCode
.insert(scriptCode
.end(), raw
.begin(), raw
.end());
208 BOOST_ERROR("Bad test, couldn't deserialize data: " << strTest
);
212 sh
= SignatureHash(scriptCode
, *tx
, nIn
, nHashType
, 0, SIGVERSION_BASE
);
213 BOOST_CHECK_MESSAGE(sh
.GetHex() == sigHashHex
, strTest
);
216 BOOST_AUTO_TEST_SUITE_END()