<NME> test_bitcoin.cpp
<BEF> // Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#define BOOST_TEST_MODULE Firo Test Suite

#if defined(HAVE_CONFIG_H)
#include "../config/bitcoin-config.h"
#endif

#include "test_bitcoin.h"

#include "util.h"
#include "chainparams.h"
#include "consensus/consensus.h"
#include "consensus/validation.h"
#include "key.h"
#include "validation.h"
#include "miner.h"
#include "net_processing.h"
#include "pubkey.h"
#include "random.h"
#include "txdb.h"
#include "txmempool.h"
#include "ui_interface.h"
#include "rpc/server.h"
#include "rpc/register.h"
#include "script/sigcache.h"
#include "stacktraces.h"


    TestingSetup() {
        fPrintToDebugLog = false; // don't want to write to debug.log file
        SelectParams(CBaseChainParams::MAIN);
        noui_connect();
#ifdef ENABLE_WALLET
        bitdb.MakeMock();
#include "../elysium/elysium.h"
#endif

#include <boost/filesystem.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_monitor.hpp>
#include <boost/thread.hpp>
#include "sigma.h"
#include "evo/evodb.h"
#include "evo/cbtx.h"
#include "evo/specialtx.h"
#include "llmq/quorums_init.h"

extern std::unique_ptr<CConnman> g_connman;
uint256 insecure_rand_seed = GetRandHash();
FastRandomContext insecure_rand_ctx(insecure_rand_seed);

extern bool fPrintToConsole;
extern void noui_connect();
extern CEvoDB* evoDb;

BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
{
    ECC_Start();
    SetupEnvironment();
    SetupNetworking();
    InitSignatureCache();
    fPrintToDebugLog = false; // don't want to write to debug.log file
    fCheckBlockIndex = true;
    SelectParams(chainName);
    SoftSetBoolArg("-dandelion", false);
    evoDb = new CEvoDB(1 << 20, true, true);
    deterministicMNManager = new CDeterministicMNManager(*evoDb);
    noui_connect();
}

BasicTestingSetup::~BasicTestingSetup()
{
        delete deterministicMNManager;
        delete evoDb;

        ECC_Stop();
        g_connman.reset();
}

TestingSetup::TestingSetup(const std::string& chainName, std::string suf) : BasicTestingSetup(chainName)
{
    const CChainParams& chainparams = Params();
        // Ideally we'd move all the RPC tests to the functional testing framework
        // instead of unit tests, but for now we need these here.
        RegisterAllCoreRPCCommands(tableRPC);
        ClearDatadirCache();
        pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
        boost::filesystem::create_directories(pathTemp);
        ForceSetArg("-datadir", pathTemp.string());
        mempool.setSanityCheck(1.0);
        pblocktree = new CBlockTreeDB(1 << 20, true);
        pcoinsdbview = new CCoinsViewDB(1 << 23, true);
        llmq::InitLLMQSystem(*evoDb, nullptr, true);
        pcoinsTip = new CCoinsViewCache(pcoinsdbview);
        pwalletMain = new CWallet(std::string("wallet_test.dat"));
        static bool fFirstRun = true;
        pwalletMain->LoadWallet(fFirstRun);

        InitBlockIndex(chainparams);
        {
            CValidationState state;
            bool ok = ActivateBestChain(state, chainparams);
            BOOST_CHECK(ok);
        }
        nScriptCheckThreads = 3;
        for (int i=0; i < nScriptCheckThreads-1; i++)
            threadGroup.create_thread(&ThreadScriptCheck);
        g_connman = std::unique_ptr<CConnman>(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests.
        connman = g_connman.get();
        RegisterNodeSignals(GetNodeSignals());

        // Init HD mint

        // Create new keyUser and set as default key
        // generate a new master key
        CPubKey masterPubKey = pwalletMain->GenerateNewHDMasterKey();
        pwalletMain->SetHDMasterKey(masterPubKey);
        CPubKey newDefaultKey;
        if (pwalletMain->GetKeyFromPool(newDefaultKey)) {
            pwalletMain->SetDefaultKey(newDefaultKey);
            pwalletMain->SetAddressBook(pwalletMain->vchDefaultKey.GetID(), "", "receive");
        }

        pwalletMain->SetBestChain(chainActive.GetLocator());

        pwalletMain->zwallet = std::make_unique<CHDMintWallet>(pwalletMain->strWalletFile);
        pwalletMain->zwallet->GetTracker().Init();
        pwalletMain->zwallet->LoadMintPoolFromDB();
        pwalletMain->zwallet->SyncWithChain();
}

TestingSetup::~TestingSetup()
{
    UnregisterNodeSignals(GetNodeSignals());
    llmq::InterruptLLMQSystem();
    llmq::DestroyLLMQSystem();
#ifdef ENABLE_ELYSIUM
    elysium_shutdown();
#endif
    threadGroup.interrupt_all();
    threadGroup.join_all();
    UnloadBlockIndex();
    delete pwalletMain;
    pwalletMain = NULL;
    delete pcoinsTip;
    delete pcoinsdbview;
    delete pblocktree;
	try {
		boost::filesystem::remove_all(pathTemp);
	}
	catch(...) {
		try {
			MilliSleep(100);
			boost::filesystem::remove_all(std::wstring(L"\\\\?\\") + pathTemp.wstring());
		}
		catch(...) {

		}
	}
    bitdb.RemoveDb("wallet_test.dat");
    bitdb.Reset();
}

TestChain100Setup::TestChain100Setup(int nBlocks) : TestingSetup(CBaseChainParams::REGTEST)
{
    // Generate a 100-block chain:
    coinbaseKey.MakeNewKey(true);
    CScript scriptPubKey = CScript() <<  ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
    for (int i = 0; i < nBlocks; i++)
    {
        std::vector<CMutableTransaction> noTxns;
        CBlock b = CreateAndProcessBlock(noTxns, scriptPubKey);
        coinbaseTxns.push_back(*b.vtx[0]);
    }
}

CBlock TestChain100Setup::CreateBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey)
{
    const CChainParams& chainparams = Params();
    std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
    CBlock& block = pblocktemplate->block;

    std::vector<CTransactionRef> llmqCommitments;
    for (const auto& tx : block.vtx) {
        if (tx->nVersion == 3 && tx->nType == TRANSACTION_QUORUM_COMMITMENT) {
            llmqCommitments.emplace_back(tx);
        }
    }

    // Replace mempool-selected txns with just coinbase plus passed-in txns:
    if (!fAllowMempoolTxsInCreateBlock)
        block.vtx.resize(1);
    // Re-add quorum commitments
    block.vtx.insert(block.vtx.end(), llmqCommitments.begin(), llmqCommitments.end());
    BOOST_FOREACH(const CMutableTransaction& tx, txns)
        block.vtx.push_back(MakeTransactionRef(tx));

    // Manually update CbTx as we modified the block here
    if (block.vtx[0]->nType == TRANSACTION_COINBASE) {
        LOCK(cs_main);
        CCbTx cbTx;
        if (!GetTxPayload(*block.vtx[0], cbTx)) {
            BOOST_ASSERT(false);
        }
        CValidationState state;
        if (!CalcCbTxMerkleRootMNList(block, chainActive.Tip(), cbTx.merkleRootMNList, state)) {
            BOOST_ASSERT(false);
        }
        if (!CalcCbTxMerkleRootQuorums(block, chainActive.Tip(), cbTx.merkleRootQuorums, state)) {
            BOOST_ASSERT(false);
        }
        CMutableTransaction tmpTx = *block.vtx[0];
        SetTxPayload(tmpTx, cbTx);
        block.vtx[0] = MakeTransactionRef(tmpTx);
    }

    // IncrementExtraNonce creates a valid coinbase and merkleRoot
    unsigned int extraNonce = 0;
    IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);

    if (block.IsProgPow()) {
        while (!CheckProofOfWork(progpow_hash_full(block.GetProgPowHeader(), block.mix_hash), block.nBits, chainparams.GetConsensus()))
            ++block.nNonce64;
    }
    else {
        while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
    }

    CBlock result = block;
    return result;
}

CBlock TestChain100Setup::CreateBlock(const std::vector<CMutableTransaction>& txns, const CKey& scriptKey)
{
    CScript scriptPubKey = CScript() <<  ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
    return CreateBlock(txns, scriptPubKey);
}

//
// Create a new block with just given transactions, coinbase paying to
// scriptPubKey, and try to add it to the current chain.
//
CBlock
TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey, bool * processBlockResult)
{
    const CChainParams& chainparams = Params();
    auto block = CreateBlock(txns, scriptPubKey);

    std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
    bool pbr = ProcessNewBlock(chainparams, shared_pblock, true, NULL);
    if(processBlockResult)
        *processBlockResult = pbr;

    CBlock result = block;
    return result;
}

CBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CKey& scriptKey, bool * processBlockResult)
{
    CScript scriptPubKey = CScript() <<  ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
    return CreateAndProcessBlock(txns, scriptPubKey, processBlockResult);
}

TestChain100Setup::~TestChain100Setup()
{
}


CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction &tx, CTxMemPool *pool) {
    CTransaction txn(tx);
    return FromTx(txn, pool);
}

CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn, CTxMemPool *pool) {
    // Hack to assume either it's completely dependent on other mempool txs or not at all
    CAmount inChainValue = pool && pool->HasNoInputsOf(txn) ? txn.GetValueOut() : 0;

    return CTxMemPoolEntry(MakeTransactionRef(txn), nFee, nTime, nHeight,
                           inChainValue, spendsCoinbase, sigOpCost, lp);
}

size_t FindZnodeOutput(CTransaction const & tx) {
    static std::vector<CScript> const founders {
        GetScriptForDestination(CBitcoinAddress("TDk19wPKYq91i18qmY6U9FeTdTxwPeSveo").Get()),
        GetScriptForDestination(CBitcoinAddress("TWZZcDGkNixTAMtRBqzZkkMHbq1G6vUTk5").Get()),
        GetScriptForDestination(CBitcoinAddress("TRZTFdNCKCKbLMQV8cZDkQN9Vwuuq4gDzT").Get()),
        GetScriptForDestination(CBitcoinAddress("TG2ruj59E5b1u9G3F7HQVs6pCcVDBxrQve").Get()),
        GetScriptForDestination(CBitcoinAddress("TCsTzQZKVn4fao8jDmB9zQBk9YQNEZ3XfS").Get()),
    };

    BOOST_CHECK(tx.IsCoinBase());
    for(size_t i = 0; i < tx.vout.size(); ++i) {
        CTxOut const & out = tx.vout[i];
         if(std::find(founders.begin(), founders.end(), out.scriptPubKey) == founders.end()) {
            if(out.nValue == GetZnodePayment(Params().GetConsensus(), false))
                return i;
        }
    }
    throw std::runtime_error("Cannot find the Znode output");
}

/*
void Shutdown(void* parg)
{
  exit(EXIT_SUCCESS);
}

void StartShutdown()
{
  exit(EXIT_SUCCESS);
}

bool ShutdownRequested()
{
  return false;
}
*/

#ifdef ENABLE_CRASH_HOOKS
template<typename T>
void translate_exception(const T &e)
{
    std::cerr << GetPrettyExceptionStr(std::current_exception()) << std::endl;
    throw;
}

template<typename T>
void register_exception_translator()
{
    boost::unit_test::unit_test_monitor.register_exception_translator<T>(&translate_exception<T>);
}

struct ExceptionInitializer {
    ExceptionInitializer()
    {
        RegisterPrettyTerminateHander();
        RegisterPrettySignalHandlers();

        register_exception_translator<std::exception>();
        register_exception_translator<std::string>();
        register_exception_translator<const char*>();
    }
    ~ExceptionInitializer()
    {
    }
};

BOOST_GLOBAL_FIXTURE( ExceptionInitializer );
#endif

<MSG> Switch testing framework from MAIN to new UNITTEST network

UNITTEST inherites from MAIN but allows synamically changing its parameters using the ModifiableParams() interface

<DFF> @@ -31,7 +31,7 @@ struct TestingSetup {
 
     TestingSetup() {
         fPrintToDebugLog = false; // don't want to write to debug.log file
-        SelectParams(CBaseChainParams::MAIN);
+        SelectParams(CBaseChainParams::UNITTEST);
         noui_connect();
 #ifdef ENABLE_WALLET
         bitdb.MakeMock();

{'commit': 'diff --git a/src/Makefile.test.include b/src/Makefile.test.include\nindex ab449f3e7..d37696199 100644\n--- a/src/Makefile.test.include\n+++ b/src/Makefile.test.include\n@@ -51,6 +51,7 @@ BITCOIN_TESTS =\\\n   test/key_tests.cpp \\\n   test/main_tests.cpp \\\n   test/miner_tests.cpp \\\n+  test/blockv2_tests.cpp \\\n   test/mruset_tests.cpp \\\n   test/multisig_tests.cpp \\\n   test/netbase_tests.cpp \\\ndiff --git a/src/chainparams.cpp b/src/chainparams.cpp\nindex 179db5a81..d924a6a2b 100644\n--- a/src/chainparams.cpp\n+++ b/src/chainparams.cpp\n@@ -214,8 +214,50 @@ public:\n };\n static CRegTestParams regTestParams;\n \n+//\n+// Regression test\n+//\n+class CUnitTestParams : public CMainParams, public CModifiableParams {\n+public:\n+    CUnitTestParams() {\n+        networkID = CBaseChainParams::UNITTEST;\n+        strNetworkID = "unittest";\n+        nDefaultPort = 18445;\n+        vFixedSeeds.clear();\n+        vSeeds.clear();  // Regtest mode doesn\'t have any DNS seeds.\n+\n+        fRequireRPCPassword = false;\n+        fMiningRequiresPeers = false;\n+        fDefaultCheckMemPool = true;\n+        fAllowMinDifficultyBlocks = false;\n+        fMineBlocksOnDemand = true;\n+        fSkipProofOfWorkCheck = false;\n+    }\n+    virtual bool SkipProofOfWorkCheck() const { return fSkipProofOfWorkCheck; }\n+protected:\n+    bool fSkipProofOfWorkCheck;\n+public:\n+    // Published setters to allow changing values in unit test cases\n+    virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval)  { nSubsidyHalvingInterval=anSubsidyHalvingInterval; }\n+    virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority)  { nEnforceBlockUpgradeMajority=anEnforceBlockUpgradeMajority; }\n+    virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority)  { nRejectBlockOutdatedMajority=anRejectBlockOutdatedMajority; }\n+    virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority)  { nToCheckBlockUpgradeMajority=anToCheckBlockUpgradeMajority; }\n+    virtual void setDefaultCheckMemPool(bool aDefaultCheckMemPool)  { fDefaultCheckMemPool=aDefaultCheckMemPool; }\n+    virtual void setAllowMinDifficultyBlocks(bool aAllowMinDifficultyBlocks) {  fAllowMinDifficultyBlocks=aAllowMinDifficultyBlocks; }\n+    virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck) { fSkipProofOfWorkCheck = aSkipProofOfWorkCheck; }\n+};\n+static CUnitTestParams unitTestParams;\n+\n+\n static CChainParams *pCurrentParams = 0;\n \n+CModifiableParams *ModifiableParams()\n+{\n+   assert(pCurrentParams);\n+   assert(pCurrentParams==&unitTestParams);\n+   return (CModifiableParams*)&unitTestParams;\n+}\n+\n const CChainParams &Params() {\n     assert(pCurrentParams);\n     return *pCurrentParams;\n@@ -229,6 +271,8 @@ CChainParams &Params(CBaseChainParams::Network network) {\n             return testNetParams;\n         case CBaseChainParams::REGTEST:\n             return regTestParams;\n+        case CBaseChainParams::UNITTEST:\n+            return unitTestParams;\n         default:\n             assert(false && "Unimplemented network");\n             return mainParams;\ndiff --git a/src/chainparams.h b/src/chainparams.h\nindex e5dfc87c6..171a590a5 100644\n--- a/src/chainparams.h\n+++ b/src/chainparams.h\n@@ -61,6 +61,8 @@ public:\n     bool DefaultCheckMemPool() const { return fDefaultCheckMemPool; }\n     /* Allow mining of a min-difficulty block */\n     bool AllowMinDifficultyBlocks() const { return fAllowMinDifficultyBlocks; }\n+    /* Skip proof-of-work check: allow mining of any difficulty block */\n+    virtual bool SkipProofOfWorkCheck() const { return false; }\n     /* Make standard checks */\n     bool RequireStandard() const { return fRequireStandard; }\n     int64_t TargetTimespan() const { return nTargetTimespan; }\n@@ -105,6 +107,24 @@ protected:\n     bool fMineBlocksOnDemand;\n };\n \n+/** Modifiable parameters interface is used by test cases to adapt the parameters in order\n+*** to test specific features more easily. Test cases should always restore the previous\n+*** values after finalization.\n+**/\n+\n+class CModifiableParams {\n+public:\n+    // Published setters to allow changing values in unit test cases\n+    virtual void setSubsidyHalvingInterval(int anSubsidyHalvingInterval) =0;\n+    virtual void setEnforceBlockUpgradeMajority(int anEnforceBlockUpgradeMajority)=0;\n+    virtual void setRejectBlockOutdatedMajority(int anRejectBlockOutdatedMajority)=0;\n+    virtual void setToCheckBlockUpgradeMajority(int anToCheckBlockUpgradeMajority)=0;\n+    virtual void setDefaultCheckMemPool(bool aDefaultCheckMemPool)=0;\n+    virtual void setAllowMinDifficultyBlocks(bool aAllowMinDifficultyBlocks)=0;\n+    virtual void setSkipProofOfWorkCheck(bool aSkipProofOfWorkCheck)=0;\n+};\n+\n+\n /**\n  * Return the currently selected parameters. This won\'t change after app startup\n  * outside of the unit tests.\n@@ -114,6 +134,9 @@ const CChainParams &Params();\n /** Return parameters for the given network. */\n CChainParams &Params(CBaseChainParams::Network network);\n \n+/** Get modifyable network parameters (UNITTEST only) */\n+CModifiableParams *ModifiableParams();\n+\n /** Sets the params returned by Params() to those for the given network. */\n void SelectParams(CBaseChainParams::Network network);\n \ndiff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp\nindex 98bb5b855..e9d63197b 100644\n--- a/src/chainparamsbase.cpp\n+++ b/src/chainparamsbase.cpp\n@@ -57,6 +57,20 @@ public:\n };\n static CBaseRegTestParams regTestParams;\n \n+//\n+// Unit test\n+//\n+class CBaseUnitTestParams : public CBaseMainParams\n+{\n+public:\n+    CBaseUnitTestParams()\n+    {\n+        networkID = CBaseChainParams::UNITTEST;\n+        strDataDir = "unittest";\n+    }\n+};\n+static CBaseUnitTestParams unitTestParams;\n+\n static CBaseChainParams* pCurrentBaseParams = 0;\n \n const CBaseChainParams& BaseParams()\n@@ -77,6 +91,9 @@ void SelectBaseParams(CBaseChainParams::Network network)\n     case CBaseChainParams::REGTEST:\n         pCurrentBaseParams = &regTestParams;\n         break;\n+    case CBaseChainParams::UNITTEST:\n+        pCurrentBaseParams = &unitTestParams;\n+        break;\n     default:\n         assert(false && "Unimplemented network");\n         return;\ndiff --git a/src/chainparamsbase.h b/src/chainparamsbase.h\nindex c054f03f1..cc154cf50 100644\n--- a/src/chainparamsbase.h\n+++ b/src/chainparamsbase.h\n@@ -19,6 +19,7 @@ public:\n         MAIN,\n         TESTNET,\n         REGTEST,\n+        UNITTEST,\n \n         MAX_NETWORK_TYPES\n     };\ndiff --git a/src/checkpoints.cpp b/src/checkpoints.cpp\nindex c41deea7c..9a6bc05e6 100644\n--- a/src/checkpoints.cpp\n+++ b/src/checkpoints.cpp\n@@ -88,6 +88,8 @@ namespace Checkpoints {\n             return dataTestnet;\n         else if (Params().NetworkID() == CBaseChainParams::MAIN)\n             return data;\n+        else if (Params().NetworkID() == CBaseChainParams::UNITTEST) // UnitTest share the same checkpoints as MAIN\n+            return data;\n         else\n             return dataRegtest;\n     }\ndiff --git a/src/main.cpp b/src/main.cpp\nindex 9a4271eda..4bd8fd6e3 100644\n--- a/src/main.cpp\n+++ b/src/main.cpp\n@@ -2304,6 +2304,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex\n         nHeight = pindexPrev->nHeight+1;\n \n         // Check proof of work\n+        if (!Params().SkipProofOfWorkCheck())\n         if (block.nBits != GetNextWorkRequired(pindexPrev, &block))\n             return state.DoS(100, error("AcceptBlock() : incorrect proof of work"),\n                              REJECT_INVALID, "bad-diffbits");\ndiff --git a/src/pow.cpp b/src/pow.cpp\nindex 893f6c18b..d50222849 100644\n--- a/src/pow.cpp\n+++ b/src/pow.cpp\n@@ -81,6 +81,10 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)\n     bool fNegative;\n     bool fOverflow;\n     uint256 bnTarget;\n+\n+    if (Params().SkipProofOfWorkCheck())\n+       return true;\n+\n     bnTarget.SetCompact(nBits, &fNegative, &fOverflow);\n \n     // Check range\ndiff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp\nindex 58fffb6df..c298c805d 100644\n--- a/src/test/base58_tests.cpp\n+++ b/src/test/base58_tests.cpp\n@@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)\n             BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest);\n         }\n     }\n-    SelectParams(CBaseChainParams::MAIN);\n+    SelectParams(CBaseChainParams::UNITTEST);\n }\n \n // Goal: check that generated keys match test vectors\n@@ -243,7 +243,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)\n     CTxDestination nodest = CNoDestination();\n     BOOST_CHECK(!dummyAddr.Set(nodest));\n \n-    SelectParams(CBaseChainParams::MAIN);\n+    SelectParams(CBaseChainParams::UNITTEST);\n }\n \n // Goal: check that base58 parsing code is robust against a variety of corrupted data\ndiff --git a/src/test/blockv2_tests.cpp b/src/test/blockv2_tests.cpp\nnew file mode 100644\nindex 000000000..0d59c8761\n--- /dev/null\n+++ b/src/test/blockv2_tests.cpp\n@@ -0,0 +1,232 @@\n+// Copyright (c) 2011-2014 The Bitcoin Core developers\n+// Distributed under the MIT/X11 software license, see the accompanying\n+// file COPYING or http://www.opensource.org/licenses/mit-license.php.\n+\n+#include "main.h"\n+#include "miner.h"\n+#include "uint256.h"\n+#include "util.h"\n+\n+#include <boost/test/unit_test.hpp>\n+\n+// Tests the majority rule which states that after 1000 v2 blocks no v1 block can go\n+BOOST_AUTO_TEST_SUITE(blockv2_tests)\n+\n+static CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;\n+\n+static void SetEmptyBlock(CBlock * pblock)\n+{\n+        pblock->nVersion = 2;\n+        pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;\n+        pblock->nNonce = 0;\n+}\n+\n+static void SetBlockDefaultAttributesAndHeight(CBlock * pblock,bool addHeight,int difValue)\n+{\n+        SetEmptyBlock(pblock);\n+\n+        // Add the coinbase\n+        CMutableTransaction txCoinbase(pblock->vtx[0]);\n+\n+        if (addHeight)\n+            txCoinbase.vin[0].scriptSig = (CScript() << (chainActive.Height()+1+difValue) << 0);\n+            else\n+            txCoinbase.vin[0].scriptSig = (CScript() << difValue << 0); // At least size 2, this is a protocol spec\n+\n+        txCoinbase.vout[0].scriptPubKey = CScript();\n+        pblock->vtx[0] = CTransaction(txCoinbase);\n+        pblock->hashMerkleRoot = pblock->BuildMerkleTree();\n+}\n+\n+void CheckSubsidyHalving(CBlockTemplate * &pblocktemplate, CBlock * &pblock)\n+{\n+    if ((chainActive.Height()+1) % Params().SubsidyHalvingInterval() == 0)\n+        {\n+            // The RegTest network has a low subsidy halving interval (150) so\n+            // we must recompute the coinbase subsidy if we reach the boundary.\n+\n+            // preserve parent hash\n+            uint256 prevParent = pblock->hashPrevBlock;\n+            delete pblocktemplate;\n+            pblocktemplate = CreateNewBlock(scriptPubKey);\n+            pblock = &pblocktemplate->block; // pointer for convenience\n+            pblock->hashPrevBlock = prevParent;\n+        }\n+}\n+\n+void Blockv2test()\n+{\n+    assert(Params().NetworkID() == CBaseChainParams::UNITTEST);\n+    ModifiableParams()->setSkipProofOfWorkCheck(true);\n+\n+    // We don\'t know the state of the block-chain here: it depends on which other tests are run before this test.\n+    // See https://github.com/bitcoin/bitcoin/pull/4688 for a patch that allows the re-creation of the block-chain\n+    // for each testcase that requires it.\n+\n+    // If miner_tests.cpp is run before, the chain will be 100 blocks long, and all of them will be v1\n+\n+\n+    LogPrintf("Blockv2test testcase starts\\n");\n+\n+    CBlockTemplate *pblocktemplate;\n+    CScript script;\n+    uint256 hash;\n+    int PreviousHeight;\n+\n+\n+    LOCK(cs_main);\n+\n+\n+    // Simple block creation, nothing special yet.\n+    pblocktemplate = CreateNewBlock(scriptPubKey);\n+    CBlock *pblock = &pblocktemplate->block; // pointer for convenience\n+\n+    LogPrintf("Blockv2test block v1 add begin\\n");\n+    // First create a block v1, check that it is accepted. The block has an invalid height\n+    SetBlockDefaultAttributesAndHeight(pblock,false,5000);\n+    pblock->nVersion = 1;\n+    CValidationState state1;\n+    PreviousHeight = chainActive.Height();\n+    BOOST_CHECK(ProcessBlock(state1, NULL, pblock));\n+    BOOST_CHECK(state1.IsValid());\n+    BOOST_CHECK((PreviousHeight+1) == chainActive.Height()); // to differentiate from orphan blocks, which also get accepted in ProcessBlock()\n+    pblock->hashPrevBlock = pblock->GetHash(); // update parent\n+\n+\n+    // Now create exactly 1000 blocks v2\n+\n+    // First check that the supermajority threshold is exactly 1000 blocks\n+    BOOST_CHECK(Params().ToCheckBlockUpgradeMajority()==1000);  //\n+    BOOST_CHECK(Params().EnforceBlockUpgradeMajority()==750);\n+    BOOST_CHECK(Params().RejectBlockOutdatedMajority()==950);\n+\n+    // Over the last 1000 blocks, 750 blocks must be v2 to switch to v2-only mode.\n+    // Here we\'re testing only the last 750, not any subset.\n+\n+    LogPrintf("Blockv2test BIP30 repetition begin\\n");\n+\n+    // First, if we try to add a block v2 with the same coinbase tx, we should get\n+    // "bad-txns-BIP30" because the coinbase tx has the same hash as the previous.\n+    // Unluckily, even if ConnectBlock returns a "bad-txns-BIP30", ActivateBestChainStep clears\n+    // the state, so we get true here and the "bad-txns-BIP30" reason is lost.\n+    // We verify instead that the chain height has not been incremented.\n+\n+    CValidationState state7;\n+    PreviousHeight = chainActive.Height();\n+    CheckSubsidyHalving(pblocktemplate,pblock);\n+    SetBlockDefaultAttributesAndHeight(pblock,false,5000); //\n+    pblock->nVersion = 2;\n+    BOOST_CHECK(ProcessBlock(state7, NULL, pblock)); // should we care about the return value?\n+    BOOST_CHECK(state7.IsValid());\n+    BOOST_CHECK(PreviousHeight == chainActive.Height()); // we check the block has not been added.\n+\n+    LogPrintf("Blockv2test 750 v2 blocks  begin\\n");\n+    for (int i=0;i<750;i++)\n+    {\n+\n+        LogPrintf("Blockv2test block %d begin\\n",i);\n+\n+        CheckSubsidyHalving(pblocktemplate,pblock);\n+\n+        // We add a value to the height to make is NOT equal to the actual height.\n+        SetBlockDefaultAttributesAndHeight(pblock,true,1000); // blocks version 2 without height are allowed! for only 750 blocks\n+        pblock->nVersion = 2;\n+        CValidationState state;\n+\n+        PreviousHeight = chainActive.Height();\n+        BOOST_CHECK(ProcessBlock(state, NULL, pblock));\n+        BOOST_CHECK(state.IsValid());\n+        BOOST_CHECK((PreviousHeight+1) == chainActive.Height()); // to differentiate from orphan blocks, which also get accepted in ProcessBlock()\n+        pblock->hashPrevBlock = pblock->GetHash(); // update parent\n+    }\n+\n+    LogPrintf("Blockv2test v2 without height rejected begin\\n");\n+\n+    // Now we try to add a block v2, with an invalid height and it should be rejected. We use 2000 because is not in the range [1000..1750].\n+    CheckSubsidyHalving(pblocktemplate,pblock);\n+    SetBlockDefaultAttributesAndHeight(pblock,true,2000); //\n+    pblock->nVersion = 2;\n+    CValidationState state0;\n+    BOOST_CHECK(ProcessBlock(state0, NULL, pblock)==false);\n+    BOOST_CHECK(!state0.IsValid());\n+    BOOST_CHECK(state0.GetRejectReason()=="bad-cb-height");\n+    // Do not update parent since block has failed\n+\n+    LogPrintf("Blockv2test v2 with height accepted begin\\n");\n+\n+\n+    // Now we add a block with height, must be ok.\n+    for (int i=0;i<200;i++)\n+    {\n+\n+        LogPrintf("Blockv2test v2block %d begin\\n",i);\n+        CheckSubsidyHalving(pblocktemplate,pblock);\n+        SetBlockDefaultAttributesAndHeight(pblock,true,0);\n+        pblock->nVersion = 2;\n+        CValidationState state;\n+        PreviousHeight = chainActive.Height();\n+        BOOST_CHECK(ProcessBlock(state, NULL, pblock));\n+        BOOST_CHECK(state.IsValid());\n+        BOOST_CHECK((PreviousHeight+1) == chainActive.Height()); // to differentiate from orphan blocks, which also get accepted in ProcessBlock()\n+\n+        pblock->hashPrevBlock = pblock->GetHash(); // update parent\n+    }\n+\n+\n+    LogPrintf("Blockv2test block v1 rejected\\n");\n+    // Now we add 200 additional blocks, until we get 950 (the threshold were v1 blocks are not accepted anymore)\n+    // Now we try to add a block v1, it should be rejected, even if it hash the height field\n+    CheckSubsidyHalving(pblocktemplate,pblock);\n+    SetBlockDefaultAttributesAndHeight(pblock,true,0);\n+    pblock->nVersion = 1;\n+    CValidationState state2;\n+    BOOST_CHECK(ProcessBlock(state2, NULL, pblock)==false);\n+    BOOST_CHECK(!state2.IsValid());\n+    BOOST_CHECK(state2.GetRejectReason()=="bad-version");\n+    // Do not update parent since block has failed\n+\n+\n+\n+    // Some other missing tests, added here as bonus...\n+\n+    // Block time too old check\n+    CheckSubsidyHalving(pblocktemplate,pblock);\n+    SetBlockDefaultAttributesAndHeight(pblock,true,0);\n+    pblock->nVersion = 2;\n+    pblock->nTime = chainActive.Tip()->GetMedianTimePast()-1;\n+    CValidationState state4;\n+    BOOST_CHECK(ProcessBlock(state4, NULL, pblock)==false);\n+    BOOST_CHECK(!state4.IsValid());\n+    BOOST_CHECK(state4.GetRejectReason()=="time-too-old");\n+    // Do not update parent since block has failed\n+\n+    // Adding a non-final coinbase, must modify coinbase\n+    CheckSubsidyHalving(pblocktemplate,pblock);\n+    SetEmptyBlock(pblock);\n+    // Use a mutable coinbase to change nLockTime and  nSequence\n+    CMutableTransaction txCoinbase(pblock->vtx[0]);\n+    txCoinbase.vin[0].scriptSig = (CScript() << chainActive.Height() << 0);\n+    txCoinbase.nLockTime = LOCKTIME_THRESHOLD-1; // refers to height\n+    txCoinbase.vin[0].nSequence = 1; // non-zero sequence\n+    pblock->vtx[0] = CTransaction(txCoinbase);\n+    pblock->nVersion = 2;\n+    pblock->hashMerkleRoot = pblock->BuildMerkleTree();\n+    CValidationState state5;\n+    BOOST_CHECK(ProcessBlock(state5, NULL, pblock)==false);\n+    BOOST_CHECK(!state5.IsValid());\n+    BOOST_CHECK(state5.GetRejectReason()=="bad-txns-nonfinal");\n+    // Do not update parent since block has failed\n+\n+\n+    delete pblocktemplate;\n+\n+    ModifiableParams()->setSkipProofOfWorkCheck(false);\n+    LogPrintf("Blockv2test testcase ends\\n");\n+}\n+\n+BOOST_AUTO_TEST_CASE(Blockv2testcase)\n+{\n+    Blockv2test();\n+}\n+\n+BOOST_AUTO_TEST_SUITE_END()\ndiff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp\nindex 9e4669eba..bad5c13ac 100644\n--- a/src/test/miner_tests.cpp\n+++ b/src/test/miner_tests.cpp\n@@ -253,6 +253,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)\n \n     chainActive.Tip()->nHeight--;\n     SetMockTime(0);\n+    mempool.clear();\n \n     BOOST_FOREACH(CTransaction *tx, txFirst)\n         delete tx;\ndiff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp\nindex 68fad8d03..6e5f0e3fa 100644\n--- a/src/test/test_bitcoin.cpp\n+++ b/src/test/test_bitcoin.cpp\n@@ -31,7 +31,7 @@ struct TestingSetup {\n \n     TestingSetup() {\n         fPrintToDebugLog = false; // don\'t want to write to debug.log file\n-        SelectParams(CBaseChainParams::MAIN);\n+        SelectParams(CBaseChainParams::UNITTEST);\n         noui_connect();\n #ifdef ENABLE_WALLET\n         bitdb.MakeMock();\n', 'commit_subject': 'Switch testing framework from MAIN to new UNITTEST network', 'repo_name': 'zcoinofficial/zcoin', 'committer': {'name': 'Wladimir J. van der Laan', 'email': 'bbc07dc96bb50bf6868a2ddfc4dae14fbed703d9@gmail.com', 'time_sec': '1411988602', 'tz_offset': '120', 'date': {'seconds': '1411988602'}}, 'commit_tree': '331eae7469995c3a8318df70f1654c7116fd1bd4', 'commit_message': 'Switch testing framework from MAIN to new UNITTEST network\n\nUNITTEST inherites from MAIN but allows synamically changing its parameters using the ModifiableParams() interface\n', 'language_name': 'Java', 'license': 'mit', 'hunks': "@@ -31,7 +31,7 @@ struct TestingSetup {\n \n     TestingSetup() {\n         fPrintToDebugLog = false; // don't want to write to debug.log file\n-        SelectParams(CBaseChainParams::MAIN);\n+        SelectParams(CBaseChainParams::UNITTEST);\n         noui_connect();\n #ifdef ENABLE_WALLET\n         bitdb.MakeMock();\n", 'addition_count': 1, 'deletion_count': 1, 'src_file': 'a/src/test/test_bitcoin.cpp', 'tgt_file': 'b/src/test/test_bitcoin.cpp', 'file_extension': '.cpp', 'before_file': '// Copyright (c) 2011-2016 The Bitcoin Core developers\n// Distributed under the MIT software license, see the accompanying\n// file COPYING or http://www.opensource.org/licenses/mit-license.php.\n\n#define BOOST_TEST_MODULE Firo Test Suite\n\n#if defined(HAVE_CONFIG_H)\n#include "../config/bitcoin-config.h"\n#endif\n\n#include "test_bitcoin.h"\n\n#include "util.h"\n#include "chainparams.h"\n#include "consensus/consensus.h"\n#include "consensus/validation.h"\n#include "key.h"\n#include "validation.h"\n#include "miner.h"\n#include "net_processing.h"\n#include "pubkey.h"\n#include "random.h"\n#include "txdb.h"\n#include "txmempool.h"\n#include "ui_interface.h"\n#include "rpc/server.h"\n#include "rpc/register.h"\n#include "script/sigcache.h"\n#include "stacktraces.h"\n\n\n    TestingSetup() {\n        fPrintToDebugLog = false; // don\'t want to write to debug.log file\n        SelectParams(CBaseChainParams::MAIN);\n        noui_connect();\n#ifdef ENABLE_WALLET\n        bitdb.MakeMock();\n#include "../elysium/elysium.h"\n#endif\n\n#include <boost/filesystem.hpp>\n#include <boost/test/unit_test.hpp>\n#include <boost/test/unit_test_monitor.hpp>\n#include <boost/thread.hpp>\n#include "sigma.h"\n#include "evo/evodb.h"\n#include "evo/cbtx.h"\n#include "evo/specialtx.h"\n#include "llmq/quorums_init.h"\n\nextern std::unique_ptr<CConnman> g_connman;\nuint256 insecure_rand_seed = GetRandHash();\nFastRandomContext insecure_rand_ctx(insecure_rand_seed);\n\nextern bool fPrintToConsole;\nextern void noui_connect();\nextern CEvoDB* evoDb;\n\nBasicTestingSetup::BasicTestingSetup(const std::string& chainName)\n{\n    ECC_Start();\n    SetupEnvironment();\n    SetupNetworking();\n    InitSignatureCache();\n    fPrintToDebugLog = false; // don\'t want to write to debug.log file\n    fCheckBlockIndex = true;\n    SelectParams(chainName);\n    SoftSetBoolArg("-dandelion", false);\n    evoDb = new CEvoDB(1 << 20, true, true);\n    deterministicMNManager = new CDeterministicMNManager(*evoDb);\n    noui_connect();\n}\n\nBasicTestingSetup::~BasicTestingSetup()\n{\n        delete deterministicMNManager;\n        delete evoDb;\n\n        ECC_Stop();\n        g_connman.reset();\n}\n\nTestingSetup::TestingSetup(const std::string& chainName, std::string suf) : BasicTestingSetup(chainName)\n{\n    const CChainParams& chainparams = Params();\n        // Ideally we\'d move all the RPC tests to the functional testing framework\n        // instead of unit tests, but for now we need these here.\n        RegisterAllCoreRPCCommands(tableRPC);\n        ClearDatadirCache();\n        pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));\n        boost::filesystem::create_directories(pathTemp);\n        ForceSetArg("-datadir", pathTemp.string());\n        mempool.setSanityCheck(1.0);\n        pblocktree = new CBlockTreeDB(1 << 20, true);\n        pcoinsdbview = new CCoinsViewDB(1 << 23, true);\n        llmq::InitLLMQSystem(*evoDb, nullptr, true);\n        pcoinsTip = new CCoinsViewCache(pcoinsdbview);\n        pwalletMain = new CWallet(std::string("wallet_test.dat"));\n        static bool fFirstRun = true;\n        pwalletMain->LoadWallet(fFirstRun);\n\n        InitBlockIndex(chainparams);\n        {\n            CValidationState state;\n            bool ok = ActivateBestChain(state, chainparams);\n            BOOST_CHECK(ok);\n        }\n        nScriptCheckThreads = 3;\n        for (int i=0; i < nScriptCheckThreads-1; i++)\n            threadGroup.create_thread(&ThreadScriptCheck);\n        g_connman = std::unique_ptr<CConnman>(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests.\n        connman = g_connman.get();\n        RegisterNodeSignals(GetNodeSignals());\n\n        // Init HD mint\n\n        // Create new keyUser and set as default key\n        // generate a new master key\n        CPubKey masterPubKey = pwalletMain->GenerateNewHDMasterKey();\n        pwalletMain->SetHDMasterKey(masterPubKey);\n        CPubKey newDefaultKey;\n        if (pwalletMain->GetKeyFromPool(newDefaultKey)) {\n            pwalletMain->SetDefaultKey(newDefaultKey);\n            pwalletMain->SetAddressBook(pwalletMain->vchDefaultKey.GetID(), "", "receive");\n        }\n\n        pwalletMain->SetBestChain(chainActive.GetLocator());\n\n        pwalletMain->zwallet = std::make_unique<CHDMintWallet>(pwalletMain->strWalletFile);\n        pwalletMain->zwallet->GetTracker().Init();\n        pwalletMain->zwallet->LoadMintPoolFromDB();\n        pwalletMain->zwallet->SyncWithChain();\n}\n\nTestingSetup::~TestingSetup()\n{\n    UnregisterNodeSignals(GetNodeSignals());\n    llmq::InterruptLLMQSystem();\n    llmq::DestroyLLMQSystem();\n#ifdef ENABLE_ELYSIUM\n    elysium_shutdown();\n#endif\n    threadGroup.interrupt_all();\n    threadGroup.join_all();\n    UnloadBlockIndex();\n    delete pwalletMain;\n    pwalletMain = NULL;\n    delete pcoinsTip;\n    delete pcoinsdbview;\n    delete pblocktree;\n\ttry {\n\t\tboost::filesystem::remove_all(pathTemp);\n\t}\n\tcatch(...) {\n\t\ttry {\n\t\t\tMilliSleep(100);\n\t\t\tboost::filesystem::remove_all(std::wstring(L"\\\\\\\\?\\\\") + pathTemp.wstring());\n\t\t}\n\t\tcatch(...) {\n\n\t\t}\n\t}\n    bitdb.RemoveDb("wallet_test.dat");\n    bitdb.Reset();\n}\n\nTestChain100Setup::TestChain100Setup(int nBlocks) : TestingSetup(CBaseChainParams::REGTEST)\n{\n    // Generate a 100-block chain:\n    coinbaseKey.MakeNewKey(true);\n    CScript scriptPubKey = CScript() <<  ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;\n    for (int i = 0; i < nBlocks; i++)\n    {\n        std::vector<CMutableTransaction> noTxns;\n        CBlock b = CreateAndProcessBlock(noTxns, scriptPubKey);\n        coinbaseTxns.push_back(*b.vtx[0]);\n    }\n}\n\nCBlock TestChain100Setup::CreateBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey)\n{\n    const CChainParams& chainparams = Params();\n    std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);\n    CBlock& block = pblocktemplate->block;\n\n    std::vector<CTransactionRef> llmqCommitments;\n    for (const auto& tx : block.vtx) {\n        if (tx->nVersion == 3 && tx->nType == TRANSACTION_QUORUM_COMMITMENT) {\n            llmqCommitments.emplace_back(tx);\n        }\n    }\n\n    // Replace mempool-selected txns with just coinbase plus passed-in txns:\n    if (!fAllowMempoolTxsInCreateBlock)\n        block.vtx.resize(1);\n    // Re-add quorum commitments\n    block.vtx.insert(block.vtx.end(), llmqCommitments.begin(), llmqCommitments.end());\n    BOOST_FOREACH(const CMutableTransaction& tx, txns)\n        block.vtx.push_back(MakeTransactionRef(tx));\n\n    // Manually update CbTx as we modified the block here\n    if (block.vtx[0]->nType == TRANSACTION_COINBASE) {\n        LOCK(cs_main);\n        CCbTx cbTx;\n        if (!GetTxPayload(*block.vtx[0], cbTx)) {\n            BOOST_ASSERT(false);\n        }\n        CValidationState state;\n        if (!CalcCbTxMerkleRootMNList(block, chainActive.Tip(), cbTx.merkleRootMNList, state)) {\n            BOOST_ASSERT(false);\n        }\n        if (!CalcCbTxMerkleRootQuorums(block, chainActive.Tip(), cbTx.merkleRootQuorums, state)) {\n            BOOST_ASSERT(false);\n        }\n        CMutableTransaction tmpTx = *block.vtx[0];\n        SetTxPayload(tmpTx, cbTx);\n        block.vtx[0] = MakeTransactionRef(tmpTx);\n    }\n\n    // IncrementExtraNonce creates a valid coinbase and merkleRoot\n    unsigned int extraNonce = 0;\n    IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);\n\n    if (block.IsProgPow()) {\n        while (!CheckProofOfWork(progpow_hash_full(block.GetProgPowHeader(), block.mix_hash), block.nBits, chainparams.GetConsensus()))\n            ++block.nNonce64;\n    }\n    else {\n        while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;\n    }\n\n    CBlock result = block;\n    return result;\n}\n\nCBlock TestChain100Setup::CreateBlock(const std::vector<CMutableTransaction>& txns, const CKey& scriptKey)\n{\n    CScript scriptPubKey = CScript() <<  ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;\n    return CreateBlock(txns, scriptPubKey);\n}\n\n//\n// Create a new block with just given transactions, coinbase paying to\n// scriptPubKey, and try to add it to the current chain.\n//\nCBlock\nTestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey, bool * processBlockResult)\n{\n    const CChainParams& chainparams = Params();\n    auto block = CreateBlock(txns, scriptPubKey);\n\n    std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);\n    bool pbr = ProcessNewBlock(chainparams, shared_pblock, true, NULL);\n    if(processBlockResult)\n        *processBlockResult = pbr;\n\n    CBlock result = block;\n    return result;\n}\n\nCBlock TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CKey& scriptKey, bool * processBlockResult)\n{\n    CScript scriptPubKey = CScript() <<  ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;\n    return CreateAndProcessBlock(txns, scriptPubKey, processBlockResult);\n}\n\nTestChain100Setup::~TestChain100Setup()\n{\n}\n\n\nCTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction &tx, CTxMemPool *pool) {\n    CTransaction txn(tx);\n    return FromTx(txn, pool);\n}\n\nCTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn, CTxMemPool *pool) {\n    // Hack to assume either it\'s completely dependent on other mempool txs or not at all\n    CAmount inChainValue = pool && pool->HasNoInputsOf(txn) ? txn.GetValueOut() : 0;\n\n    return CTxMemPoolEntry(MakeTransactionRef(txn), nFee, nTime, nHeight,\n                           inChainValue, spendsCoinbase, sigOpCost, lp);\n}\n\nsize_t FindZnodeOutput(CTransaction const & tx) {\n    static std::vector<CScript> const founders {\n        GetScriptForDestination(CBitcoinAddress("TDk19wPKYq91i18qmY6U9FeTdTxwPeSveo").Get()),\n        GetScriptForDestination(CBitcoinAddress("TWZZcDGkNixTAMtRBqzZkkMHbq1G6vUTk5").Get()),\n        GetScriptForDestination(CBitcoinAddress("TRZTFdNCKCKbLMQV8cZDkQN9Vwuuq4gDzT").Get()),\n        GetScriptForDestination(CBitcoinAddress("TG2ruj59E5b1u9G3F7HQVs6pCcVDBxrQve").Get()),\n        GetScriptForDestination(CBitcoinAddress("TCsTzQZKVn4fao8jDmB9zQBk9YQNEZ3XfS").Get()),\n    };\n\n    BOOST_CHECK(tx.IsCoinBase());\n    for(size_t i = 0; i < tx.vout.size(); ++i) {\n        CTxOut const & out = tx.vout[i];\n         if(std::find(founders.begin(), founders.end(), out.scriptPubKey) == founders.end()) {\n            if(out.nValue == GetZnodePayment(Params().GetConsensus(), false))\n                return i;\n        }\n    }\n    throw std::runtime_error("Cannot find the Znode output");\n}\n\n/*\nvoid Shutdown(void* parg)\n{\n  exit(EXIT_SUCCESS);\n}\n\nvoid StartShutdown()\n{\n  exit(EXIT_SUCCESS);\n}\n\nbool ShutdownRequested()\n{\n  return false;\n}\n*/\n\n#ifdef ENABLE_CRASH_HOOKS\ntemplate<typename T>\nvoid translate_exception(const T &e)\n{\n    std::cerr << GetPrettyExceptionStr(std::current_exception()) << std::endl;\n    throw;\n}\n\ntemplate<typename T>\nvoid register_exception_translator()\n{\n    boost::unit_test::unit_test_monitor.register_exception_translator<T>(&translate_exception<T>);\n}\n\nstruct ExceptionInitializer {\n    ExceptionInitializer()\n    {\n        RegisterPrettyTerminateHander();\n        RegisterPrettySignalHandlers();\n\n        register_exception_translator<std::exception>();\n        register_exception_translator<std::string>();\n        register_exception_translator<const char*>();\n    }\n    ~ExceptionInitializer()\n    {\n    }\n};\n\nBOOST_GLOBAL_FIXTURE( ExceptionInitializer );\n#endif\n', 'message': 'Switch testing framework from MAIN to new UNITTEST network\n\nUNITTEST inherites from MAIN but allows synamically changing its parameters using the ModifiableParams() interface\n', 'author_name': 'Wladimir J. van der Laan', 'lang': 'cpp'}