mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-02-04 11:14:16 +00:00
92fd887fd4
Make sure that chainparams and logging is properly initialized. Doing this for every test may be overkill, but this initialization is so simple that that does not matter. This should fix the travis issues.
217 lines
7.0 KiB
C++
217 lines
7.0 KiB
C++
// Copyright (c) 2013 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include "data/sighash.json.h"
|
|
#include "main.h"
|
|
#include "random.h"
|
|
#include "serialize.h"
|
|
#include "script/script.h"
|
|
#include "script/interpreter.h"
|
|
#include "util.h"
|
|
#include "version.h"
|
|
#include "test/test_bitcoin.h"
|
|
|
|
#include <iostream>
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
#include "json/json_spirit_reader_template.h"
|
|
#include "json/json_spirit_utils.h"
|
|
#include "json/json_spirit_writer_template.h"
|
|
|
|
using namespace json_spirit;
|
|
extern Array read_json(const std::string& jsondata);
|
|
|
|
// Old script.cpp SignatureHash function
|
|
uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
|
|
{
|
|
static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
|
if (nIn >= txTo.vin.size())
|
|
{
|
|
printf("ERROR: SignatureHash(): nIn=%d out of range\n", nIn);
|
|
return one;
|
|
}
|
|
CMutableTransaction txTmp(txTo);
|
|
|
|
// In case concatenating two scripts ends up with two codeseparators,
|
|
// or an extra one at the end, this prevents all those possible incompatibilities.
|
|
scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR));
|
|
|
|
// Blank out other inputs' signatures
|
|
for (unsigned int i = 0; i < txTmp.vin.size(); i++)
|
|
txTmp.vin[i].scriptSig = CScript();
|
|
txTmp.vin[nIn].scriptSig = scriptCode;
|
|
|
|
// Blank out some of the outputs
|
|
if ((nHashType & 0x1f) == SIGHASH_NONE)
|
|
{
|
|
// Wildcard payee
|
|
txTmp.vout.clear();
|
|
|
|
// Let the others update at will
|
|
for (unsigned int i = 0; i < txTmp.vin.size(); i++)
|
|
if (i != nIn)
|
|
txTmp.vin[i].nSequence = 0;
|
|
}
|
|
else if ((nHashType & 0x1f) == SIGHASH_SINGLE)
|
|
{
|
|
// Only lock-in the txout payee at same index as txin
|
|
unsigned int nOut = nIn;
|
|
if (nOut >= txTmp.vout.size())
|
|
{
|
|
printf("ERROR: SignatureHash(): nOut=%d out of range\n", nOut);
|
|
return one;
|
|
}
|
|
txTmp.vout.resize(nOut+1);
|
|
for (unsigned int i = 0; i < nOut; i++)
|
|
txTmp.vout[i].SetNull();
|
|
|
|
// Let the others update at will
|
|
for (unsigned int i = 0; i < txTmp.vin.size(); i++)
|
|
if (i != nIn)
|
|
txTmp.vin[i].nSequence = 0;
|
|
}
|
|
|
|
// Blank out other inputs completely, not recommended for open transactions
|
|
if (nHashType & SIGHASH_ANYONECANPAY)
|
|
{
|
|
txTmp.vin[0] = txTmp.vin[nIn];
|
|
txTmp.vin.resize(1);
|
|
}
|
|
|
|
// Serialize and hash
|
|
CHashWriter ss(SER_GETHASH, 0);
|
|
ss << txTmp << nHashType;
|
|
return ss.GetHash();
|
|
}
|
|
|
|
void static RandomScript(CScript &script) {
|
|
static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR};
|
|
script = CScript();
|
|
int ops = (insecure_rand() % 10);
|
|
for (int i=0; i<ops; i++)
|
|
script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))];
|
|
}
|
|
|
|
void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
|
|
tx.nVersion = insecure_rand();
|
|
tx.vin.clear();
|
|
tx.vout.clear();
|
|
tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0;
|
|
int ins = (insecure_rand() % 4) + 1;
|
|
int outs = fSingle ? ins : (insecure_rand() % 4) + 1;
|
|
for (int in = 0; in < ins; in++) {
|
|
tx.vin.push_back(CTxIn());
|
|
CTxIn &txin = tx.vin.back();
|
|
txin.prevout.hash = GetRandHash();
|
|
txin.prevout.n = insecure_rand() % 4;
|
|
RandomScript(txin.scriptSig);
|
|
txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1;
|
|
}
|
|
for (int out = 0; out < outs; out++) {
|
|
tx.vout.push_back(CTxOut());
|
|
CTxOut &txout = tx.vout.back();
|
|
txout.nValue = insecure_rand() % 100000000;
|
|
RandomScript(txout.scriptPubKey);
|
|
}
|
|
}
|
|
|
|
BOOST_FIXTURE_TEST_SUITE(sighash_tests, BasicTestingSetup)
|
|
|
|
BOOST_AUTO_TEST_CASE(sighash_test)
|
|
{
|
|
seed_insecure_rand(false);
|
|
|
|
#if defined(PRINT_SIGHASH_JSON)
|
|
std::cout << "[\n";
|
|
std::cout << "\t[\"raw_transaction, script, input_index, hashType, signature_hash (result)\"],\n";
|
|
#endif
|
|
int nRandomTests = 50000;
|
|
|
|
#if defined(PRINT_SIGHASH_JSON)
|
|
nRandomTests = 500;
|
|
#endif
|
|
for (int i=0; i<nRandomTests; i++) {
|
|
int nHashType = insecure_rand();
|
|
CMutableTransaction txTo;
|
|
RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
|
|
CScript scriptCode;
|
|
RandomScript(scriptCode);
|
|
int nIn = insecure_rand() % txTo.vin.size();
|
|
|
|
uint256 sh, sho;
|
|
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
|
|
sh = SignatureHash(scriptCode, txTo, nIn, nHashType);
|
|
#if defined(PRINT_SIGHASH_JSON)
|
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
|
ss << txTo;
|
|
|
|
std::cout << "\t[\"" ;
|
|
std::cout << HexStr(ss.begin(), ss.end()) << "\", \"";
|
|
std::cout << HexStr(scriptCode) << "\", ";
|
|
std::cout << nIn << ", ";
|
|
std::cout << nHashType << ", \"";
|
|
std::cout << sho.GetHex() << "\"]";
|
|
if (i+1 != nRandomTests) {
|
|
std::cout << ",";
|
|
}
|
|
std::cout << "\n";
|
|
#endif
|
|
BOOST_CHECK(sh == sho);
|
|
}
|
|
#if defined(PRINT_SIGHASH_JSON)
|
|
std::cout << "]\n";
|
|
#endif
|
|
}
|
|
|
|
// Goal: check that SignatureHash generates correct hash
|
|
BOOST_AUTO_TEST_CASE(sighash_from_data)
|
|
{
|
|
Array tests = read_json(std::string(json_tests::sighash, json_tests::sighash + sizeof(json_tests::sighash)));
|
|
|
|
BOOST_FOREACH(Value& tv, tests)
|
|
{
|
|
Array test = tv.get_array();
|
|
std::string strTest = write_string(tv, false);
|
|
if (test.size() < 1) // Allow for extra stuff (useful for comments)
|
|
{
|
|
BOOST_ERROR("Bad test: " << strTest);
|
|
continue;
|
|
}
|
|
if (test.size() == 1) continue; // comment
|
|
|
|
std::string raw_tx, raw_script, sigHashHex;
|
|
int nIn, nHashType;
|
|
uint256 sh;
|
|
CTransaction tx;
|
|
CScript scriptCode = CScript();
|
|
|
|
try {
|
|
// deserialize test data
|
|
raw_tx = test[0].get_str();
|
|
raw_script = test[1].get_str();
|
|
nIn = test[2].get_int();
|
|
nHashType = test[3].get_int();
|
|
sigHashHex = test[4].get_str();
|
|
|
|
uint256 sh;
|
|
CDataStream stream(ParseHex(raw_tx), SER_NETWORK, PROTOCOL_VERSION);
|
|
stream >> tx;
|
|
|
|
CValidationState state;
|
|
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
|
|
BOOST_CHECK(state.IsValid());
|
|
|
|
std::vector<unsigned char> raw = ParseHex(raw_script);
|
|
scriptCode.insert(scriptCode.end(), raw.begin(), raw.end());
|
|
} catch (...) {
|
|
BOOST_ERROR("Bad test, couldn't deserialize data: " << strTest);
|
|
continue;
|
|
}
|
|
|
|
sh = SignatureHash(scriptCode, tx, nIn, nHashType);
|
|
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
|
|
}
|
|
}
|
|
BOOST_AUTO_TEST_SUITE_END()
|