1 // Copyright (c) 2013-2017 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/tx_verify.h>
6 #include <consensus/validation.h>
7 #include <test/data/sighash.json.h>
9 #include <script/interpreter.h>
10 #include <script/script.h>
11 #include <serialize.h>
13 #include <test/test_bitcoin.h>
15 #include <utilstrencodings.h>
20 #include <boost/test/unit_test.hpp>
24 extern UniValue
read_json(const std::string
& jsondata
);
26 // Old script.cpp SignatureHash function
27 uint256
static SignatureHashOld(CScript scriptCode
, const CTransaction
& txTo
, unsigned int nIn
, int nHashType
)
29 static const uint256
one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
30 if (nIn
>= txTo
.vin
.size())
34 CMutableTransaction
txTmp(txTo
);
36 // In case concatenating two scripts ends up with two codeseparators,
37 // or an extra one at the end, this prevents all those possible incompatibilities.
38 scriptCode
.FindAndDelete(CScript(OP_CODESEPARATOR
));
40 // Blank out other inputs' signatures
41 for (unsigned int i
= 0; i
< txTmp
.vin
.size(); i
++)
42 txTmp
.vin
[i
].scriptSig
= CScript();
43 txTmp
.vin
[nIn
].scriptSig
= scriptCode
;
45 // Blank out some of the outputs
46 if ((nHashType
& 0x1f) == SIGHASH_NONE
)
51 // Let the others update at will
52 for (unsigned int i
= 0; i
< txTmp
.vin
.size(); i
++)
54 txTmp
.vin
[i
].nSequence
= 0;
56 else if ((nHashType
& 0x1f) == SIGHASH_SINGLE
)
58 // Only lock-in the txout payee at same index as txin
59 unsigned int nOut
= nIn
;
60 if (nOut
>= txTmp
.vout
.size())
64 txTmp
.vout
.resize(nOut
+1);
65 for (unsigned int i
= 0; i
< nOut
; i
++)
66 txTmp
.vout
[i
].SetNull();
68 // Let the others update at will
69 for (unsigned int i
= 0; i
< txTmp
.vin
.size(); i
++)
71 txTmp
.vin
[i
].nSequence
= 0;
74 // Blank out other inputs completely, not recommended for open transactions
75 if (nHashType
& SIGHASH_ANYONECANPAY
)
77 txTmp
.vin
[0] = txTmp
.vin
[nIn
];
82 CHashWriter
ss(SER_GETHASH
, SERIALIZE_TRANSACTION_NO_WITNESS
);
83 ss
<< txTmp
<< nHashType
;
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
};
90 int ops
= (InsecureRandRange(10));
91 for (int i
=0; i
<ops
; i
++)
92 script
<< oplist
[InsecureRandRange(sizeof(oplist
)/sizeof(oplist
[0]))];
95 void static RandomTransaction(CMutableTransaction
&tx
, bool fSingle
) {
96 tx
.nVersion
= InsecureRand32();
99 tx
.nLockTime
= (InsecureRandBool()) ? InsecureRand32() : 0;
100 int ins
= (InsecureRandBits(2)) + 1;
101 int outs
= fSingle
? ins
: (InsecureRandBits(2)) + 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
= InsecureRand256();
106 txin
.prevout
.n
= InsecureRandBits(2);
107 RandomScript(txin
.scriptSig
);
108 txin
.nSequence
= (InsecureRandBool()) ? InsecureRand32() : (unsigned int)-1;
110 for (int out
= 0; out
< outs
; out
++) {
111 tx
.vout
.push_back(CTxOut());
112 CTxOut
&txout
= tx
.vout
.back();
113 txout
.nValue
= InsecureRandRange(100000000);
114 RandomScript(txout
.scriptPubKey
);
118 BOOST_FIXTURE_TEST_SUITE(sighash_tests
, BasicTestingSetup
)
120 BOOST_AUTO_TEST_CASE(sighash_test
)
122 SeedInsecureRand(false);
124 #if defined(PRINT_SIGHASH_JSON)
126 std::cout
<< "\t[\"raw_transaction, script, input_index, hashType, signature_hash (result)\"],\n";
127 int nRandomTests
= 500;
129 int nRandomTests
= 50000;
131 for (int i
=0; i
<nRandomTests
; i
++) {
132 int nHashType
= InsecureRand32();
133 CMutableTransaction txTo
;
134 RandomTransaction(txTo
, (nHashType
& 0x1f) == SIGHASH_SINGLE
);
136 RandomScript(scriptCode
);
137 int nIn
= InsecureRandRange(txTo
.vin
.size());
140 sho
= SignatureHashOld(scriptCode
, txTo
, nIn
, nHashType
);
141 sh
= SignatureHash(scriptCode
, txTo
, nIn
, nHashType
, 0, SIGVERSION_BASE
);
142 #if defined(PRINT_SIGHASH_JSON)
143 CDataStream
ss(SER_NETWORK
, PROTOCOL_VERSION
);
146 std::cout
<< "\t[\"" ;
147 std::cout
<< HexStr(ss
.begin(), ss
.end()) << "\", \"";
148 std::cout
<< HexStr(scriptCode
) << "\", ";
149 std::cout
<< nIn
<< ", ";
150 std::cout
<< nHashType
<< ", \"";
151 std::cout
<< sho
.GetHex() << "\"]";
152 if (i
+1 != nRandomTests
) {
157 BOOST_CHECK(sh
== sho
);
159 #if defined(PRINT_SIGHASH_JSON)
164 // Goal: check that SignatureHash generates correct hash
165 BOOST_AUTO_TEST_CASE(sighash_from_data
)
167 UniValue tests
= read_json(std::string(json_tests::sighash
, json_tests::sighash
+ sizeof(json_tests::sighash
)));
169 for (unsigned int idx
= 0; idx
< tests
.size(); idx
++) {
170 UniValue test
= tests
[idx
];
171 std::string strTest
= test
.write();
172 if (test
.size() < 1) // Allow for extra stuff (useful for comments)
174 BOOST_ERROR("Bad test: " << strTest
);
177 if (test
.size() == 1) continue; // comment
179 std::string raw_tx
, raw_script
, sigHashHex
;
183 CScript scriptCode
= CScript();
186 // deserialize test data
187 raw_tx
= test
[0].get_str();
188 raw_script
= test
[1].get_str();
189 nIn
= test
[2].get_int();
190 nHashType
= test
[3].get_int();
191 sigHashHex
= test
[4].get_str();
193 CDataStream
stream(ParseHex(raw_tx
), SER_NETWORK
, PROTOCOL_VERSION
);
196 CValidationState state
;
197 BOOST_CHECK_MESSAGE(CheckTransaction(*tx
, state
), strTest
);
198 BOOST_CHECK(state
.IsValid());
200 std::vector
<unsigned char> raw
= ParseHex(raw_script
);
201 scriptCode
.insert(scriptCode
.end(), raw
.begin(), raw
.end());
203 BOOST_ERROR("Bad test, couldn't deserialize data: " << strTest
);
207 sh
= SignatureHash(scriptCode
, *tx
, nIn
, nHashType
, 0, SIGVERSION_BASE
);
208 BOOST_CHECK_MESSAGE(sh
.GetHex() == sigHashHex
, strTest
);
211 BOOST_AUTO_TEST_SUITE_END()