You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sighash_tests.cpp 7.0KB

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