From 26843c9c0307abb74b3605d51a40605bd3b7a6a5 Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 7 Jun 2021 10:33:08 -0500 Subject: [PATCH 01/47] wrap test chain funcs into class --- src/test-komodo/testutils.cpp | 218 ++++++++++++++++++++++++++++++++-- src/test-komodo/testutils.h | 118 +++++++++++++++++- 2 files changed, 320 insertions(+), 16 deletions(-) diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index c17de8bb14b..4a6f7c89026 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -65,40 +65,55 @@ void setupChain() InitBlockIndex(); } - +/*** + * Generate a block + * @param block a place to store the block (nullptr skips the disk read) + */ void generateBlock(CBlock *block) { + SetMockTime(nMockTime+=100); // CreateNewBlock can fail if not enough time passes + UniValue params; params.setArray(); params.push_back(1); - uint256 blockId; - - SetMockTime(nMockTime+=100); // CreateNewBlock can fail if not enough time passes try { UniValue out = generate(params, false, CPubKey()); + uint256 blockId; blockId.SetHex(out[0].getValStr()); - if (block) ASSERT_TRUE(ReadBlockFromDisk(*block, mapBlockIndex[blockId], false)); + if (block) + ASSERT_TRUE(ReadBlockFromDisk(*block, mapBlockIndex[blockId], false)); } catch (const UniValue& e) { FAIL() << "failed to create block: " << e.write().data(); } } - +/*** + * Accept a transaction, failing the gtest if the tx is not accepted + * @param tx the transaction to be accepted + */ void acceptTxFail(const CTransaction tx) { CValidationState state; - if (!acceptTx(tx, state)) FAIL() << state.GetRejectReason(); + if (!acceptTx(tx, state)) + FAIL() << state.GetRejectReason(); } bool acceptTx(const CTransaction tx, CValidationState &state) { LOCK(cs_main); - return AcceptToMemoryPool(mempool, state, tx, false, NULL); + bool missingInputs = false; + bool accepted = AcceptToMemoryPool(mempool, state, tx, false, &missingInputs, false, -1); + return accepted && !missingInputs; } - +/*** + * Create a transaction based on input + * @param txIn the vin data (which becomes prevout) + * @param nOut the index of txIn to use as prevout + * @returns the transaction + */ CMutableTransaction spendTx(const CTransaction &txIn, int nOut) { CMutableTransaction mtx; @@ -125,7 +140,7 @@ std::vector getSig(const CMutableTransaction mtx, CScript inputPubKey, * In order to do tests there needs to be inputs to spend. * This method creates a block and returns a transaction that spends the coinbase. */ -void getInputTx(CScript scriptPubKey, CTransaction &txIn) +CTransaction getInputTx(CScript scriptPubKey) { // Get coinbase CBlock block; @@ -143,5 +158,186 @@ void getInputTx(CScript scriptPubKey, CTransaction &txIn) // Accept acceptTxFail(mtx); - txIn = CTransaction(mtx); + return CTransaction(mtx); +} + +/**** + * A class to provide a simple chain for tests + */ + +TestChain::TestChain() +{ + setupChain(); + CBitcoinSecret vchSecret; + vchSecret.SetString(notarySecret); // this returns false due to network prefix mismatch but works anyway + notaryKey = vchSecret.GetKey(); +} + +CBlock TestChain::generateBlock() +{ + CBlock block; + ::generateBlock(&block); + for(auto wallet : toBeNotified) + { + wallet->BlockNotification(block); + } + return block; +} + +CKey TestChain::getNotaryKey() { return notaryKey; } + +CValidationState TestChain::acceptTx(const CTransaction& tx) +{ + CValidationState retVal; + bool accepted = ::acceptTx(tx, retVal); + if (!accepted && retVal.IsValid()) + retVal.DoS(100, false, 0U, "acceptTx returned false"); + return retVal; +} + +std::shared_ptr TestChain::AddWallet(const CKey& in) +{ + std::shared_ptr retVal = std::make_shared(this, in); + toBeNotified.push_back(retVal); + return retVal; +} + +std::shared_ptr TestChain::AddWallet() +{ + std::shared_ptr retVal = std::make_shared(this); + toBeNotified.push_back(retVal); + return retVal; +} + + +/*** + * A simplistic (dumb) wallet for helping with testing + * - It does not keep track of spent transactions + * - Blocks containing vOuts that apply are added to the front of a vector + */ + +TestWallet::TestWallet(TestChain* chain) : chain(chain) +{ + key.MakeNewKey(true); + destScript = GetScriptForDestination(key.GetPubKey()); +} + +TestWallet::TestWallet(TestChain* chain, const CKey& in) : chain(chain), key(in) +{ + destScript = GetScriptForDestination(key.GetPubKey()); +} + +/*** + * @returns the public key + */ +CPubKey TestWallet::GetPubKey() const { return key.GetPubKey(); } + +/*** + * @returns the private key + */ +CKey TestWallet::GetPrivKey() const { return key; } + +/*** + * Sign a typical transaction + * @param hash the hash to sign + * @param hashType SIGHASH_ALL or something similar + * @returns the bytes to add to ScriptSig + */ +std::vector TestWallet::Sign(uint256 hash, unsigned char hashType) +{ + std::vector retVal; + key.Sign(hash, retVal); + retVal.push_back(hashType); + return retVal; +} + +/*** + * Sign a cryptocondition + * @param cc the cryptocondition + * @param hash the hash to sign + * @returns the bytes to add to ScriptSig + */ +std::vector TestWallet::Sign(CC* cc, uint256 hash) +{ + int out = cc_signTreeSecp256k1Msg32(cc, key.begin(), hash.begin()); + return CCSigVec(cc); +} + +/*** + * Notifies this wallet of a new block + */ +void TestWallet::BlockNotification(const CBlock& block) +{ + // TODO: remove spent txs from availableTransactions + // see if this block has any outs for me + for( auto tx : block.vtx ) + { + for(uint32_t i = 0; i < tx.vout.size(); ++i) + { + if (tx.vout[i].scriptPubKey == destScript) + { + availableTransactions.insert(availableTransactions.begin(), std::pair(tx, i)); + break; // skip to next tx + } + } + } +} + +/*** + * Get a transaction that has funds + * NOTE: If no single transaction matches, throws + * @param needed how much is needed + * @returns a pair of CTransaction and the n value of the vout + */ +std::pair TestWallet::GetAvailable(CAmount needed) +{ + for(auto txp : availableTransactions) + { + CTransaction tx = txp.first; + uint32_t n = txp.second; + if (tx.vout[n].nValue >= needed) + return txp; + } + throw std::logic_error("No Funds"); +} + +/*** + * Add a transaction to the list of available vouts + * @param tx the transaction + * @param n the n value of the vout + */ +void TestWallet::AddOut(CTransaction tx, uint32_t n) +{ + availableTransactions.insert(availableTransactions.begin(), std::pair(tx, n)); +} + +/*** + * Transfer to another user + * @param to who to transfer to + * @param amount the amount + * @returns the results + */ +CValidationState TestWallet::Transfer(std::shared_ptr to, CAmount amount, CAmount fee) +{ + std::pair available = GetAvailable(amount + fee); + CMutableTransaction tx; + CTxIn incoming; + incoming.prevout.hash = available.first.GetHash(); + incoming.prevout.n = available.second; + tx.vin.push_back(incoming); + CTxOut out1; + out1.scriptPubKey = GetScriptForDestination(to->GetPubKey()); + out1.nValue = amount; + tx.vout.push_back(out1); + // give the rest back to the notary + CTxOut out2; + out2.scriptPubKey = GetScriptForDestination(key.GetPubKey()); + out2.nValue = available.first.vout[available.second].nValue - amount - fee; + tx.vout.push_back(out2); + + uint256 hash = SignatureHash(available.first.vout[available.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); + tx.vin[0].scriptSig << Sign(hash, SIGHASH_ALL); + + CTransaction fundTo(tx); + return chain->acceptTx(fundTo); } diff --git a/src/test-komodo/testutils.h b/src/test-komodo/testutils.h index bbf702f263d..2f624fd78d9 100644 --- a/src/test-komodo/testutils.h +++ b/src/test-komodo/testutils.h @@ -1,9 +1,7 @@ -#ifndef TESTUTILS_H -#define TESTUTILS_H +#pragma once #include "main.h" - #define VCH(a,b) std::vector(a, a + b) static char ccjsonerr[1000] = "\0"; @@ -18,12 +16,122 @@ extern CKey notaryKey; void setupChain(); +/*** + * Generate a block + * @param block a place to store the block (read from disk) + */ void generateBlock(CBlock *block=NULL); bool acceptTx(const CTransaction tx, CValidationState &state); void acceptTxFail(const CTransaction tx); -void getInputTx(CScript scriptPubKey, CTransaction &txIn); +/**** + * In order to do tests there needs to be inputs to spend. + * This method creates a block and returns a transaction that spends the coinbase. + * @param scriptPubKey + * @returns the transaction + */ +CTransaction getInputTx(CScript scriptPubKey); CMutableTransaction spendTx(const CTransaction &txIn, int nOut=0); std::vector getSig(const CMutableTransaction mtx, CScript inputPubKey, int nIn=0); -#endif /* TESTUTILS_H */ +class TestWallet; + +class TestChain +{ +public: + /*** + * ctor to create a chain + */ + TestChain(); + /** + * Generate a block + * @returns the block generated + */ + CBlock generateBlock(); + /*** + * @returns the notary's key + */ + CKey getNotaryKey(); + /*** + * Add a transactoion to the mempool + * @param tx the transaction + * @returns the results + */ + CValidationState acceptTx(const CTransaction &tx); + /*** + * Creates a wallet with a specific key + * @param key the key + * @returns the wallet + */ + std::shared_ptr AddWallet(const CKey &key); + /**** + * Create a wallet + * @returns the wallet + */ + std::shared_ptr AddWallet(); +private: + std::vector> toBeNotified; +}; + +/*** + * A simplistic (dumb) wallet for helping with testing + * - It does not keep track of spent transactions + * - Blocks containing vOuts that apply are added to the front of a vector + */ +class TestWallet +{ +public: + TestWallet(TestChain* chain); + TestWallet(TestChain* chain, const CKey& in); + /*** + * @returns the public key + */ + CPubKey GetPubKey() const; + /*** + * @returns the private key + */ + CKey GetPrivKey() const; + /*** + * Sign a typical transaction + * @param hash the hash to sign + * @param hashType SIGHASH_ALL or something similar + * @returns the bytes to add to ScriptSig + */ + std::vector Sign(uint256 hash, unsigned char hashType); + /*** + * Sign a cryptocondition + * @param cc the cryptocondition + * @param hash the hash to sign + * @returns the bytes to add to ScriptSig + */ + std::vector Sign(CC* cc, uint256 hash); + /*** + * Notifies this wallet of a new block + */ + void BlockNotification(const CBlock& block); + /*** + * Get a transaction that has funds + * NOTE: If no single transaction matches, throws + * @param needed how much is needed + * @returns a pair of CTransaction and the n value of the vout + */ + std::pair GetAvailable(CAmount needed); + /*** + * Add a transaction to the list of available vouts + * @param tx the transaction + * @param n the n value of the vout + */ + void AddOut(CTransaction tx, uint32_t n); + /*** + * Transfer to another user + * @param to who to transfer to + * @param amount the amount + * @returns the results + */ + CValidationState Transfer(std::shared_ptr to, CAmount amount, CAmount fee = 0); +private: + TestChain *chain; + CKey key; + std::vector> availableTransactions; + CScript destScript; +}; From 42859e59651bf3a5c86a5df62f12c09e37f16e93 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 26 Oct 2021 13:57:03 -0500 Subject: [PATCH 02/47] Add alert tests --- src/Makefile.am | 4 +- src/Makefile.gtest.include | 26 +- src/Makefile.ktest.include | 3 +- src/alertkeys.h | 6 +- src/test-komodo/test_alerts.cpp | 411 ++++++++++++++++++++++++++++++++ 5 files changed, 430 insertions(+), 20 deletions(-) create mode 100644 src/test-komodo/test_alerts.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 2266258bd7e..7ef9e498ef0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -815,6 +815,6 @@ endif if ENABLE_TESTS include Makefile.ktest.include -#include Makefile.test.include -#include Makefile.gtest.include +#include Makefile.test.include # bitcoin tests +#include Makefile.gtest.include # zcash tests endif diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index 05b13225454..a07694820f4 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -2,24 +2,24 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or https://www.opensource.org/licenses/mit-license.php . -TESTS += komodo-gtest -bin_PROGRAMS += komodo-gtest +TESTS += zcash-gtest +bin_PROGRAMS += zcash-gtest # tool for generating our public parameters -komodo_gtest_SOURCES = \ +zcash_gtest_SOURCES = \ gtest/main.cpp \ gtest/utils.cpp \ gtest/test_checktransaction.cpp \ gtest/json_test_vectors.cpp \ - gtest/json_test_vectors.h \ - # gtest/test_foundersreward.cpp \ - gtest/test_wallet_zkeys.cpp \ + gtest/json_test_vectors.h + # These tests are order-dependent, because they # depend on global state (see #1539) if ENABLE_WALLET zcash_gtest_SOURCES += \ wallet/gtest/test_wallet_zkeys.cpp endif + zcash_gtest_SOURCES += \ gtest/test_tautology.cpp \ gtest/test_deprecation.cpp \ @@ -54,22 +54,24 @@ zcash_gtest_SOURCES += \ wallet/gtest/test_wallet.cpp endif -komodo_gtest_CPPFLAGS = $(AM_CPPFLAGS) -DMULTICORE -fopenmp -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DSTATIC $(BITCOIN_INCLUDES) -komodo_gtest_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +zcash_gtest_CPPFLAGS = $(AM_CPPFLAGS) -DMULTICORE -fopenmp -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DSTATIC $(BITCOIN_INCLUDES) +zcash_gtest_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -komodo_gtest_LDADD = -lgtest -lgmock $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBVERUS_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \ +zcash_gtest_LDADD = -lgtest -lgmock $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBVERUS_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \ $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) + if ENABLE_ZMQ zcash_gtest_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif + if ENABLE_WALLET -komodo_gtest_LDADD += $(LIBBITCOIN_WALLET) +zcash_gtest_LDADD += $(LIBBITCOIN_WALLET) endif -komodo_gtest_LDADD += $(LIBZCASH_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(LIBZCASH) $(LIBSNARK) $(LIBZCASH_LIBS) +zcash_gtest_LDADD += $(LIBZCASH_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(LIBZCASH) $(LIBSNARK) $(LIBZCASH_LIBS) if ENABLE_PROTON -komodo_gtest_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) +zcash_gtest_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) endif diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 93aa7bc058f..adf3edca540 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -16,7 +16,8 @@ komodo_test_SOURCES = \ test-komodo/test_addrman.cpp \ test-komodo/test_netbase_tests.cpp \ test-komodo/test_events.cpp \ - test-komodo/test_hex.cpp + test-komodo/test_hex.cpp \ + test-komodo/test_alerts.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/alertkeys.h b/src/alertkeys.h index 106576add2a..82bdd680dfc 100644 --- a/src/alertkeys.h +++ b/src/alertkeys.h @@ -1,3 +1,4 @@ +#pragma once /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * @@ -13,13 +14,8 @@ * * ******************************************************************************/ -#ifndef BITCOIN_ALERTKEYS_H -#define BITCOIN_ALERTKEYS_H - // REMINDER: DO NOT COMMIT YOUR PRIVATE KEYS TO THE GIT REPOSITORY! const char* pszPrivKey = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; const char* pszTestNetPrivKey = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; -#endif - diff --git a/src/test-komodo/test_alerts.cpp b/src/test-komodo/test_alerts.cpp new file mode 100644 index 00000000000..5280dca3375 --- /dev/null +++ b/src/test-komodo/test_alerts.cpp @@ -0,0 +1,411 @@ +// 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. + +// +// Unit tests for alert system +// + +#include "alert.h" +#include "chain.h" +#include "chainparams.h" +#include "clientversion.h" +#include "test/data/alertTests.raw.h" + +#include "main.h" +#include "rpc/protocol.h" +#include "rpc/server.h" +#include "serialize.h" +#include "streams.h" +#include "util.h" +#include "utilstrencodings.h" + +#include "test/test_bitcoin.h" + +#include + +#include +#include +#include + +#include "key.h" +#include + +namespace TestAlerts +{ + + +// Code to output a C-style array of values +template +std::string HexStrArray(const T itbegin, const T itend, int lineLength) +{ + std::string rv; + static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + rv.reserve((itend-itbegin)*3); + int i = 0; + for(T it = itbegin; it < itend; ++it) + { + unsigned char val = (unsigned char)(*it); + if(it != itbegin) + { + if (i % lineLength == 0) + rv.push_back('\n'); + else + rv.push_back(' '); + } + rv.push_back('0'); + rv.push_back('x'); + rv.push_back(hexmap[val>>4]); + rv.push_back(hexmap[val&15]); + rv.push_back(','); + i++; + } + + return rv; +} + +template +inline std::string HexStrArray(const T& vch, int lineLength) +{ + return HexStrArray(vch.begin(), vch.end(), lineLength); +} + +class TestAlerts : public ::testing::Test +{ +public: + TestAlerts() + { + // generate a key that will sign alerts + key.MakeNewKey(false); + pubKey = key.GetPubKey(); + // a place to store the binary file + binary_file = temp_directory / "testAlerts.raw"; + // TODO: adjust the regtest public key so we can verify signatures + // generate the alerts + GenerateAlertTests(); + // Now read it into the alerts collection + ReadAlerts(binary_file); + } + ~TestAlerts() + { + // TODO: Delete temp_directory and everything in it + } + CKey key; + CPubKey pubKey; + std::vector alerts; + boost::filesystem::path temp_directory = boost::filesystem::temp_directory_path(); + boost::filesystem::path binary_file; + + /****** + * @brief reads the alerts that were generated by GenerateAlertTests + */ + static std::vector ReadLines(boost::filesystem::path filepath) + { + std::vector result; + + std::ifstream f(filepath.string().c_str()); + std::string line; + while (std::getline(f,line)) + result.push_back(line); + + return result; + } + + bool ReadAlerts(boost::filesystem::path infile) + { + // read the file into a vector + std::ifstream filestream(binary_file.string().c_str(), std::ios::in | std::ios::binary); + std::vector vch( (std::istreambuf_iterator(filestream)), std::istreambuf_iterator()); + + CDataStream stream(vch, SER_DISK, CLIENT_VERSION); + try { + while (!stream.eof()) + { + CAlert alert; + stream >> alert; + alerts.push_back(alert); + } + } + catch (const std::exception&) { return false; } + return true; + } + + void GenerateAlertTests() + { + CDataStream sBuffer(SER_DISK, CLIENT_VERSION); + + CAlert alert; + alert.nRelayUntil = 60; + alert.nExpiration = 24 * 60 * 60; + alert.nID = 1; + alert.nCancel = 0; // cancels previous messages up to this ID number + alert.nMinVer = 0; // These versions are protocol versions + alert.nMaxVer = 999001; + alert.nPriority = 1; + alert.strComment = "Alert comment"; + alert.strStatusBar = "Alert 1"; + + // Replace SignAndSave with SignAndSerialize + SignAndSerialize(alert, sBuffer); + + // More tests go here ... + alert.setSubVer.insert(std::string("/MagicBean:0.1.0/")); + alert.strStatusBar = "Alert 1 for MagicBean 0.1.0"; + SignAndSerialize(alert, sBuffer); + + alert.setSubVer.insert(std::string("/MagicBean:0.2.0/")); + alert.strStatusBar = "Alert 1 for MagicBean 0.1.0, 0.2.0"; + SignAndSerialize(alert, sBuffer); + + alert.setSubVer.clear(); + ++alert.nID; + alert.nCancel = 1; + alert.nPriority = 100; + alert.strStatusBar = "Alert 2, cancels 1"; + SignAndSerialize(alert, sBuffer); + + alert.nExpiration += 60; + ++alert.nID; + SignAndSerialize(alert, sBuffer); + + ++alert.nID; + alert.nPriority = 5000; + alert.strStatusBar = "Alert 3, disables RPC"; + alert.strRPCError = "RPC disabled"; + SignAndSerialize(alert, sBuffer); + + ++alert.nID; + alert.nPriority = 5000; + alert.strStatusBar = "Alert 4, re-enables RPC"; + alert.strRPCError = ""; + SignAndSerialize(alert, sBuffer); + + ++alert.nID; + alert.nMinVer = 11; + alert.nMaxVer = 22; + alert.nPriority = 100; + SignAndSerialize(alert, sBuffer); + + ++alert.nID; + alert.strStatusBar = "Alert 2 for MagicBean 0.1.0"; + alert.setSubVer.insert(std::string("/MagicBean:0.1.0/")); + SignAndSerialize(alert, sBuffer); + + ++alert.nID; + alert.nMinVer = 0; + alert.nMaxVer = 999999; + alert.strStatusBar = "Evil Alert'; /bin/ls; echo '"; + alert.setSubVer.clear(); + bool b = SignAndSerialize(alert, sBuffer); + + if (b) { + // write alerts to a file + std::vector vch = std::vector(sBuffer.begin(), sBuffer.end()); + std::ofstream outfile(binary_file.string().c_str(), std::ios::out | std::ios::binary); + outfile.write((const char*)&vch[0], vch.size()); + outfile.close(); + } + } + + + // Sign CAlert with alert private key + bool SignAlert(CAlert &alert) + { + // serialize alert data + CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); + sMsg << *(CUnsignedAlert*)&alert; + alert.vchMsg = std::vector(sMsg.begin(), sMsg.end()); + + // sign alert + if (!key.Sign(Hash(alert.vchMsg.begin(), alert.vchMsg.end()), alert.vchSig)) + { + printf("SignAlert() : key.Sign failed\n"); + return false; + } + return true; + } + + // Sign a CAlert and serialize it + bool SignAndSerialize(CAlert &alert, CDataStream &buffer) + { + // Sign + if(!SignAlert(alert)) + { + printf("SignAndSerialize() : could not sign alert\n"); + return false; + } + // ...and save! + buffer << alert; + return true; + } +}; + + +// macro to assist with log messages +#define GTEST_COUT std::cerr << "[ ] [ INFO ]" + +TEST_F(TestAlerts, AlertApplies) +{ + SetMockTime(11); + CPubKey pubKey = key.GetPubKey(); + std::vector alertKey{pubKey.begin(), std::next(pubKey.begin())}; + + for(const CAlert& alert : alerts) + { + EXPECT_TRUE(alert.CheckSignature(alertKey)); + } + + EXPECT_EQ(alerts.size(), 3); + + // Matches: + EXPECT_TRUE(alerts[0].AppliesTo(1, "")); + EXPECT_TRUE(alerts[0].AppliesTo(999001, "")); + EXPECT_TRUE(alerts[0].AppliesTo(1, "/MagicBean:11.11.11/")); + + EXPECT_TRUE(alerts[1].AppliesTo(1, "/MagicBean:0.1.0/")); + EXPECT_TRUE(alerts[1].AppliesTo(999001, "/MagicBean:0.1.0/")); + + EXPECT_TRUE(alerts[2].AppliesTo(1, "/MagicBean:0.1.0/")); + EXPECT_TRUE(alerts[2].AppliesTo(1, "/MagicBean:0.2.0/")); + + // Don't match: + EXPECT_TRUE(!alerts[0].AppliesTo(-1, "")); + EXPECT_TRUE(!alerts[0].AppliesTo(999002, "")); + + EXPECT_TRUE(!alerts[1].AppliesTo(1, "")); + EXPECT_TRUE(!alerts[1].AppliesTo(1, "MagicBean:0.1.0")); + EXPECT_TRUE(!alerts[1].AppliesTo(1, "/MagicBean:0.1.0")); + EXPECT_TRUE(!alerts[1].AppliesTo(1, "MagicBean:0.1.0/")); + EXPECT_TRUE(!alerts[1].AppliesTo(-1, "/MagicBean:0.1.0/")); + EXPECT_TRUE(!alerts[1].AppliesTo(999002, "/MagicBean:0.1.0/")); + EXPECT_TRUE(!alerts[1].AppliesTo(1, "/MagicBean:0.2.0/")); + + EXPECT_TRUE(!alerts[2].AppliesTo(1, "/MagicBean:0.3.0/")); + + SetMockTime(0); +} + + +TEST_F(TestAlerts, AlertNotify) +{ + SetMockTime(11); + const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); + + boost::filesystem::path temp = GetTempPath() / + boost::filesystem::unique_path("alertnotify-%%%%.txt"); + + // Put all alerts into a temp file + mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string(); + BOOST_FOREACH(CAlert alert, alerts) + alert.ProcessAlert(alertKey, false); + + std::vector r = ReadLines(temp); + EXPECT_EQ(r.size(), 6u); + +// Windows built-in echo semantics are different than posixy shells. Quotes and +// whitespace are printed literally. + +#ifndef WIN32 + EXPECT_EQ(r[0], "Alert 1"); + EXPECT_EQ(r[1], "Alert 2, cancels 1"); + EXPECT_EQ(r[2], "Alert 2, cancels 1"); + EXPECT_EQ(r[3], "Alert 3, disables RPC"); + EXPECT_EQ(r[4], "Alert 4, reenables RPC"); // dashes should be removed + EXPECT_EQ(r[5], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed +#else + EXPECT_EQ(r[0], "'Alert 1' "); + EXPECT_EQ(r[1], "'Alert 2, cancels 1' "); + EXPECT_EQ(r[2], "'Alert 2, cancels 1' "); + EXPECT_EQ(r[3], "'Alert 3, disables RPC' "); + EXPECT_EQ(r[4], "'Alert 4, reenables RPC' "); // dashes should be removed + EXPECT_EQ(r[5], "'Evil Alert; /bin/ls; echo ' "); +#endif + boost::filesystem::remove(temp); + + SetMockTime(0); + mapAlerts.clear(); +} + +TEST_F(TestAlerts, AlertDisablesRPC) +{ + SetMockTime(11); + const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); + + // Command should work before alerts + EXPECT_EQ(GetWarnings("rpc"), ""); + + // First alert should disable RPC + alerts[5].ProcessAlert(alertKey, false); + EXPECT_EQ(alerts[5].strRPCError, "RPC disabled"); + EXPECT_EQ(GetWarnings("rpc"), "RPC disabled"); + + // Second alert should re-enable RPC + alerts[6].ProcessAlert(alertKey, false); + EXPECT_EQ(alerts[6].strRPCError, ""); + EXPECT_EQ(GetWarnings("rpc"), ""); + + SetMockTime(0); + mapAlerts.clear(); +} + +static bool falseFunc() { return false; } + +TEST_F(TestAlerts, PartitionAlert) +{ + // Test PartitionCheck + CCriticalSection csDummy; + CBlockIndex indexDummy[400]; + CChainParams& params = Params(CBaseChainParams::MAIN); + int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; + + // Generate fake blockchain timestamps relative to + // an arbitrary time: + int64_t now = 1427379054; + SetMockTime(now); + for (int i = 0; i < 400; i++) + { + indexDummy[i].phashBlock = NULL; + if (i == 0) indexDummy[i].pprev = NULL; + else indexDummy[i].pprev = &indexDummy[i-1]; + indexDummy[i].SetHeight(i); + indexDummy[i].nTime = now - (400-i)*nPowTargetSpacing; + // Other members don't matter, the partition check code doesn't + // use them + } + + // Test 1: chain with blocks every nPowTargetSpacing seconds, + // as normal, no worries: + PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); + EXPECT_TRUE(strMiscWarning.empty()); + + // Test 2: go 3.5 hours without a block, expect a warning: + now += 3*60*60+30*60; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); + EXPECT_TRUE(!strMiscWarning.empty()); + GTEST_COUT << "Got alert text: " << strMiscWarning << std::endl; + strMiscWarning = ""; + + // Test 3: test the "partition alerts only go off once per day" + // code: + now += 60*10; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); + EXPECT_TRUE(strMiscWarning.empty()); + + // Test 4: get 2.5 times as many blocks as expected: + now += 60*60*24; // Pretend it is a day later + SetMockTime(now); + int64_t quickSpacing = nPowTargetSpacing*2/5; + for (int i = 0; i < 400; i++) // Tweak chain timestamps: + indexDummy[i].nTime = now - (400-i)*quickSpacing; + PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); + EXPECT_TRUE(!strMiscWarning.empty()); + GTEST_COUT << "Got alert text: " << strMiscWarning << std::endl; + strMiscWarning = ""; + + SetMockTime(0); +} + +} // namespace TestAlerts From bc97c3b44ac665478f44f39e59192d79e1b810f4 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 26 Oct 2021 15:54:56 -0500 Subject: [PATCH 03/47] fix pub key --- src/test-komodo/test_alerts.cpp | 46 +++++++++++++++++---------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/test-komodo/test_alerts.cpp b/src/test-komodo/test_alerts.cpp index 5280dca3375..31e5ed260ae 100644 --- a/src/test-komodo/test_alerts.cpp +++ b/src/test-komodo/test_alerts.cpp @@ -89,7 +89,7 @@ class TestAlerts : public ::testing::Test } ~TestAlerts() { - // TODO: Delete temp_directory and everything in it + boost::filesystem::remove(binary_file); } CKey key; CPubKey pubKey; @@ -243,20 +243,19 @@ class TestAlerts : public ::testing::Test // macro to assist with log messages -#define GTEST_COUT std::cerr << "[ ] [ INFO ]" +#define GTEST_COUT std::cerr << "[ ] [ INFO ] " TEST_F(TestAlerts, AlertApplies) { SetMockTime(11); - CPubKey pubKey = key.GetPubKey(); - std::vector alertKey{pubKey.begin(), std::next(pubKey.begin())}; + std::vector alertKey{pubKey.begin(), pubKey.end()}; for(const CAlert& alert : alerts) { EXPECT_TRUE(alert.CheckSignature(alertKey)); } - EXPECT_EQ(alerts.size(), 3); + EXPECT_GE(alerts.size(), 3); // Matches: EXPECT_TRUE(alerts[0].AppliesTo(1, "")); @@ -290,14 +289,14 @@ TEST_F(TestAlerts, AlertApplies) TEST_F(TestAlerts, AlertNotify) { SetMockTime(11); - const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); + const std::vector& alertKey{pubKey.begin(), pubKey.end()}; boost::filesystem::path temp = GetTempPath() / boost::filesystem::unique_path("alertnotify-%%%%.txt"); // Put all alerts into a temp file mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string(); - BOOST_FOREACH(CAlert alert, alerts) + for(CAlert alert : alerts) alert.ProcessAlert(alertKey, false); std::vector r = ReadLines(temp); @@ -321,7 +320,7 @@ TEST_F(TestAlerts, AlertNotify) EXPECT_EQ(r[4], "'Alert 4, reenables RPC' "); // dashes should be removed EXPECT_EQ(r[5], "'Evil Alert; /bin/ls; echo ' "); #endif - boost::filesystem::remove(temp); + EXPECT_TRUE(boost::filesystem::remove(temp)); SetMockTime(0); mapAlerts.clear(); @@ -330,7 +329,7 @@ TEST_F(TestAlerts, AlertNotify) TEST_F(TestAlerts, AlertDisablesRPC) { SetMockTime(11); - const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); + const std::vector& alertKey{pubKey.begin(), pubKey.end()}; // Command should work before alerts EXPECT_EQ(GetWarnings("rpc"), ""); @@ -355,34 +354,37 @@ TEST_F(TestAlerts, PartitionAlert) { // Test PartitionCheck CCriticalSection csDummy; - CBlockIndex indexDummy[400]; CChainParams& params = Params(CBaseChainParams::MAIN); - int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; + int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; // for komodo mainnet, currently 60 + int64_t normalBlocksPerDay = 86400 / nPowTargetSpacing; + CBlockIndex indexDummy[86400 / 60]; // hard coded to avoid compiler warnings about variable length buffer // Generate fake blockchain timestamps relative to // an arbitrary time: int64_t now = 1427379054; SetMockTime(now); - for (int i = 0; i < 400; i++) + for (int i = 0; i < normalBlocksPerDay; i++) { - indexDummy[i].phashBlock = NULL; - if (i == 0) indexDummy[i].pprev = NULL; - else indexDummy[i].pprev = &indexDummy[i-1]; + indexDummy[i].phashBlock = nullptr; + if (i == 0) + indexDummy[i].pprev = nullptr; + else + indexDummy[i].pprev = &indexDummy[i-1]; indexDummy[i].SetHeight(i); - indexDummy[i].nTime = now - (400-i)*nPowTargetSpacing; + indexDummy[i].nTime = now - (normalBlocksPerDay-i)*nPowTargetSpacing; // Other members don't matter, the partition check code doesn't // use them } // Test 1: chain with blocks every nPowTargetSpacing seconds, // as normal, no worries: - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[normalBlocksPerDay - 1], nPowTargetSpacing); EXPECT_TRUE(strMiscWarning.empty()); // Test 2: go 3.5 hours without a block, expect a warning: now += 3*60*60+30*60; SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[normalBlocksPerDay - 1], nPowTargetSpacing); EXPECT_TRUE(!strMiscWarning.empty()); GTEST_COUT << "Got alert text: " << strMiscWarning << std::endl; strMiscWarning = ""; @@ -391,16 +393,16 @@ TEST_F(TestAlerts, PartitionAlert) // code: now += 60*10; SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[normalBlocksPerDay - 1], nPowTargetSpacing); EXPECT_TRUE(strMiscWarning.empty()); // Test 4: get 2.5 times as many blocks as expected: now += 60*60*24; // Pretend it is a day later SetMockTime(now); int64_t quickSpacing = nPowTargetSpacing*2/5; - for (int i = 0; i < 400; i++) // Tweak chain timestamps: - indexDummy[i].nTime = now - (400-i)*quickSpacing; - PartitionCheck(falseFunc, csDummy, &indexDummy[399], nPowTargetSpacing); + for (int i = 0; i < normalBlocksPerDay; i++) // Tweak chain timestamps: + indexDummy[i].nTime = now - (normalBlocksPerDay-i)*quickSpacing; + PartitionCheck(falseFunc, csDummy, &indexDummy[normalBlocksPerDay - 1], nPowTargetSpacing); EXPECT_TRUE(!strMiscWarning.empty()); GTEST_COUT << "Got alert text: " << strMiscWarning << std::endl; strMiscWarning = ""; From 948988c4e5b3a4ddff9182394c5ffe46393ef11c Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 28 Oct 2021 07:11:51 -0500 Subject: [PATCH 04/47] Remove temp file --- src/alert.cpp | 3 +- src/cc/Makefile_custom | 9 ++-- src/test-komodo/test_alerts.cpp | 65 ++++++++++++++++++----------- src/test-komodo/test_coinimport.cpp | 6 ++- src/test-komodo/testutils.cpp | 16 ++++--- src/test-komodo/testutils.h | 5 +++ 6 files changed, 65 insertions(+), 39 deletions(-) diff --git a/src/alert.cpp b/src/alert.cpp index e76f6a41108..4991e36058e 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -261,8 +261,7 @@ bool CAlert::ProcessAlert(const std::vector& alertKey, bool fThre return true; } -void -CAlert::Notify(const std::string& strMessage, bool fThread) +void CAlert::Notify(const std::string& strMessage, bool fThread) { std::string strCmd = GetArg("-alertnotify", ""); if (strCmd.empty()) return; diff --git a/src/cc/Makefile_custom b/src/cc/Makefile_custom index 79219ec96c1..364f9f4a121 100755 --- a/src/cc/Makefile_custom +++ b/src/cc/Makefile_custom @@ -10,9 +10,9 @@ RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program $(info $(OS)) OS := $(shell uname -s) $(info $(OS)) -TARGET = customcc.so -TARGET_DARWIN = customcc.dylib -TARGET_WIN = customcc.dll +TARGET = ../libcc.so +TARGET_DARWIN = ../libcc.dylib +TARGET_WIN = ../libcc.dll SOURCES = cclib.cpp #HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ @@ -22,16 +22,13 @@ $(TARGET): $(SOURCES) $(info Building cclib to src/) ifeq ($(OS),Darwin) $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) -c $(SOURCES) - cp $(TARGET_DARWIN) ../libcc.dylib else ifeq ($(HOST),x86_64-w64-mingw32) $(info WINDOWS) $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) -c $(SOURCES) - cp $(TARGET_WIN) ../libcc.dll #else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host else $(info LINUX) $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES) - cp $(TARGET) ../libcc.so endif clean: diff --git a/src/test-komodo/test_alerts.cpp b/src/test-komodo/test_alerts.cpp index 31e5ed260ae..ed6c837c532 100644 --- a/src/test-komodo/test_alerts.cpp +++ b/src/test-komodo/test_alerts.cpp @@ -30,10 +30,14 @@ #include "key.h" #include +#include // for ::remove +#include namespace TestAlerts { +// macro to assist with log messages +#define GTEST_COUT std::cerr << "[ ] [ INFO ] " // Code to output a C-style array of values template @@ -71,31 +75,50 @@ inline std::string HexStrArray(const T& vch, int lineLength) return HexStrArray(vch.begin(), vch.end(), lineLength); } +// Stuff used by several tests, and set up by TestAlerts::SetupTestCase() +boost::filesystem::path alertnotify_file; +CKey key; +CPubKey pubKey; +std::vector alerts; +boost::filesystem::path temp_directory = boost::filesystem::temp_directory_path(); +boost::filesystem::path binary_file; + class TestAlerts : public ::testing::Test { public: TestAlerts() + { + } + ~TestAlerts() + { + } + static void SetUpTestCase() { // generate a key that will sign alerts key.MakeNewKey(false); pubKey = key.GetPubKey(); // a place to store the binary file binary_file = temp_directory / "testAlerts.raw"; - // TODO: adjust the regtest public key so we can verify signatures // generate the alerts GenerateAlertTests(); // Now read it into the alerts collection ReadAlerts(binary_file); + alertnotify_file = GetTempPath() / + boost::filesystem::unique_path("alertnotify-%%%%.txt"); + mapArgs["-alertnotify"] = std::string("echo %s >> ") + alertnotify_file.string(); } - ~TestAlerts() + static void TearDownTestCase() { - boost::filesystem::remove(binary_file); + if (!boost::filesystem::remove( alertnotify_file) ) + GTEST_COUT << "Boost says it was unable to remove file " << alertnotify_file.string() + << std::endl; + if (!boost::filesystem::remove(binary_file)) + GTEST_COUT << "Unable to remove file " << binary_file.string() << std::endl; } - CKey key; - CPubKey pubKey; - std::vector alerts; - boost::filesystem::path temp_directory = boost::filesystem::temp_directory_path(); - boost::filesystem::path binary_file; + + virtual void SetUp() {} + + virtual void TearDown() {} /****** * @brief reads the alerts that were generated by GenerateAlertTests @@ -108,11 +131,11 @@ class TestAlerts : public ::testing::Test std::string line; while (std::getline(f,line)) result.push_back(line); - + f.close(); return result; } - bool ReadAlerts(boost::filesystem::path infile) + static bool ReadAlerts(boost::filesystem::path infile) { // read the file into a vector std::ifstream filestream(binary_file.string().c_str(), std::ios::in | std::ios::binary); @@ -131,7 +154,7 @@ class TestAlerts : public ::testing::Test return true; } - void GenerateAlertTests() + static void GenerateAlertTests() { CDataStream sBuffer(SER_DISK, CLIENT_VERSION); @@ -208,9 +231,8 @@ class TestAlerts : public ::testing::Test } } - // Sign CAlert with alert private key - bool SignAlert(CAlert &alert) + static bool SignAlert(CAlert &alert) { // serialize alert data CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); @@ -227,7 +249,7 @@ class TestAlerts : public ::testing::Test } // Sign a CAlert and serialize it - bool SignAndSerialize(CAlert &alert, CDataStream &buffer) + static bool SignAndSerialize(CAlert &alert, CDataStream &buffer) { // Sign if(!SignAlert(alert)) @@ -241,10 +263,6 @@ class TestAlerts : public ::testing::Test } }; - -// macro to assist with log messages -#define GTEST_COUT std::cerr << "[ ] [ INFO ] " - TEST_F(TestAlerts, AlertApplies) { SetMockTime(11); @@ -291,15 +309,10 @@ TEST_F(TestAlerts, AlertNotify) SetMockTime(11); const std::vector& alertKey{pubKey.begin(), pubKey.end()}; - boost::filesystem::path temp = GetTempPath() / - boost::filesystem::unique_path("alertnotify-%%%%.txt"); - - // Put all alerts into a temp file - mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string(); for(CAlert alert : alerts) alert.ProcessAlert(alertKey, false); - std::vector r = ReadLines(temp); + std::vector r = ReadLines( alertnotify_file); EXPECT_EQ(r.size(), 6u); // Windows built-in echo semantics are different than posixy shells. Quotes and @@ -320,7 +333,6 @@ TEST_F(TestAlerts, AlertNotify) EXPECT_EQ(r[4], "'Alert 4, reenables RPC' "); // dashes should be removed EXPECT_EQ(r[5], "'Evil Alert; /bin/ls; echo ' "); #endif - EXPECT_TRUE(boost::filesystem::remove(temp)); SetMockTime(0); mapAlerts.clear(); @@ -408,6 +420,9 @@ TEST_F(TestAlerts, PartitionAlert) strMiscWarning = ""; SetMockTime(0); + // PartitionCheck adds records to the alertnotify file asynchronously. + // To remove the file, we need to wait briefly + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } // namespace TestAlerts diff --git a/src/test-komodo/test_coinimport.cpp b/src/test-komodo/test_coinimport.cpp index 05c709eb309..717c517406c 100644 --- a/src/test-komodo/test_coinimport.cpp +++ b/src/test-komodo/test_coinimport.cpp @@ -19,6 +19,8 @@ extern Eval* EVAL_TEST; +std::shared_ptr testChain; + namespace TestCoinImport { @@ -54,7 +56,9 @@ class TestCoinImport : public ::testing::Test, public Eval { protected: - static void SetUpTestCase() { setupChain(); } + static void SetUpTestCase() { testChain = std::make_shared(); } + static void TearDownTestCase() { testChain = nullptr; }; + virtual void SetUp() { ASSETCHAINS_CC = 1; EVAL_TEST = this; diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index 4a6f7c89026..242460d6e78 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -53,11 +53,6 @@ void setupChain() // Init blockchain ClearDatadirCache(); - auto pathTemp = GetTempPath() / strprintf("test_komodo_%li_%i", GetTime(), GetRand(100000)); - if (ASSETCHAINS_SYMBOL[0]) - pathTemp = pathTemp / strprintf("_%s", ASSETCHAINS_SYMBOL); - boost::filesystem::create_directories(pathTemp); - mapArgs["-datadir"] = pathTemp.string(); pblocktree = new CBlockTreeDB(1 << 20, true); CCoinsViewDB *pcoinsdbview = new CCoinsViewDB(1 << 23, true); pcoinsTip = new CCoinsViewCache(pcoinsdbview); @@ -167,12 +162,23 @@ CTransaction getInputTx(CScript scriptPubKey) TestChain::TestChain() { + dataDir = GetTempPath() / strprintf("test_komodo_%li_%i", GetTime(), GetRand(100000)); + if (ASSETCHAINS_SYMBOL[0]) + dataDir = dataDir / strprintf("_%s", ASSETCHAINS_SYMBOL); + boost::filesystem::create_directories(dataDir); + mapArgs["-datadir"] = dataDir.string(); + setupChain(); CBitcoinSecret vchSecret; vchSecret.SetString(notarySecret); // this returns false due to network prefix mismatch but works anyway notaryKey = vchSecret.GetKey(); } +TestChain::~TestChain() +{ + boost::filesystem::remove_all(dataDir); +} + CBlock TestChain::generateBlock() { CBlock block; diff --git a/src/test-komodo/testutils.h b/src/test-komodo/testutils.h index 2f624fd78d9..5a3442693ed 100644 --- a/src/test-komodo/testutils.h +++ b/src/test-komodo/testutils.h @@ -43,6 +43,10 @@ class TestChain * ctor to create a chain */ TestChain(); + /*** + * dtor to release resources + */ + ~TestChain(); /** * Generate a block * @returns the block generated @@ -71,6 +75,7 @@ class TestChain std::shared_ptr AddWallet(); private: std::vector> toBeNotified; + boost::filesystem::path dataDir; }; /*** From bae9e3a0dfe615c62c466fa3b41e1ed47d72d055 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 28 Oct 2021 08:51:46 -0500 Subject: [PATCH 05/47] properly shutdown tests --- src/test-komodo/main.cpp | 4 +++- src/test-komodo/test_alerts.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test-komodo/main.cpp b/src/test-komodo/main.cpp index 1adb729b4a2..7bcd5db543e 100644 --- a/src/test-komodo/main.cpp +++ b/src/test-komodo/main.cpp @@ -18,5 +18,7 @@ int main(int argc, char **argv) { notaryKey = vchSecret.GetKey(); testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + auto retval = RUN_ALL_TESTS(); + ECC_Stop(); + return retval; } diff --git a/src/test-komodo/test_alerts.cpp b/src/test-komodo/test_alerts.cpp index ed6c837c532..d3bf42604fd 100644 --- a/src/test-komodo/test_alerts.cpp +++ b/src/test-komodo/test_alerts.cpp @@ -421,7 +421,7 @@ TEST_F(TestAlerts, PartitionAlert) SetMockTime(0); // PartitionCheck adds records to the alertnotify file asynchronously. - // To remove the file, we need to wait briefly + // To remove the file, we need to wait briefly for it to be closed. std::this_thread::sleep_for(std::chrono::milliseconds(100)); } From 324a3ddd8f930cca324cb6f57240f5b186127224 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 28 Oct 2021 09:01:50 -0500 Subject: [PATCH 06/47] Move zcash tests to komodo --- src/Makefile.gtest.include | 2 -- src/Makefile.ktest.include | 4 +++- src/{gtest => test-komodo}/test_equihash.cpp | 0 src/{gtest => test-komodo}/test_random.cpp | 12 ++++++++++-- 4 files changed, 13 insertions(+), 5 deletions(-) rename src/{gtest => test-komodo}/test_equihash.cpp (100%) rename src/{gtest => test-komodo}/test_random.cpp (91%) diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index a07694820f4..7a6082b3dd0 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -23,7 +23,6 @@ endif zcash_gtest_SOURCES += \ gtest/test_tautology.cpp \ gtest/test_deprecation.cpp \ - gtest/test_equihash.cpp \ gtest/test_httprpc.cpp \ gtest/test_joinsplit.cpp \ gtest/test_keys.cpp \ @@ -34,7 +33,6 @@ zcash_gtest_SOURCES += \ gtest/test_metrics.cpp \ gtest/test_miner.cpp \ gtest/test_pow.cpp \ - gtest/test_random.cpp \ gtest/test_rpc.cpp \ gtest/test_sapling_note.cpp \ gtest/test_transaction.cpp \ diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index adf3edca540..2c269558218 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -17,7 +17,9 @@ komodo_test_SOURCES = \ test-komodo/test_netbase_tests.cpp \ test-komodo/test_events.cpp \ test-komodo/test_hex.cpp \ - test-komodo/test_alerts.cpp + test-komodo/test_alerts.cpp \ + test-komodo/test_equihash.cpp \ + test-komodo/test_random.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/gtest/test_equihash.cpp b/src/test-komodo/test_equihash.cpp similarity index 100% rename from src/gtest/test_equihash.cpp rename to src/test-komodo/test_equihash.cpp diff --git a/src/gtest/test_random.cpp b/src/test-komodo/test_random.cpp similarity index 91% rename from src/gtest/test_random.cpp rename to src/test-komodo/test_random.cpp index d89702bcdf4..91d390e05a3 100644 --- a/src/gtest/test_random.cpp +++ b/src/test-komodo/test_random.cpp @@ -2,8 +2,16 @@ #include "random.h" -extern int GenZero(int n); -extern int GenMax(int n); +int GenZero(int n) +{ + return 0; +} + +int GenMax(int n) +{ + return n-1; +} + TEST(Random, MappedShuffle) { std::vector a {8, 4, 6, 3, 5}; From fad7afb31963efcc8778de2638061684fe279075 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 28 Oct 2021 09:35:49 -0500 Subject: [PATCH 07/47] serialize block header size test --- src/Makefile.ktest.include | 3 ++- src/{gtest => test-komodo}/test_block.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) rename src/{gtest => test-komodo}/test_block.cpp (50%) diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 2c269558218..3631647ef8d 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -19,7 +19,8 @@ komodo_test_SOURCES = \ test-komodo/test_hex.cpp \ test-komodo/test_alerts.cpp \ test-komodo/test_equihash.cpp \ - test-komodo/test_random.cpp + test-komodo/test_random.cpp \ + test-komodo/test_block.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/gtest/test_block.cpp b/src/test-komodo/test_block.cpp similarity index 50% rename from src/gtest/test_block.cpp rename to src/test-komodo/test_block.cpp index a0cdc11622b..972cc64e78c 100644 --- a/src/gtest/test_block.cpp +++ b/src/test-komodo/test_block.cpp @@ -2,12 +2,13 @@ #include "primitives/block.h" - TEST(block_tests, header_size_is_expected) { - // Dummy header with an empty Equihash solution. + // Header with an empty Equihash solution. CBlockHeader header; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << header; - ASSERT_EQ(ss.size(), CBlockHeader::HEADER_SIZE); + auto stream_size = CBlockHeader::HEADER_SIZE + 1; + // ss.size is +1 due to data stream header of 1 byte + EXPECT_EQ(ss.size(), stream_size); } From 42bec82812d45d88c1bf82282931376d0e907b98 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 28 Oct 2021 09:46:30 -0500 Subject: [PATCH 08/47] mempool tests --- src/Makefile.gtest.include | 1 - src/Makefile.ktest.include | 3 +- src/{gtest => test-komodo}/test_mempool.cpp | 49 ++++++++++++++++++++- 3 files changed, 49 insertions(+), 4 deletions(-) rename src/{gtest => test-komodo}/test_mempool.cpp (87%) diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index 7a6082b3dd0..cddf62d4ae9 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -28,7 +28,6 @@ zcash_gtest_SOURCES += \ gtest/test_keys.cpp \ gtest/test_keystore.cpp \ gtest/test_noteencryption.cpp \ - gtest/test_mempool.cpp \ gtest/test_merkletree.cpp \ gtest/test_metrics.cpp \ gtest/test_miner.cpp \ diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 3631647ef8d..29e9ab4f94e 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -20,7 +20,8 @@ komodo_test_SOURCES = \ test-komodo/test_alerts.cpp \ test-komodo/test_equihash.cpp \ test-komodo/test_random.cpp \ - test-komodo/test_block.cpp + test-komodo/test_block.cpp \ + test-komodo/test_mempool.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/gtest/test_mempool.cpp b/src/test-komodo/test_mempool.cpp similarity index 87% rename from src/gtest/test_mempool.cpp rename to src/test-komodo/test_mempool.cpp index 6ef626e5f90..d2d98fb5288 100644 --- a/src/gtest/test_mempool.cpp +++ b/src/test-komodo/test_mempool.cpp @@ -10,8 +10,53 @@ #include "policy/fees.h" #include "util.h" -// Implementation is in test_checktransaction.cpp -extern CMutableTransaction GetValidTransaction(); +void CreateJoinSplitSignature(CMutableTransaction& mtx, uint32_t consensusBranchId) { + // Generate an ephemeral keypair. + uint256 joinSplitPubKey; + unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; + crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); + mtx.joinSplitPubKey = joinSplitPubKey; + + // Compute the correct hSig. + // TODO: #966. + static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); + // Empty output script. + CScript scriptCode; + CTransaction signTx(mtx); + uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId); + if (dataToBeSigned == one) { + throw std::runtime_error("SignatureHash failed"); + } + + // Add the signature + assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, + dataToBeSigned.begin(), 32, + joinSplitPrivKey + ) == 0); +} + +CMutableTransaction GetValidTransaction() { + uint32_t consensusBranchId = SPROUT_BRANCH_ID; + + CMutableTransaction mtx; + mtx.vin.resize(2); + mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); + mtx.vin[0].prevout.n = 0; + mtx.vin[1].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); + mtx.vin[1].prevout.n = 0; + mtx.vout.resize(2); + // mtx.vout[0].scriptPubKey = + mtx.vout[0].nValue = 0; + mtx.vout[1].nValue = 0; + mtx.vjoinsplit.resize(2); + mtx.vjoinsplit[0].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000000"); + mtx.vjoinsplit[0].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); + mtx.vjoinsplit[1].nullifiers.at(0) = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); + mtx.vjoinsplit[1].nullifiers.at(1) = uint256S("0000000000000000000000000000000000000000000000000000000000000003"); + + CreateJoinSplitSignature(mtx, consensusBranchId); + return mtx; +} // Fake the input of transaction 5295156213414ed77f6e538e7e8ebe14492156906b9fe995b242477818789364 // - 532639cc6bebed47c1c69ae36dd498c68a012e74ad12729adbd3dbb56f8f3f4a, 0 From 6e1257dd4f3be1642f66113b43cb90bab8fc4f6f Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 28 Oct 2021 11:59:35 -0500 Subject: [PATCH 09/47] PoW tests --- src/Makefile.ktest.include | 3 +- src/consensus/params.h | 25 +++++++---- src/pow.cpp | 17 ++++++-- src/{gtest => test-komodo}/test_pow.cpp | 57 ++++++++++++++++++++----- 4 files changed, 79 insertions(+), 23 deletions(-) rename src/{gtest => test-komodo}/test_pow.cpp (65%) diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 29e9ab4f94e..c7e8891e307 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -21,7 +21,8 @@ komodo_test_SOURCES = \ test-komodo/test_equihash.cpp \ test-komodo/test_random.cpp \ test-komodo/test_block.cpp \ - test-komodo/test_mempool.cpp + test-komodo/test_mempool.cpp \ + test-komodo/test_pow.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/consensus/params.h b/src/consensus/params.h index 67d84af0bfb..ea55832e4c8 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -109,14 +109,14 @@ struct Params { NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]; /** Proof of work parameters */ - uint256 powLimit; - uint256 powAlternate; + uint256 powLimit; // minimum dificulty limit if EQUIHASH used + uint256 powAlternate; // minimum dificulty limit if EQUIHASH not used boost::optional nPowAllowMinDifficultyBlocksAfterHeight; - int64_t nPowAveragingWindow; - int64_t nPowMaxAdjustDown; - int64_t nPowMaxAdjustUp; - int64_t nPowTargetSpacing; - int64_t nLwmaAjustedWeight; + int64_t nPowAveragingWindow; // lookback window to determine block production speed averages + int64_t nPowMaxAdjustDown; // max percentage difficulty level should be lowered + int64_t nPowMaxAdjustUp; // max percentage difficulty level should be raised + int64_t nPowTargetSpacing; // the target block production speed (in seconds) + int64_t nLwmaAjustedWeight; // k value for work calculation (for non-staked, non-equihash chains) /* Proof of stake parameters */ uint256 posLimit; @@ -127,12 +127,21 @@ struct Params { /* applied to all block times */ int64_t nMaxFutureBlockTime; + /***** + * @returns How long the entire lookback window should take given target values + */ int64_t AveragingWindowTimespan() const { return nPowAveragingWindow * nPowTargetSpacing; } + /**** + * @returns the minimum time the lookback window should take before difficulty should be raised + */ int64_t MinActualTimespan() const { return (AveragingWindowTimespan() * (100 - nPowMaxAdjustUp )) / 100; } + /***** + * @returns the maximum time the lookback window should take before the difficulty should be lowered + */ int64_t MaxActualTimespan() const { return (AveragingWindowTimespan() * (100 + nPowMaxAdjustDown)) / 100; } void SetSaplingHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = height; } void SetOverwinterHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = height; } - uint256 nMinimumChainWork; + uint256 nMinimumChainWork; // the minimum work allowed for this PoW chain }; } // namespace Consensus diff --git a/src/pow.cpp b/src/pow.cpp index bd5c132bc92..4b0485fcdbe 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -389,7 +389,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead if (pindexFirst == NULL) return nProofOfWorkLimit; - bool fNegative,fOverflow; int32_t zawyflag = 0; arith_uint256 easy,origtarget,bnAvg {bnTot / params.nPowAveragingWindow}; + bool fNegative,fOverflow; int32_t zawyflag = 0; + arith_uint256 easy,origtarget; + arith_uint256 bnAvg{bnTot / params.nPowAveragingWindow}; // average number of bits in the lookback window nbits = CalculateNextWorkRequired(bnAvg, pindexLast->GetMedianTimePast(), pindexFirst->GetMedianTimePast(), params); if ( ASSETCHAINS_ADAPTIVEPOW > 0 ) { @@ -503,9 +505,16 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead return(nbits); } +/**** + * @brief calculate the nBits value (work required) for the next block + * @param bnAvg the average nBits value (work required) across the lookback window + * @param nLastBlockTime the time of the most recent block in the lookback window + * @param nFirstBlockTime the time of the first block in the lookback window + * @param params the chain's consensus parameters + * @return the nBits value for the next block + */ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, - int64_t nLastBlockTime, int64_t nFirstBlockTime, - const Consensus::Params& params) + int64_t nLastBlockTime, int64_t nFirstBlockTime, const Consensus::Params& params) { // Limit adjustment step // Use medians to prevent time-warp attacks @@ -528,7 +537,7 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg, else bnLimit = UintToArith256(params.powAlternate); - const arith_uint256 bnPowLimit = bnLimit; //UintToArith256(params.powLimit); + const arith_uint256 bnPowLimit = bnLimit; arith_uint256 bnNew {bnAvg}; bnNew /= params.AveragingWindowTimespan(); bnNew *= nActualTimespan; diff --git a/src/gtest/test_pow.cpp b/src/test-komodo/test_pow.cpp similarity index 65% rename from src/gtest/test_pow.cpp rename to src/test-komodo/test_pow.cpp index 3f7b3f0cef2..4403b68a736 100644 --- a/src/gtest/test_pow.cpp +++ b/src/test-komodo/test_pow.cpp @@ -73,16 +73,19 @@ TEST(PoW, MinDifficultyRules) { SelectParams(CBaseChainParams::TESTNET); const Consensus::Params& params = Params().GetConsensus(); size_t lastBlk = 2*params.nPowAveragingWindow; - size_t firstBlk = lastBlk - params.nPowAveragingWindow; + const uint32_t startTime = 1269211443; // Start with blocks evenly-spaced and equal difficulty std::vector blocks(lastBlk+1); + uint32_t nextTime = startTime; for (int i = 0; i <= lastBlk; i++) { + nextTime = nextTime + params.nPowTargetSpacing; blocks[i].pprev = i ? &blocks[i - 1] : nullptr; - blocks[i].nHeight = params.nPowAllowMinDifficultyBlocksAfterHeight.get() + i; - blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing; + blocks[i].SetHeight(params.nPowAllowMinDifficultyBlocksAfterHeight.get() + i); + blocks[i].nTime = nextTime; blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ - blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); + blocks[i].chainPower.chainWork = i ? blocks[i - 1].chainPower.chainWork + + GetBlockProof(blocks[i - 1]).chainWork : arith_uint256(0); } // Create a new block at the target spacing @@ -96,16 +99,50 @@ TEST(PoW, MinDifficultyRules) { bnRes *= params.AveragingWindowTimespan(); EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); - // Delay last block up to the edge of the min-difficulty limit + // Delay last block a bit, time warp protection should prevent any change next.nTime += params.nPowTargetSpacing * 5; // Result should be unchanged, modulo integer division precision loss EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); - // Delay last block over the min-difficulty limit - next.nTime += 1; + // Delay last block to a huge number. Result should be unchanged, time warp protection + next.nTime = std::numeric_limits::max(); + EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), bnRes.GetCompact()); + + // space all blocks out so the median is above the limits and difficulty should drop + nextTime = startTime; + for (int i = 0; i <= lastBlk; i++) { + nextTime = nextTime + ( params.MaxActualTimespan() / params.nPowAveragingWindow + 1); + blocks[i].nTime = nextTime; + blocks[i].chainPower.chainWork = i ? blocks[i - 1].chainPower.chainWork + + GetBlockProof(blocks[i - 1]).chainWork : arith_uint256(0); + } + + // difficulty should have decreased ( nBits increased ) + EXPECT_GT(GetNextWorkRequired(&blocks[lastBlk], &next, params), + bnRes.GetCompact()); + + // diffuculty should never decrease below minimum + arith_uint256 minWork = UintToArith256(params.nMinimumChainWork); + for (int i = 0; i <= lastBlk; i++) { + blocks[i].nBits = minWork.GetCompact(); + blocks[i].chainPower.chainWork = i ? blocks[i - 1].chainPower.chainWork + + GetBlockProof(blocks[i - 1]).chainWork : arith_uint256(0); + } + EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), minWork.GetCompact()); + + // space all blocks out so the median is under limits and difficulty should increase + nextTime = startTime; + for (int i = 0; i <= lastBlk; i++) { + nextTime = nextTime + (params.MinActualTimespan() / params.nPowAveragingWindow - 1); + blocks[i].nTime = nextTime; + blocks[i].nBits = 0x1e7fffff; /* target 0x007fffff000... */ + blocks[i].chainPower.chainWork = i ? blocks[i - 1].chainPower.chainWork + + GetBlockProof(blocks[i - 1]).chainWork : arith_uint256(0); + } + + // difficulty should have increased ( nBits decreased ) + EXPECT_LT(GetNextWorkRequired(&blocks[lastBlk], &next, params), + bnRes.GetCompact()); - // Result should be the minimum difficulty - EXPECT_EQ(GetNextWorkRequired(&blocks[lastBlk], &next, params), - UintToArith256(params.powLimit).GetCompact()); } From defe10dd318939638eedcbbcd385f261e4fb13a3 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 28 Oct 2021 14:44:47 -0500 Subject: [PATCH 10/47] PoW min difficulty test --- src/chainparams.cpp | 15 --------------- src/consensus/params.h | 2 +- src/main.cpp | 12 +----------- src/test-komodo/test_pow.cpp | 2 +- 4 files changed, 3 insertions(+), 28 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 264bd512dbb..8ce4b709712 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -131,9 +131,6 @@ class CMainParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; - // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000281b32ff3198a1"); - /** * The message start string is designed to be unlikely to occur in normal data. * The characters are rarely used upper ASCII, not valid as UTF-8, and produce @@ -285,9 +282,6 @@ class CTestNetParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170007; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 280000; - // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000000001d0c4d9cd"); - pchMessageStart[0] = 0x5A; pchMessageStart[1] = 0x1F; pchMessageStart[2] = 0x7E; @@ -388,9 +382,6 @@ class CRegTestParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; - // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00"); - pchMessageStart[0] = 0xaa; pchMessageStart[1] = 0x8e; pchMessageStart[2] = 0xf3; @@ -639,15 +630,9 @@ void *chainparams_commandline() (double)2777 // * estimated number of transactions per day after checkpoint // total number of tx / (checkpoint block height / (24 * 24)) }; - - pCurrentParams->consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000000001a8f4f23f8b2d1f7e"); } else { - if (strcmp(ASSETCHAINS_SYMBOL,"VRSCTEST") == 0 || strcmp(ASSETCHAINS_SYMBOL,"VERUSTEST") == 0) - { - pCurrentParams->consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000000000000001f7e"); - } pCurrentParams->consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = ASSETCHAINS_SAPLING; pCurrentParams->consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = ASSETCHAINS_OVERWINTER; checkpointData = //(Checkpoints::CCheckpointData) diff --git a/src/consensus/params.h b/src/consensus/params.h index ea55832e4c8..bb08c9b2199 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -141,8 +141,8 @@ struct Params { int64_t MaxActualTimespan() const { return (AveragingWindowTimespan() * (100 + nPowMaxAdjustDown)) / 100; } void SetSaplingHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = height; } void SetOverwinterHeight(int32_t height) { vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = height; } - uint256 nMinimumChainWork; // the minimum work allowed for this PoW chain }; + } // namespace Consensus #endif // BITCOIN_CONSENSUS_PARAMS_H diff --git a/src/main.cpp b/src/main.cpp index de26d1a6057..6c9f96a4ab3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2528,22 +2528,12 @@ bool IsInitialBlockDownload() return true; } - bool state; - arith_uint256 bigZero = arith_uint256(); - arith_uint256 minWork = UintToArith256(chainParams.GetConsensus().nMinimumChainWork); CBlockIndex *ptr = chainActive.Tip(); - if (ptr == NULL) { - //fprintf(stderr,"nullptr in IsInitialDownload\n"); - return true; - } - if (0 && ptr->chainPower < CChainPower(ptr, bigZero, minWork)) - { - fprintf(stderr,"chainpower insufficient in IsInitialDownload\n"); return true; } - state = ((chainActive.Height() < ptr->GetHeight() - 24*60) || + bool state = ((chainActive.Height() < ptr->GetHeight() - 24*60) || ptr->GetBlockTime() < (GetTime() - nMaxTipAge)); if ( KOMODO_INSYNC != 0 ) state = false; diff --git a/src/test-komodo/test_pow.cpp b/src/test-komodo/test_pow.cpp index 4403b68a736..438873bf124 100644 --- a/src/test-komodo/test_pow.cpp +++ b/src/test-komodo/test_pow.cpp @@ -123,7 +123,7 @@ TEST(PoW, MinDifficultyRules) { bnRes.GetCompact()); // diffuculty should never decrease below minimum - arith_uint256 minWork = UintToArith256(params.nMinimumChainWork); + arith_uint256 minWork = UintToArith256(params.powLimit); for (int i = 0; i <= lastBlk; i++) { blocks[i].nBits = minWork.GetCompact(); blocks[i].chainPower.chainWork = i ? blocks[i - 1].chainPower.chainWork From 6a331b8bc2b4332f62ad24a44dddb2fa4a556e95 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 28 Oct 2021 14:49:13 -0500 Subject: [PATCH 11/47] Remove unnecessary header --- src/test-komodo/test_alerts.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test-komodo/test_alerts.cpp b/src/test-komodo/test_alerts.cpp index d3bf42604fd..95e73d0e738 100644 --- a/src/test-komodo/test_alerts.cpp +++ b/src/test-komodo/test_alerts.cpp @@ -10,7 +10,6 @@ #include "chain.h" #include "chainparams.h" #include "clientversion.h" -#include "test/data/alertTests.raw.h" #include "main.h" #include "rpc/protocol.h" From 58aeb73aa403128860f2d8432dae1c4f71eba280 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 28 Oct 2021 15:16:54 -0500 Subject: [PATCH 12/47] add txid tests --- src/Makefile.gtest.include | 1 - src/Makefile.ktest.include | 3 ++- src/{gtest => test-komodo}/test_txid.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/{gtest => test-komodo}/test_txid.cpp (94%) diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index cddf62d4ae9..b5fe04fd3a3 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -39,7 +39,6 @@ zcash_gtest_SOURCES += \ gtest/test_upgrades.cpp \ gtest/test_validation.cpp \ gtest/test_circuit.cpp \ - gtest/test_txid.cpp \ gtest/test_libzcash_utils.cpp \ gtest/test_proofs.cpp \ gtest/test_paymentdisclosure.cpp \ diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index c7e8891e307..1eb8726b8cc 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -22,7 +22,8 @@ komodo_test_SOURCES = \ test-komodo/test_random.cpp \ test-komodo/test_block.cpp \ test-komodo/test_mempool.cpp \ - test-komodo/test_pow.cpp + test-komodo/test_pow.cpp \ + test-komodo/test_txid.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/gtest/test_txid.cpp b/src/test-komodo/test_txid.cpp similarity index 94% rename from src/gtest/test_txid.cpp rename to src/test-komodo/test_txid.cpp index 9b4a21068d1..f3500b08c32 100644 --- a/src/gtest/test_txid.cpp +++ b/src/test-komodo/test_txid.cpp @@ -8,7 +8,7 @@ #include "utilstrencodings.h" /* - Test that removing #1144 succeeded by verifying the hash of a transaction is over the entire serialized form. + Verify the hash of a transaction is over the entire serialized form. */ TEST(txid_tests, check_txid_and_hash_are_same) { // Random zcash transaction aacaa62d40fcdd9192ed35ea9df31660ccf7f6c60566530faaa444fb5d0d410e From abe48f62a82194ab502f917e743bd88bb9bf6a22 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 28 Oct 2021 15:49:43 -0500 Subject: [PATCH 13/47] Add coin_tests --- src/Makefile.ktest.include | 3 +- src/Makefile.test.include | 1 - .../test_coins.cpp} | 238 +++++++++--------- 3 files changed, 115 insertions(+), 127 deletions(-) rename src/{test/coins_tests.cpp => test-komodo/test_coins.cpp} (79%) diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 1eb8726b8cc..72b3296ec37 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -23,7 +23,8 @@ komodo_test_SOURCES = \ test-komodo/test_block.cpp \ test-komodo/test_mempool.cpp \ test-komodo/test_pow.cpp \ - test-komodo/test_txid.cpp + test-komodo/test_txid.cpp \ + test-komodo/test_coins.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 2f0346b57a4..74aee61225c 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -62,7 +62,6 @@ BITCOIN_TESTS =\ test/bloom_tests.cpp \ test/checkblock_tests.cpp \ test/Checkpoints_tests.cpp \ - test/coins_tests.cpp \ test/compress_tests.cpp \ test/convertbits_tests.cpp \ test/crypto_tests.cpp \ diff --git a/src/test/coins_tests.cpp b/src/test-komodo/test_coins.cpp similarity index 79% rename from src/test/coins_tests.cpp rename to src/test-komodo/test_coins.cpp index dc795ad7a7b..e554c56358e 100644 --- a/src/test/coins_tests.cpp +++ b/src/test-komodo/test_coins.cpp @@ -17,11 +17,12 @@ #include #include -#include +#include #include "zcash/IncrementalMerkleTree.hpp" -namespace +namespace TestCoins { + class CCoinsViewTest : public CCoinsView { uint256 hashBestBlock_; @@ -208,7 +209,7 @@ class CCoinsViewCacheTest : public CCoinsViewCache for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) { ret += it->second.coins.DynamicMemoryUsage(); } - BOOST_CHECK_EQUAL(DynamicMemoryUsage(), ret); + EXPECT_EQ(DynamicMemoryUsage(), ret); } }; @@ -238,7 +239,6 @@ class TxWithNullifiers } }; -} uint256 appendRandomSproutCommitment(SproutMerkleTree &tree) { @@ -256,20 +256,20 @@ template bool GetAnchorAt(const CCoinsViewCacheTest &cache, const template<> bool GetAnchorAt(const CCoinsViewCacheTest &cache, const uint256 &rt, SproutMerkleTree &tree) { return cache.GetSproutAnchorAt(rt, tree); } template<> bool GetAnchorAt(const CCoinsViewCacheTest &cache, const uint256 &rt, SaplingMerkleTree &tree) { return cache.GetSaplingAnchorAt(rt, tree); } -BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup) -void checkNullifierCache(const CCoinsViewCacheTest &cache, const TxWithNullifiers &txWithNullifiers, bool shouldBeInCache) { +void checkNullifierCache(const CCoinsViewCacheTest &cache, const TxWithNullifiers &txWithNullifiers, bool shouldBeInCache) +{ // Make sure the nullifiers have not gotten mixed up - BOOST_CHECK(!cache.GetNullifier(txWithNullifiers.sproutNullifier, SAPLING)); - BOOST_CHECK(!cache.GetNullifier(txWithNullifiers.saplingNullifier, SPROUT)); + EXPECT_TRUE(!cache.GetNullifier(txWithNullifiers.sproutNullifier, SAPLING)); + EXPECT_TRUE(!cache.GetNullifier(txWithNullifiers.saplingNullifier, SPROUT)); // Check if the nullifiers either are or are not in the cache bool containsSproutNullifier = cache.GetNullifier(txWithNullifiers.sproutNullifier, SPROUT); bool containsSaplingNullifier = cache.GetNullifier(txWithNullifiers.saplingNullifier, SAPLING); - BOOST_CHECK(containsSproutNullifier == shouldBeInCache); - BOOST_CHECK(containsSaplingNullifier == shouldBeInCache); + EXPECT_TRUE(containsSproutNullifier == shouldBeInCache); + EXPECT_TRUE(containsSaplingNullifier == shouldBeInCache); } -BOOST_AUTO_TEST_CASE(nullifier_regression_test) +TEST(TestCoins, nullifier_regression_test) { // Correct behavior: { @@ -357,7 +357,8 @@ BOOST_AUTO_TEST_CASE(nullifier_regression_test) } } -template void anchorPopRegressionTestImpl(ShieldedType type) +template +void anchorPopRegressionTestImpl(ShieldedType type) { // Correct behavior: { @@ -383,8 +384,8 @@ template void anchorPopRegressionTestImpl(ShieldedType type) // The base contains the anchor, of course! { Tree checkTree; - BOOST_CHECK(GetAnchorAt(cache1, tree.root(), checkTree)); - BOOST_CHECK(checkTree.root() == tree.root()); + EXPECT_TRUE(GetAnchorAt(cache1, tree.root(), checkTree)); + EXPECT_TRUE(checkTree.root() == tree.root()); } } @@ -415,8 +416,8 @@ template void anchorPopRegressionTestImpl(ShieldedType type) // treestate... { Tree checktree; - BOOST_CHECK(GetAnchorAt(cache1, tree.root(), checktree)); - BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks. + EXPECT_TRUE(GetAnchorAt(cache1, tree.root(), checktree)); + EXPECT_TRUE(checktree.root() == tree.root()); // Oh, shucks. } // Flushing cache won't help either, just makes the inconsistency @@ -424,23 +425,20 @@ template void anchorPopRegressionTestImpl(ShieldedType type) cache1.Flush(); { Tree checktree; - BOOST_CHECK(GetAnchorAt(cache1, tree.root(), checktree)); - BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks. + EXPECT_TRUE(GetAnchorAt(cache1, tree.root(), checktree)); + EXPECT_TRUE(checktree.root() == tree.root()); // Oh, shucks. } } } -BOOST_AUTO_TEST_CASE(anchor_pop_regression_test) +TEST(TestCoins, anchor_pop_regression_test) { - BOOST_TEST_CONTEXT("Sprout") { - anchorPopRegressionTestImpl(SPROUT); - } - BOOST_TEST_CONTEXT("Sapling") { - anchorPopRegressionTestImpl(SAPLING); - } + anchorPopRegressionTestImpl(SPROUT); + anchorPopRegressionTestImpl(SAPLING); } -template void anchorRegressionTestImpl(ShieldedType type) +template +void anchorRegressionTestImpl(ShieldedType type) { // Correct behavior: { @@ -455,8 +453,8 @@ template void anchorRegressionTestImpl(ShieldedType type) cache1.Flush(); cache1.PopAnchor(Tree::empty_root(), type); - BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root()); - BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree)); + EXPECT_TRUE(cache1.GetBestAnchor(type) == Tree::empty_root()); + EXPECT_TRUE(!GetAnchorAt(cache1, tree.root(), tree)); } // Also correct behavior: @@ -472,8 +470,8 @@ template void anchorRegressionTestImpl(ShieldedType type) cache1.PopAnchor(Tree::empty_root(), type); cache1.Flush(); - BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root()); - BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree)); + EXPECT_TRUE(cache1.GetBestAnchor(type) == Tree::empty_root()); + EXPECT_TRUE(!GetAnchorAt(cache1, tree.root(), tree)); } // Works because we bring the anchor in from parent cache. @@ -490,13 +488,13 @@ template void anchorRegressionTestImpl(ShieldedType type) { // Pop anchor. CCoinsViewCacheTest cache2(&cache1); - BOOST_CHECK(GetAnchorAt(cache2, tree.root(), tree)); + EXPECT_TRUE(GetAnchorAt(cache2, tree.root(), tree)); cache2.PopAnchor(Tree::empty_root(), type); cache2.Flush(); } - BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root()); - BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree)); + EXPECT_TRUE(cache1.GetBestAnchor(type) == Tree::empty_root()); + EXPECT_TRUE(!GetAnchorAt(cache1, tree.root(), tree)); } // Was broken: @@ -517,22 +515,18 @@ template void anchorRegressionTestImpl(ShieldedType type) cache2.Flush(); } - BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root()); - BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree)); + EXPECT_TRUE(cache1.GetBestAnchor(type) == Tree::empty_root()); + EXPECT_TRUE(!GetAnchorAt(cache1, tree.root(), tree)); } } -BOOST_AUTO_TEST_CASE(anchor_regression_test) +TEST(TestCoins, anchor_regression_test) { - BOOST_TEST_CONTEXT("Sprout") { - anchorRegressionTestImpl(SPROUT); - } - BOOST_TEST_CONTEXT("Sapling") { - anchorRegressionTestImpl(SAPLING); - } + anchorRegressionTestImpl(SPROUT); + anchorRegressionTestImpl(SAPLING); } -BOOST_AUTO_TEST_CASE(nullifiers_test) +TEST(TestCoins, nullifiers_test) { CCoinsViewTest base; CCoinsViewCacheTest cache(&base); @@ -555,14 +549,15 @@ BOOST_AUTO_TEST_CASE(nullifiers_test) checkNullifierCache(cache3, txWithNullifiers, false); } -template void anchorsFlushImpl(ShieldedType type) +template +void anchorsFlushImpl(ShieldedType type) { CCoinsViewTest base; uint256 newrt; { CCoinsViewCacheTest cache(&base); Tree tree; - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); tree.append(GetRandHash()); newrt = tree.root(); @@ -574,28 +569,24 @@ template void anchorsFlushImpl(ShieldedType type) { CCoinsViewCacheTest cache(&base); Tree tree; - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); // Get the cached entry. - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); uint256 check_rt = tree.root(); - BOOST_CHECK(check_rt == newrt); + EXPECT_TRUE(check_rt == newrt); } } -BOOST_AUTO_TEST_CASE(anchors_flush_test) +TEST(TestCoins, anchors_flush_test) { - BOOST_TEST_CONTEXT("Sprout") { - anchorsFlushImpl(SPROUT); - } - BOOST_TEST_CONTEXT("Sapling") { - anchorsFlushImpl(SAPLING); - } + anchorsFlushImpl(SPROUT); + anchorsFlushImpl(SAPLING); } -BOOST_AUTO_TEST_CASE(chained_joinsplits) +TEST(TestCoins, chained_joinsplits) { // TODO update this or add a similar test when the SaplingNote class exist CCoinsViewTest base; @@ -632,7 +623,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) CMutableTransaction mtx; mtx.vjoinsplit.push_back(js2); - BOOST_CHECK(!cache.HaveJoinSplitRequirements(mtx)); + EXPECT_TRUE(!cache.HaveJoinSplitRequirements(mtx)); } { @@ -642,7 +633,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js2); mtx.vjoinsplit.push_back(js1); - BOOST_CHECK(!cache.HaveJoinSplitRequirements(mtx)); + EXPECT_TRUE(!cache.HaveJoinSplitRequirements(mtx)); } { @@ -650,7 +641,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js1); mtx.vjoinsplit.push_back(js2); - BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx)); + EXPECT_TRUE(cache.HaveJoinSplitRequirements(mtx)); } { @@ -659,7 +650,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js2); mtx.vjoinsplit.push_back(js3); - BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx)); + EXPECT_TRUE(cache.HaveJoinSplitRequirements(mtx)); } { @@ -669,11 +660,12 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits) mtx.vjoinsplit.push_back(js2); mtx.vjoinsplit.push_back(js3); - BOOST_CHECK(cache.HaveJoinSplitRequirements(mtx)); + EXPECT_TRUE(cache.HaveJoinSplitRequirements(mtx)); } } -template void anchorsTestImpl(ShieldedType type) +template +void anchorsTestImpl(ShieldedType type) { // TODO: These tests should be more methodical. // Or, integrate with Bitcoin's tests later. @@ -681,13 +673,13 @@ template void anchorsTestImpl(ShieldedType type) CCoinsViewTest base; CCoinsViewCacheTest cache(&base); - BOOST_CHECK(cache.GetBestAnchor(type) == Tree::empty_root()); + EXPECT_TRUE(cache.GetBestAnchor(type) == Tree::empty_root()); { Tree tree; - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); - BOOST_CHECK(cache.GetBestAnchor(type) == tree.root()); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), tree)); + EXPECT_TRUE(cache.GetBestAnchor(type) == tree.root()); tree.append(GetRandHash()); tree.append(GetRandHash()); tree.append(GetRandHash()); @@ -703,13 +695,13 @@ template void anchorsTestImpl(ShieldedType type) uint256 newrt2; cache.PushAnchor(tree); - BOOST_CHECK(cache.GetBestAnchor(type) == newrt); + EXPECT_TRUE(cache.GetBestAnchor(type) == newrt); { Tree confirm_same; - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), confirm_same)); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), confirm_same)); - BOOST_CHECK(confirm_same.root() == newrt); + EXPECT_TRUE(confirm_same.root() == newrt); } tree.append(GetRandHash()); @@ -718,18 +710,18 @@ template void anchorsTestImpl(ShieldedType type) newrt2 = tree.root(); cache.PushAnchor(tree); - BOOST_CHECK(cache.GetBestAnchor(type) == newrt2); + EXPECT_TRUE(cache.GetBestAnchor(type) == newrt2); Tree test_tree; - BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), test_tree)); + EXPECT_TRUE(GetAnchorAt(cache, cache.GetBestAnchor(type), test_tree)); - BOOST_CHECK(tree.root() == test_tree.root()); + EXPECT_TRUE(tree.root() == test_tree.root()); { Tree test_tree2; GetAnchorAt(cache, newrt, test_tree2); - BOOST_CHECK(test_tree2.root() == newrt); + EXPECT_TRUE(test_tree2.root() == newrt); } { @@ -743,14 +735,10 @@ template void anchorsTestImpl(ShieldedType type) } } -BOOST_AUTO_TEST_CASE(anchors_test) +TEST(TestCoins, anchors_test) { - BOOST_TEST_CONTEXT("Sprout") { - anchorsTestImpl(SPROUT); - } - BOOST_TEST_CONTEXT("Sapling") { - anchorsTestImpl(SAPLING); - } + anchorsTestImpl(SPROUT); + anchorsTestImpl(SAPLING); } static const unsigned int NUM_SIMULATION_ITERATIONS = 40000; @@ -764,7 +752,7 @@ static const unsigned int NUM_SIMULATION_ITERATIONS = 40000; // // During the process, booleans are kept to make sure that the randomized // operation hits all branches. -BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) +TEST(TestCoins, coins_cache_simulation_test) { // Various coverage trackers. bool removed_all_caches = false; @@ -796,7 +784,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration. CCoins& coins = result[txid]; CCoinsModifier entry = stack.back()->ModifyCoins(txid); - BOOST_CHECK(coins == *entry); + EXPECT_TRUE(coins == *entry); if (insecure_rand() % 5 == 0 || coins.IsPruned()) { if (coins.IsPruned()) { added_an_entry = true; @@ -819,10 +807,10 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) for (std::map::iterator it = result.begin(); it != result.end(); it++) { const CCoins* coins = stack.back()->AccessCoins(it->first); if (coins) { - BOOST_CHECK(*coins == it->second); + EXPECT_TRUE(*coins == it->second); found_an_entry = true; } else { - BOOST_CHECK(it->second.IsPruned()); + EXPECT_TRUE(it->second.IsPruned()); missed_an_entry = true; } } @@ -860,16 +848,16 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } // Verify coverage. - BOOST_CHECK(removed_all_caches); - BOOST_CHECK(reached_4_caches); - BOOST_CHECK(added_an_entry); - BOOST_CHECK(removed_an_entry); - BOOST_CHECK(updated_an_entry); - BOOST_CHECK(found_an_entry); - BOOST_CHECK(missed_an_entry); + EXPECT_TRUE(removed_all_caches); + EXPECT_TRUE(reached_4_caches); + EXPECT_TRUE(added_an_entry); + EXPECT_TRUE(removed_an_entry); + EXPECT_TRUE(updated_an_entry); + EXPECT_TRUE(found_an_entry); + EXPECT_TRUE(missed_an_entry); } -BOOST_AUTO_TEST_CASE(coins_coinbase_spends) +TEST(TestCoins, coins_coinbase_spends) { CCoinsViewTest base; CCoinsViewCacheTest cache(&base); @@ -885,7 +873,7 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends) CTransaction tx(mtx); - BOOST_CHECK(tx.IsCoinBase()); + EXPECT_TRUE(tx.IsCoinBase()); CValidationState state; UpdateCoins(tx, cache, 100); @@ -899,7 +887,7 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends) { CTransaction tx2(mtx2); - BOOST_CHECK(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); + EXPECT_TRUE(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); } mtx2.vout.resize(1); @@ -908,63 +896,63 @@ BOOST_AUTO_TEST_CASE(coins_coinbase_spends) { CTransaction tx2(mtx2); - BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); - BOOST_CHECK(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs"); + EXPECT_TRUE(!Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); + EXPECT_TRUE(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs"); } } -BOOST_AUTO_TEST_CASE(ccoins_serialization) +TEST(TestCoins, ccoins_serialization) { // Good example CDataStream ss1(ParseHex("0104835800816115944e077fe7c803cfa57f29b36bf87c1d358bb85e"), SER_DISK, CLIENT_VERSION); CCoins cc1; ss1 >> cc1; - BOOST_CHECK_EQUAL(cc1.nVersion, 1); - BOOST_CHECK_EQUAL(cc1.fCoinBase, false); - BOOST_CHECK_EQUAL(cc1.nHeight, 203998); - BOOST_CHECK_EQUAL(cc1.vout.size(), 2); - BOOST_CHECK_EQUAL(cc1.IsAvailable(0), false); - BOOST_CHECK_EQUAL(cc1.IsAvailable(1), true); - BOOST_CHECK_EQUAL(cc1.vout[1].nValue, 60000000000ULL); - BOOST_CHECK_EQUAL(HexStr(cc1.vout[1].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35")))))); + EXPECT_EQ(cc1.nVersion, 1); + EXPECT_EQ(cc1.fCoinBase, false); + EXPECT_EQ(cc1.nHeight, 203998); + EXPECT_EQ(cc1.vout.size(), 2); + EXPECT_EQ(cc1.IsAvailable(0), false); + EXPECT_EQ(cc1.IsAvailable(1), true); + EXPECT_EQ(cc1.vout[1].nValue, 60000000000ULL); + EXPECT_EQ(HexStr(cc1.vout[1].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35")))))); // Good example CDataStream ss2(ParseHex("0109044086ef97d5790061b01caab50f1b8e9c50a5057eb43c2d9563a4eebbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa486af3b"), SER_DISK, CLIENT_VERSION); CCoins cc2; ss2 >> cc2; - BOOST_CHECK_EQUAL(cc2.nVersion, 1); - BOOST_CHECK_EQUAL(cc2.fCoinBase, true); - BOOST_CHECK_EQUAL(cc2.nHeight, 120891); - BOOST_CHECK_EQUAL(cc2.vout.size(), 17); + EXPECT_EQ(cc2.nVersion, 1); + EXPECT_EQ(cc2.fCoinBase, true); + EXPECT_EQ(cc2.nHeight, 120891); + EXPECT_EQ(cc2.vout.size(), 17); for (int i = 0; i < 17; i++) { - BOOST_CHECK_EQUAL(cc2.IsAvailable(i), i == 4 || i == 16); + EXPECT_EQ(cc2.IsAvailable(i), i == 4 || i == 16); } - BOOST_CHECK_EQUAL(cc2.vout[4].nValue, 234925952); - BOOST_CHECK_EQUAL(HexStr(cc2.vout[4].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("61b01caab50f1b8e9c50a5057eb43c2d9563a4ee")))))); - BOOST_CHECK_EQUAL(cc2.vout[16].nValue, 110397); - BOOST_CHECK_EQUAL(HexStr(cc2.vout[16].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4")))))); + EXPECT_EQ(cc2.vout[4].nValue, 234925952); + EXPECT_EQ(HexStr(cc2.vout[4].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("61b01caab50f1b8e9c50a5057eb43c2d9563a4ee")))))); + EXPECT_EQ(cc2.vout[16].nValue, 110397); + EXPECT_EQ(HexStr(cc2.vout[16].scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4")))))); // Smallest possible example CDataStream ssx(SER_DISK, CLIENT_VERSION); - BOOST_CHECK_EQUAL(HexStr(ssx.begin(), ssx.end()), ""); + EXPECT_EQ(HexStr(ssx.begin(), ssx.end()), ""); CDataStream ss3(ParseHex("0002000600"), SER_DISK, CLIENT_VERSION); CCoins cc3; ss3 >> cc3; - BOOST_CHECK_EQUAL(cc3.nVersion, 0); - BOOST_CHECK_EQUAL(cc3.fCoinBase, false); - BOOST_CHECK_EQUAL(cc3.nHeight, 0); - BOOST_CHECK_EQUAL(cc3.vout.size(), 1); - BOOST_CHECK_EQUAL(cc3.IsAvailable(0), true); - BOOST_CHECK_EQUAL(cc3.vout[0].nValue, 0); - BOOST_CHECK_EQUAL(cc3.vout[0].scriptPubKey.size(), 0); + EXPECT_EQ(cc3.nVersion, 0); + EXPECT_EQ(cc3.fCoinBase, false); + EXPECT_EQ(cc3.nHeight, 0); + EXPECT_EQ(cc3.vout.size(), 1); + EXPECT_EQ(cc3.IsAvailable(0), true); + EXPECT_EQ(cc3.vout[0].nValue, 0); + EXPECT_EQ(cc3.vout[0].scriptPubKey.size(), 0); // scriptPubKey that ends beyond the end of the stream CDataStream ss4(ParseHex("0002000800"), SER_DISK, CLIENT_VERSION); try { CCoins cc4; ss4 >> cc4; - BOOST_CHECK_MESSAGE(false, "We should have thrown"); + FAIL() << "We should have thrown"; } catch (const std::ios_base::failure& e) { } @@ -972,14 +960,14 @@ BOOST_AUTO_TEST_CASE(ccoins_serialization) CDataStream tmp(SER_DISK, CLIENT_VERSION); uint64_t x = 3000000000ULL; tmp << VARINT(x); - BOOST_CHECK_EQUAL(HexStr(tmp.begin(), tmp.end()), "8a95c0bb00"); + EXPECT_EQ(HexStr(tmp.begin(), tmp.end()), "8a95c0bb00"); CDataStream ss5(ParseHex("0002008a95c0bb0000"), SER_DISK, CLIENT_VERSION); try { CCoins cc5; ss5 >> cc5; - BOOST_CHECK_MESSAGE(false, "We should have thrown"); + FAIL() << "We should have thrown"; } catch (const std::ios_base::failure& e) { } } -BOOST_AUTO_TEST_SUITE_END() +} // namespace TestCoins From e8d9f8059b91bc17b49a85bd73db085260c43303 Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 3 Nov 2021 10:01:05 -0500 Subject: [PATCH 14/47] Begin tests of ConnectBlock --- src/test-komodo/test_pow.cpp | 19 ++++++++++++++++++- src/test-komodo/testutils.cpp | 18 ++++++++++++++++++ src/test-komodo/testutils.h | 11 +++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/test-komodo/test_pow.cpp b/src/test-komodo/test_pow.cpp index 438873bf124..d3ec61c39cb 100644 --- a/src/test-komodo/test_pow.cpp +++ b/src/test-komodo/test_pow.cpp @@ -1,9 +1,12 @@ -#include #include "chain.h" #include "chainparams.h" #include "pow.h" #include "random.h" +#include "testutils.h" +#include "komodo_extern_globals.h" +#include "consensus/validation.h" +#include TEST(PoW, DifficultyAveraging) { SelectParams(CBaseChainParams::MAIN); @@ -146,3 +149,17 @@ TEST(PoW, MinDifficultyRules) { bnRes.GetCompact()); } + +TEST(PoW, TestStopAt) +{ + TestChain chain; + auto notary = chain.AddWallet(chain.getNotaryKey()); + CBlock lastBlock = chain.generateBlock(); // genesis block + ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); + lastBlock = chain.generateBlock(); // now we should be above 1 + ASSERT_GT( chain.GetIndex()->GetHeight(), 1); + CBlock block; + CValidationState state; + KOMODO_STOPAT = 1; + EXPECT_FALSE( ConnectBlock(block, state, chain.GetIndex(), *chain.GetCoinsViewCache(), false, true) ); +} \ No newline at end of file diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index 242460d6e78..31ba4d2d7b1 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -179,6 +179,24 @@ TestChain::~TestChain() boost::filesystem::remove_all(dataDir); } +/*** + * Get the block index at the specified height + * @param height the height (0 indicates current height) + * @returns the block index + */ +CBlockIndex *TestChain::GetIndex(uint32_t height) +{ + if (height == 0) + return chainActive.LastTip(); + return chainActive[height]; + +} + +CCoinsViewCache *TestChain::GetCoinsViewCache() +{ + return pcoinsTip; +} + CBlock TestChain::generateBlock() { CBlock block; diff --git a/src/test-komodo/testutils.h b/src/test-komodo/testutils.h index 5a3442693ed..279df4c0ac2 100644 --- a/src/test-komodo/testutils.h +++ b/src/test-komodo/testutils.h @@ -47,6 +47,17 @@ class TestChain * dtor to release resources */ ~TestChain(); + /*** + * Get the block index at the specified height + * @param height the height (0 indicates current height + * @returns the block index + */ + CBlockIndex *GetIndex(uint32_t height = 0); + /*** + * Get this chains view of the state of the chain + * @returns the view + */ + CCoinsViewCache *GetCoinsViewCache(); /** * Generate a block * @returns the block generated From 432c57f3c392932913cfdafdd3325c0eed51706e Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 3 Nov 2021 10:27:00 -0500 Subject: [PATCH 15/47] fix for running all tests --- src/test-komodo/test_coins.cpp | 2 +- src/test-komodo/test_pow.cpp | 2 +- src/test-komodo/testutils.cpp | 8 ++++++++ src/test-komodo/testutils.h | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/test-komodo/test_coins.cpp b/src/test-komodo/test_coins.cpp index e554c56358e..5ec26b2d31e 100644 --- a/src/test-komodo/test_coins.cpp +++ b/src/test-komodo/test_coins.cpp @@ -896,7 +896,7 @@ TEST(TestCoins, coins_coinbase_spends) { CTransaction tx2(mtx2); - EXPECT_TRUE(!Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); + EXPECT_FALSE(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); EXPECT_TRUE(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs"); } } diff --git a/src/test-komodo/test_pow.cpp b/src/test-komodo/test_pow.cpp index d3ec61c39cb..ae5f015f1a1 100644 --- a/src/test-komodo/test_pow.cpp +++ b/src/test-komodo/test_pow.cpp @@ -162,4 +162,4 @@ TEST(PoW, TestStopAt) CValidationState state; KOMODO_STOPAT = 1; EXPECT_FALSE( ConnectBlock(block, state, chain.GetIndex(), *chain.GetCoinsViewCache(), false, true) ); -} \ No newline at end of file +} diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index 31ba4d2d7b1..0afdbc9324b 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -162,6 +162,7 @@ CTransaction getInputTx(CScript scriptPubKey) TestChain::TestChain() { + previousNetwork = Params().NetworkIDString(); dataDir = GetTempPath() / strprintf("test_komodo_%li_%i", GetTime(), GetRand(100000)); if (ASSETCHAINS_SYMBOL[0]) dataDir = dataDir / strprintf("_%s", ASSETCHAINS_SYMBOL); @@ -177,6 +178,13 @@ TestChain::TestChain() TestChain::~TestChain() { boost::filesystem::remove_all(dataDir); + if (previousNetwork == "main") + SelectParams(CBaseChainParams::MAIN); + if (previousNetwork == "regtest") + SelectParams(CBaseChainParams::REGTEST); + if (previousNetwork == "test") + SelectParams(CBaseChainParams::TESTNET); + } /*** diff --git a/src/test-komodo/testutils.h b/src/test-komodo/testutils.h index 279df4c0ac2..a976c403073 100644 --- a/src/test-komodo/testutils.h +++ b/src/test-komodo/testutils.h @@ -87,6 +87,7 @@ class TestChain private: std::vector> toBeNotified; boost::filesystem::path dataDir; + std::string previousNetwork; }; /*** From e46aae1bef0a0745ca7ffc7a9458bc04a0447de7 Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 3 Nov 2021 10:56:54 -0500 Subject: [PATCH 16/47] make static adjustable for unit testing --- src/komodo.cpp | 9 ++++++++- src/main.cpp | 37 ++++++++++------------------------- src/main.h | 11 ++++++++++- src/test-komodo/test_pow.cpp | 13 ++++++++++++ src/test-komodo/testutils.cpp | 3 +++ 5 files changed, 44 insertions(+), 29 deletions(-) diff --git a/src/komodo.cpp b/src/komodo.cpp index fb9b2e864de..35c2b668786 100644 --- a/src/komodo.cpp +++ b/src/komodo.cpp @@ -600,9 +600,16 @@ int32_t komodo_notarycmp(uint8_t *scriptPubKey,int32_t scriptlen,uint8_t pubkeys /* read blackjok3rtt comments in main.cpp */ +/* + JMJ: Moved hwmheight out of komodo_connectblock to allow testing. + Adjusting this should only be done by komodo_connectblock or a unit test +*/ +static int32_t hwmheight; + +void adjust_hwmheight(int32_t newHeight) { hwmheight = newHeight; } + int32_t komodo_connectblock(bool fJustCheck, CBlockIndex *pindex,CBlock& block) { - static int32_t hwmheight; int32_t staked_era; static int32_t lastStakedEra; std::vector notarisations; uint64_t signedmask,voutmask; char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; diff --git a/src/main.cpp b/src/main.cpp index 6c9f96a4ab3..d20612700e9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3416,6 +3416,16 @@ static int64_t nTimeTotal = 0; bool FindBlockPos(int32_t tmpflag,CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false); bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos); +/***** + * @brief Apply the effects of this block (with given index) on the UTXO set represented by coins + * @param block the block to add + * @param state the result status + * @param pindex where to insert the block + * @param view the chain + * @param fJustCheck do not actually modify, only do checks + * @param fcheckPOW + * @returns true on success + */ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck,bool fCheckPOW) { CDiskBlockPos blockPos; @@ -3424,7 +3434,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return(true); if ( KOMODO_STOPAT != 0 && pindex->GetHeight() > KOMODO_STOPAT ) return(false); - //fprintf(stderr,"connectblock ht.%d\n",(int32_t)pindex->GetHeight()); AssertLockHeld(cs_main); bool fExpensiveChecks = true; if (fCheckpointsEnabled) { @@ -3442,7 +3451,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Check it again to verify JoinSplit proofs, and in case a previous version let a bad block in if ( !CheckBlock(&futureblock,pindex->GetHeight(),pindex,block, state, fExpensiveChecks ? verifier : disabledVerifier, fCheckPOW, !fJustCheck) || futureblock != 0 ) { - //fprintf(stderr,"checkblock failure in connectblock futureblock.%d\n",futureblock); return false; } if ( fCheckPOW != 0 && (pindex->nStatus & BLOCK_VALID_CONTEXT) != BLOCK_VALID_CONTEXT ) // Activate Jan 15th, 2019 @@ -3477,7 +3485,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin REJECT_INVALID, "bad-cb-amount"); // calculate the notaries compensation and validate the amounts and pubkeys are correct. notarypaycheque = komodo_checknotarypay((CBlock *)&block,(int32_t)pindex->GetHeight()); - //fprintf(stderr, "notarypaycheque.%lu\n", notarypaycheque); if ( notarypaycheque > 0 ) blockReward += notarypaycheque; else @@ -3499,7 +3506,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) return error("AcceptBlock(): ReceivedBlockTransactions failed"); setDirtyFileInfo.insert(blockPos.nFile); - //fprintf(stderr,"added ht.%d copy of tmpfile to %d.%d\n",pindex->GetHeight(),blockPos.nFile,blockPos.nPos); } // verify that the view's current state corresponds to the previous block uint256 hashPrevBlock = pindex->pprev == NULL ? uint256() : pindex->pprev->GetBlockHash(); @@ -3526,8 +3532,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } bool fScriptChecks = (!fCheckpointsEnabled || pindex->GetHeight() >= Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints())); - //if ( KOMODO_TESTNET_EXPIRATION != 0 && pindex->GetHeight() > KOMODO_TESTNET_EXPIRATION ) // "testnet" - // return(false); // Do not allow blocks that contain transactions which 'overwrite' older transactions, // unless those are already completely spent. BOOST_FOREACH(const CTransaction& tx, block.vtx) { @@ -3603,7 +3607,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (nSigOps > MAX_BLOCK_SIGOPS) return state.DoS(100, error("ConnectBlock(): too many sigops"), REJECT_INVALID, "bad-blk-sigops"); - //fprintf(stderr,"ht.%d vout0 t%u\n",pindex->GetHeight(),tx.nLockTime); if (!tx.IsMint()) { if (!view.HaveInputs(tx)) @@ -3667,21 +3670,10 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin fprintf(stderr,"valueout %.8f too big\n",(double)valueout/COIN); return state.DoS(100, error("ConnectBlock(): GetValueOut too big"),REJECT_INVALID,"tx valueout is too big"); } - //prevsum = voutsum; - //voutsum += valueout; - /*if ( KOMODO_VALUETOOBIG(voutsum) != 0 ) - { - fprintf(stderr,"voutsum %.8f too big\n",(double)voutsum/COIN); - return state.DoS(100, error("ConnectBlock(): voutsum too big"),REJECT_INVALID,"tx valueout is too big"); - } - else - if ( voutsum < prevsum ) // PRLPAY overflows this and it isnt a conclusive test anyway - return state.DoS(100, error("ConnectBlock(): voutsum less after adding valueout"),REJECT_INVALID,"tx valueout is too big");*/ if (!tx.IsCoinBase()) { nFees += (stakeTxValue= view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime) - valueout); sum += interest; - //fprintf(stderr, "tx.%s nFees.%li interest.%li\n", tx.GetHash().ToString().c_str(), stakeTxValue, interest); std::vector vChecks; if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, nScriptCheckThreads ? &vChecks : NULL)) @@ -3714,8 +3706,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } } - //if ( ASSETCHAINS_SYMBOL[0] == 0 ) - // komodo_earned_interest(pindex->GetHeight(),sum); CTxUndo undoDummy; if (i > 0) { blockundo.vtxundo.push_back(CTxUndo()); @@ -3725,7 +3715,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { BOOST_FOREACH(const uint256 ¬e_commitment, joinsplit.commitments) { // Insert the note commitments into our temporary tree. - sprout_tree.append(note_commitment); } } @@ -3739,7 +3728,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } // This is moved from CheckBlock for staking chains, so we can enforce the staking tx value was indeed paid to the coinbase. - //fprintf(stderr, "blockReward.%li stakeTxValue.%li sum.%li\n",blockReward,stakeTxValue,sum); if ( ASSETCHAINS_STAKED != 0 && fCheckPOW && komodo_checkPOW(blockReward+stakeTxValue-notarypaycheque,1,(CBlock *)&block,pindex->GetHeight()) < 0 ) return state.DoS(100, error("ConnectBlock: ac_staked chain failed slow komodo_checkPOW"),REJECT_INVALID, "failed-slow_checkPOW"); @@ -3786,8 +3774,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin { if ( ASSETCHAINS_SYMBOL[0] != 0 || pindex->GetHeight() >= KOMODO_NOTARIES_HEIGHT1 || block.vtx[0].vout[0].nValue > blockReward ) { - //fprintf(stderr, "coinbase pays too much\n"); - //sleepflag = true; return state.DoS(100, error("ConnectBlock(): coinbase pays too much (actual=%d vs limit=%d)", block.vtx[0].GetValueOut(), blockReward), @@ -3804,7 +3790,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin return true; // Write undo information to disk - //fprintf(stderr,"nFile.%d isNull %d vs isvalid %d nStatus %x\n",(int32_t)pindex->nFile,pindex->GetUndoPos().IsNull(),pindex->IsValid(BLOCK_VALID_SCRIPTS),(uint32_t)pindex->nStatus); if (pindex->GetUndoPos().IsNull() || !pindex->IsValid(BLOCK_VALID_SCRIPTS)) { if (pindex->GetUndoPos().IsNull()) @@ -3891,13 +3876,11 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin int64_t nTime4 = GetTimeMicros(); nTimeCallbacks += nTime4 - nTime3; LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeCallbacks * 0.000001); - //FlushStateToDisk(); komodo_connectblock(false,pindex,*(CBlock *)&block); // dPoW state update. if ( ASSETCHAINS_NOTARY_PAY[0] != 0 ) { // Update the notary pay with the latest payment. pindex->nNotaryPay = pindex->pprev->nNotaryPay + notarypaycheque; - //fprintf(stderr, "total notary pay.%li\n", pindex->nNotaryPay); } return true; } diff --git a/src/main.h b/src/main.h index 9ba9303a65d..696922b4b39 100644 --- a/src/main.h +++ b/src/main.h @@ -820,7 +820,16 @@ bool PruneOneBlockFile(bool tempfile, const int fileNumber); * of problems. Note that in any case, coins may be modified. */ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL); -/** Apply the effects of this block (with given index) on the UTXO set represented by coins */ +/***** + * @brief Apply the effects of this block (with given index) on the UTXO set represented by coins + * @param block the block to add + * @param state the result status + * @param pindex where to insert the block + * @param view the chain + * @param fJustCheck do not actually modify, only do checks + * @param fcheckPOW + * @returns true on success + */ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false,bool fCheckPOW = false); /** Context-independent validity checks */ diff --git a/src/test-komodo/test_pow.cpp b/src/test-komodo/test_pow.cpp index ae5f015f1a1..961f7d6d909 100644 --- a/src/test-komodo/test_pow.cpp +++ b/src/test-komodo/test_pow.cpp @@ -163,3 +163,16 @@ TEST(PoW, TestStopAt) KOMODO_STOPAT = 1; EXPECT_FALSE( ConnectBlock(block, state, chain.GetIndex(), *chain.GetCoinsViewCache(), false, true) ); } + + +TEST(PoW, TestNormalConnect) +{ + TestChain chain; + auto notary = chain.AddWallet(chain.getNotaryKey()); + CBlock lastBlock = chain.generateBlock(); // genesis block + ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); + CBlock block; + CValidationState state; + EXPECT_TRUE( ConnectBlock(block, state, chain.GetIndex(), *chain.GetCoinsViewCache(), false, true) ); + EXPECT_TRUE( state.IsValid() ); +} diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index 0afdbc9324b..23b6a0ebc5c 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -36,6 +36,8 @@ int64_t nMockTime; extern uint32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY; +void adjust_hwmheight(int32_t in); // in komodo.cpp + void setupChain() { SelectParams(CBaseChainParams::REGTEST); @@ -177,6 +179,7 @@ TestChain::TestChain() TestChain::~TestChain() { + adjust_hwmheight(0); // hwmheight can get skewed if komodo_connectblock not called (which some tests do) boost::filesystem::remove_all(dataDir); if (previousNetwork == "main") SelectParams(CBaseChainParams::MAIN); From fc14310e533332609a2b8c2201f6904a076eefd3 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 4 Nov 2021 17:07:01 -0500 Subject: [PATCH 17/47] More ConnectBlock tests --- src/test-komodo/test_pow.cpp | 118 ++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 3 deletions(-) diff --git a/src/test-komodo/test_pow.cpp b/src/test-komodo/test_pow.cpp index 961f7d6d909..30d61261484 100644 --- a/src/test-komodo/test_pow.cpp +++ b/src/test-komodo/test_pow.cpp @@ -165,14 +165,126 @@ TEST(PoW, TestStopAt) } -TEST(PoW, TestNormalConnect) +TEST(PoW, TestConnectWithoutChecks) { TestChain chain; auto notary = chain.AddWallet(chain.getNotaryKey()); + auto alice = chain.AddWallet(); CBlock lastBlock = chain.generateBlock(); // genesis block ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); + // Add some transaction to a block + int32_t newHeight = chain.GetIndex()->GetHeight() + 1; + auto notaryPrevOut = notary->GetAvailable(100000); + ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); + CMutableTransaction tx; + CTxIn notaryIn; + notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); + notaryIn.prevout.n = notaryPrevOut.second; + tx.vin.push_back(notaryIn); + CTxOut aliceOut; + aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceOut.nValue = 100000; + tx.vout.push_back(aliceOut); + CTxOut notaryOut; + notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); + notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; + tx.vout.push_back(notaryOut); + // sign it + uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); + tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); + CTransaction fundAlice(tx); + // construct the block CBlock block; + // first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // then the actual tx + block.vtx.push_back(fundAlice); CValidationState state; - EXPECT_TRUE( ConnectBlock(block, state, chain.GetIndex(), *chain.GetCoinsViewCache(), false, true) ); - EXPECT_TRUE( state.IsValid() ); + // create a new CBlockIndex to forward to ConnectBlock + auto view = chain.GetCoinsViewCache(); + auto index = chain.GetIndex(); + CBlockIndex newIndex; + newIndex.pprev = index; + EXPECT_TRUE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); + if (!state.IsValid() ) + FAIL() << state.GetRejectReason(); +} + +TEST(PoW, TestSpendInSameBlock) +{ + TestChain chain; + auto notary = chain.AddWallet(chain.getNotaryKey()); + auto alice = chain.AddWallet(); + auto bob = chain.AddWallet(); + CBlock lastBlock = chain.generateBlock(); // genesis block + ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); + // Add some transaction to a block + int32_t newHeight = chain.GetIndex()->GetHeight() + 1; + auto notaryPrevOut = notary->GetAvailable(100000); + ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); + CMutableTransaction tx; + CTxIn notaryIn; + notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); + notaryIn.prevout.n = notaryPrevOut.second; + tx.vin.push_back(notaryIn); + CTxOut aliceOut; + aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceOut.nValue = 100000; + tx.vout.push_back(aliceOut); + CTxOut notaryOut; + notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); + notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; + tx.vout.push_back(notaryOut); + // sign it + uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); + tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); + CTransaction fundAlice(tx); + // now have Alice move some funds to Bob in the same block + CMutableTransaction aliceToBobMutable; + CTxIn aliceIn; + aliceIn.prevout.hash = fundAlice.GetHash(); + aliceIn.prevout.n = 0; + aliceToBobMutable.vin.push_back(aliceIn); + CTxOut bobOut; + bobOut.scriptPubKey = GetScriptForDestination(bob->GetPubKey()); + bobOut.nValue = 10000; + aliceToBobMutable.vout.push_back(bobOut); + CTxOut aliceRemainder; + aliceRemainder.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceRemainder.nValue = aliceOut.nValue - 10000; + aliceToBobMutable.vout.push_back(aliceRemainder); + hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); + aliceToBobMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); + CTransaction aliceToBobTx(aliceToBobMutable); + // construct the block + CBlock block; + // first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // then the actual txs + block.vtx.push_back(fundAlice); + block.vtx.push_back(aliceToBobTx); + CValidationState state; + // create a new CBlockIndex to forward to ConnectBlock + auto index = chain.GetIndex(); + CBlockIndex newIndex; + newIndex.pprev = index; + EXPECT_TRUE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); + if (!state.IsValid() ) + FAIL() << state.GetRejectReason(); } From 528d8f6defaa4197cc3dcbd3423174700787e1a8 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 4 Nov 2021 17:30:58 -0500 Subject: [PATCH 18/47] fix mempool nullptr --- src/main.cpp | 36 +++++++++++++++++++------------- src/test-komodo/test_mempool.cpp | 4 ++-- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d20612700e9..3f8f726987a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -353,13 +353,21 @@ namespace { return &it->second; } - int GetHeight() + int GetChainHeight() { CBlockIndex *pindex; if ( (pindex= chainActive.LastTip()) != 0 ) return pindex->GetHeight(); else return(0); } + + unsigned int GetChainTime() + { + CBlockIndex *pIndex = chainActive.LastTip(); + if (pIndex == nullptr) + return 0; + return pIndex->nTime; + } void UpdatePreferredDownload(CNode* node, CNodeState* state) { @@ -608,7 +616,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { void RegisterNodeSignals(CNodeSignals& nodeSignals) { - nodeSignals.GetHeight.connect(&GetHeight); + nodeSignals.GetHeight.connect(&GetChainHeight); nodeSignals.ProcessMessages.connect(&ProcessMessages); nodeSignals.SendMessages.connect(&SendMessages); nodeSignals.InitializeNode.connect(&InitializeNode); @@ -617,7 +625,7 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals) void UnregisterNodeSignals(CNodeSignals& nodeSignals) { - nodeSignals.GetHeight.disconnect(&GetHeight); + nodeSignals.GetHeight.disconnect(&GetChainHeight); nodeSignals.ProcessMessages.disconnect(&ProcessMessages); nodeSignals.SendMessages.disconnect(&SendMessages); nodeSignals.InitializeNode.disconnect(&InitializeNode); @@ -1826,7 +1834,9 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } //fprintf(stderr,"addmempool 1\n"); auto verifier = libzcash::ProofVerifier::Strict(); - if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,chainActive.LastTip()->GetHeight()+1,chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 ) + if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != nullptr + && komodo_validate_interest(tx,chainActive.LastTip()->GetHeight()+1, + chainActive.LastTip()->GetMedianTimePast() + 777,0) < 0 ) { fprintf(stderr,"AcceptToMemoryPool komodo_validate_interest failure\n"); return error("AcceptToMemoryPool: komodo_validate_interest failed"); @@ -1964,9 +1974,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Bring the best block into scope view.GetBestBlock(); - nValueIn = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime); - if ( 0 && interest != 0 ) - fprintf(stderr,"add interest %.8f\n",(double)interest/COIN); + nValueIn = view.GetValueIn(GetChainHeight(),&interest,tx,GetChainTime()); // we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool view.SetBackend(dummy); } @@ -7213,7 +7221,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Reject incoming connections from nodes that don't know about the current epoch const Consensus::Params& params = Params().GetConsensus(); - auto currentEpoch = CurrentEpoch(GetHeight(), params); + auto currentEpoch = CurrentEpoch(GetChainHeight(), params); if (nVersion < params.vUpgrades[currentEpoch].nProtocolVersion) { LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, nVersion); @@ -7363,14 +7371,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // 1. The version message has been received // 2. Peer version is below the minimum version for the current epoch else if (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[ - CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion) + CurrentEpoch(GetChainHeight(), chainparams.GetConsensus())].nProtocolVersion) { - LogPrintf("peer=%d using obsolete version %i vs %d; disconnecting\n", pfrom->id, pfrom->nVersion,(int32_t)chainparams.GetConsensus().vUpgrades[ - CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion); + LogPrintf("peer=%d using obsolete version %i vs %d; disconnecting\n", + pfrom->id, pfrom->nVersion,(int32_t)chainparams.GetConsensus().vUpgrades[ + CurrentEpoch(GetChainHeight(), chainparams.GetConsensus())].nProtocolVersion); pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, - strprintf("Version must be %d or greater", - chainparams.GetConsensus().vUpgrades[ - CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion)); + strprintf("Version must be %d or greater", chainparams.GetConsensus().vUpgrades[ + CurrentEpoch(GetChainHeight(), chainparams.GetConsensus())].nProtocolVersion)); pfrom->fDisconnect = true; return false; } diff --git a/src/test-komodo/test_mempool.cpp b/src/test-komodo/test_mempool.cpp index d2d98fb5288..02be26fd878 100644 --- a/src/test-komodo/test_mempool.cpp +++ b/src/test-komodo/test_mempool.cpp @@ -141,8 +141,8 @@ TEST(Mempool, PriorityStatsDoNotCrash) { CTxMemPoolEntry entry(tx, nFees, nTime, dPriority, nHeight, true, false, SPROUT_BRANCH_ID); - // Check it does not crash (ie. the death test fails) - EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(testPool.addUnchecked(tx.GetHash(), entry), ""), ""); + // This should not crash + EXPECT_TRUE(testPool.addUnchecked(tx.GetHash(), entry)); EXPECT_EQ(dPriority, MAX_PRIORITY); } From 16291afb6f17301f3fdca410268d33e9ffeaa886 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 5 Nov 2021 09:03:13 -0500 Subject: [PATCH 19/47] Replace ptr with ref --- src/cc/CCutils.cpp | 2 +- src/coins.cpp | 25 +++++++++++++++++-------- src/coins.h | 13 +++++++------ src/main.cpp | 26 +++++++++----------------- src/miner.cpp | 2 +- 5 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/cc/CCutils.cpp b/src/cc/CCutils.cpp index bd79eaa6857..b52921702f9 100644 --- a/src/cc/CCutils.cpp +++ b/src/cc/CCutils.cpp @@ -160,7 +160,7 @@ bool CheckTxFee(const CTransaction &tx, uint64_t txfee, uint32_t height, uint64_ int64_t interest; uint64_t valuein; CCoinsViewMemPool viewMemPool(pcoinsTip, mempool); view.SetBackend(viewMemPool); - valuein = view.GetValueIn(height,&interest,tx,blocktime); + valuein = view.GetValueIn(height,interest,tx); actualtxfee = valuein-tx.GetValueOut(); if ( actualtxfee > txfee ) { diff --git a/src/coins.cpp b/src/coins.cpp index 92206b65379..8d9f7fe2bd8 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -593,11 +593,19 @@ const CScript &CCoinsViewCache::GetSpendFor(const CTxIn& input) const return GetSpendFor(coins, input); } -CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTransaction& tx,uint32_t tiptime) const +/** + * @brief get amount of bitcoins coming in to a transaction + * @note lightweight clients may not know anything besides the hash of previous transactions, + * so may not be able to calculate this. + * @param[in] nHeight the chain height + * @param[out] interestp the interest found + * @param[in] tx transaction for which we are checking input total + * @returns Sum of value of all inputs (scriptSigs), (positive valueBalance or zero) and JoinSplit vpub_new + */ +CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t &interestp,const CTransaction& tx) const { CAmount value,nResult = 0; - if ( interestp != 0 ) - *interestp = 0; + interestp = 0; if ( tx.IsCoinImport() ) return GetCoinImportValue(tx); if ( tx.IsCoinBase() != 0 ) @@ -616,12 +624,13 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTr { if ( value >= 10*COIN ) { - int64_t interest; int32_t txheight; uint32_t locktime; - interest = komodo_accrued_interest(&txheight,&locktime,tx.vin[i].prevout.hash,tx.vin[i].prevout.n,0,value,(int32_t)nHeight); - //printf("nResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nResult/COIN,(double)value/COIN,(double)interest/COIN,txheight,locktime,tiptime); - //fprintf(stderr,"nResult %.8f += val %.8f interest %.8f ht.%d lock.%u tip.%u\n",(double)nResult/COIN,(double)value/COIN,(double)interest/COIN,txheight,locktime,tiptime); + int64_t interest; + int32_t txheight; + uint32_t locktime; + interest = komodo_accrued_interest(&txheight,&locktime,tx.vin[i].prevout.hash, + tx.vin[i].prevout.n,0,value,(int32_t)nHeight); nResult += interest; - (*interestp) += interest; + interestp += interest; } } #endif diff --git a/src/coins.h b/src/coins.h index e0ea7d822b0..289daf5a83a 100644 --- a/src/coins.h +++ b/src/coins.h @@ -580,14 +580,15 @@ class CCoinsViewCache : public CCoinsViewBacked size_t DynamicMemoryUsage() const; /** - * Amount of bitcoins coming in to a transaction - * Note that lightweight clients may not know anything besides the hash of previous transactions, + * @brief get amount of bitcoins coming in to a transaction + * @note lightweight clients may not know anything besides the hash of previous transactions, * so may not be able to calculate this. - * - * @param[in] tx transaction for which we are checking input total - * @return Sum of value of all inputs (scriptSigs), (positive valueBalance or zero) and JoinSplit vpub_new + * @param[in] nHeight the chain height + * @param[out] interestp the interest found + * @param[in] tx transaction for which we are checking input total + * @returns Sum of value of all inputs (scriptSigs), (positive valueBalance or zero) and JoinSplit vpub_new */ - CAmount GetValueIn(int32_t nHeight,int64_t *interestp,const CTransaction& tx,uint32_t prevblocktime) const; + CAmount GetValueIn(int32_t nHeight,int64_t &interestp,const CTransaction& tx) const; //! Check whether all prevouts of the transaction are present in the UTXO set represented by this view bool HaveInputs(const CTransaction& tx) const; diff --git a/src/main.cpp b/src/main.cpp index 3f8f726987a..28f3a9eb92b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -353,21 +353,13 @@ namespace { return &it->second; } - int GetChainHeight() + int GetHeight() { CBlockIndex *pindex; if ( (pindex= chainActive.LastTip()) != 0 ) return pindex->GetHeight(); else return(0); } - - unsigned int GetChainTime() - { - CBlockIndex *pIndex = chainActive.LastTip(); - if (pIndex == nullptr) - return 0; - return pIndex->nTime; - } void UpdatePreferredDownload(CNode* node, CNodeState* state) { @@ -616,7 +608,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { void RegisterNodeSignals(CNodeSignals& nodeSignals) { - nodeSignals.GetHeight.connect(&GetChainHeight); + nodeSignals.GetHeight.connect(&GetHeight); nodeSignals.ProcessMessages.connect(&ProcessMessages); nodeSignals.SendMessages.connect(&SendMessages); nodeSignals.InitializeNode.connect(&InitializeNode); @@ -625,7 +617,7 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals) void UnregisterNodeSignals(CNodeSignals& nodeSignals) { - nodeSignals.GetHeight.disconnect(&GetChainHeight); + nodeSignals.GetHeight.disconnect(&GetHeight); nodeSignals.ProcessMessages.disconnect(&ProcessMessages); nodeSignals.SendMessages.disconnect(&SendMessages); nodeSignals.InitializeNode.disconnect(&InitializeNode); @@ -1974,7 +1966,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // Bring the best block into scope view.GetBestBlock(); - nValueIn = view.GetValueIn(GetChainHeight(),&interest,tx,GetChainTime()); + nValueIn = view.GetValueIn(GetHeight(),interest,tx); // we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool view.SetBackend(dummy); } @@ -3680,7 +3672,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } if (!tx.IsCoinBase()) { - nFees += (stakeTxValue= view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime) - valueout); + nFees += (stakeTxValue= view.GetValueIn(chainActive.LastTip()->GetHeight(),interest,tx) - valueout); sum += interest; std::vector vChecks; @@ -7221,7 +7213,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // Reject incoming connections from nodes that don't know about the current epoch const Consensus::Params& params = Params().GetConsensus(); - auto currentEpoch = CurrentEpoch(GetChainHeight(), params); + auto currentEpoch = CurrentEpoch(GetHeight(), params); if (nVersion < params.vUpgrades[currentEpoch].nProtocolVersion) { LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, nVersion); @@ -7371,14 +7363,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // 1. The version message has been received // 2. Peer version is below the minimum version for the current epoch else if (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[ - CurrentEpoch(GetChainHeight(), chainparams.GetConsensus())].nProtocolVersion) + CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion) { LogPrintf("peer=%d using obsolete version %i vs %d; disconnecting\n", pfrom->id, pfrom->nVersion,(int32_t)chainparams.GetConsensus().vUpgrades[ - CurrentEpoch(GetChainHeight(), chainparams.GetConsensus())].nProtocolVersion); + CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion); pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", chainparams.GetConsensus().vUpgrades[ - CurrentEpoch(GetChainHeight(), chainparams.GetConsensus())].nProtocolVersion)); + CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion)); pfrom->fDisconnect = true; return false; } diff --git a/src/miner.cpp b/src/miner.cpp index e9e12019643..28a7a62a1b0 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -568,7 +568,7 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 //fprintf(stderr,"dont have inputs\n"); continue; } - CAmount nTxFees = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime)-tx.GetValueOut(); + CAmount nTxFees = view.GetValueIn(chainActive.LastTip()->GetHeight(),interest,tx)-tx.GetValueOut(); nTxSigOps += GetP2SHSigOpCount(tx, view); if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1) From cfe4608ed8b0ecdd9fe02005122514bea687e05f Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 5 Nov 2021 10:13:58 -0500 Subject: [PATCH 20/47] test double-spend in same block --- src/coins.cpp | 2 +- src/test-komodo/test_pow.cpp | 90 ++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/coins.cpp b/src/coins.cpp index 8d9f7fe2bd8..8bd7592f5ba 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -628,7 +628,7 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t &interestp,const CTr int32_t txheight; uint32_t locktime; interest = komodo_accrued_interest(&txheight,&locktime,tx.vin[i].prevout.hash, - tx.vin[i].prevout.n,0,value,(int32_t)nHeight); + tx.vin[i].prevout.n,0,value,nHeight); nResult += interest; interestp += interest; } diff --git a/src/test-komodo/test_pow.cpp b/src/test-komodo/test_pow.cpp index 30d61261484..ebe6ee0b500 100644 --- a/src/test-komodo/test_pow.cpp +++ b/src/test-komodo/test_pow.cpp @@ -288,3 +288,93 @@ TEST(PoW, TestSpendInSameBlock) if (!state.IsValid() ) FAIL() << state.GetRejectReason(); } + +TEST(PoW, TestDoubleSpendInSameBlock) +{ + TestChain chain; + auto notary = chain.AddWallet(chain.getNotaryKey()); + auto alice = chain.AddWallet(); + auto bob = chain.AddWallet(); + auto charlie = chain.AddWallet(); + CBlock lastBlock = chain.generateBlock(); // genesis block + ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); + // Add some transaction to a block + int32_t newHeight = chain.GetIndex()->GetHeight() + 1; + auto notaryPrevOut = notary->GetAvailable(100000); + ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); + CMutableTransaction tx; + CTxIn notaryIn; + notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); + notaryIn.prevout.n = notaryPrevOut.second; + tx.vin.push_back(notaryIn); + CTxOut aliceOut; + aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceOut.nValue = 100000; + tx.vout.push_back(aliceOut); + CTxOut notaryOut; + notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); + notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; + tx.vout.push_back(notaryOut); + // sign it + uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); + tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); + CTransaction fundAlice(tx); + // now have Alice move some funds to Bob in the same block + CMutableTransaction aliceToBobMutable; + CTxIn aliceIn; + aliceIn.prevout.hash = fundAlice.GetHash(); + aliceIn.prevout.n = 0; + aliceToBobMutable.vin.push_back(aliceIn); + CTxOut bobOut; + bobOut.scriptPubKey = GetScriptForDestination(bob->GetPubKey()); + bobOut.nValue = 10000; + aliceToBobMutable.vout.push_back(bobOut); + CTxOut aliceRemainder; + aliceRemainder.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceRemainder.nValue = aliceOut.nValue - 10000; + aliceToBobMutable.vout.push_back(aliceRemainder); + hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); + aliceToBobMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); + CTransaction aliceToBobTx(aliceToBobMutable); + // alice attempts to double spend and send the same to charlie + CMutableTransaction aliceToCharlieMutable; + CTxIn aliceIn2; + aliceIn2.prevout.hash = fundAlice.GetHash(); + aliceIn2.prevout.n = 0; + aliceToCharlieMutable.vin.push_back(aliceIn2); + CTxOut charlieOut; + charlieOut.scriptPubKey = GetScriptForDestination(charlie->GetPubKey()); + charlieOut.nValue = 10000; + aliceToCharlieMutable.vout.push_back(charlieOut); + CTxOut aliceRemainder2; + aliceRemainder2.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceRemainder2.nValue = aliceOut.nValue - 10000; + aliceToCharlieMutable.vout.push_back(aliceRemainder2); + hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToCharlieMutable, 0, SIGHASH_ALL, 0, 0); + aliceToCharlieMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); + CTransaction aliceToCharlieTx(aliceToCharlieMutable); + // construct the block + CBlock block; + // first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // then the actual txs + block.vtx.push_back(fundAlice); + block.vtx.push_back(aliceToBobTx); + block.vtx.push_back(aliceToCharlieTx); + CValidationState state; + // create a new CBlockIndex to forward to ConnectBlock + auto index = chain.GetIndex(); + CBlockIndex newIndex; + newIndex.pprev = index; + EXPECT_FALSE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); + EXPECT_EQ(state.GetRejectReason(), "bad-txns-inputs-missingorspent"); +} + From 11991b31aaa60fc87d49956e2176cdb79a84696c Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 9 Nov 2021 16:46:51 -0500 Subject: [PATCH 21/47] Document mempool funcs --- src/Makefile.ktest.include | 3 +- src/cc/CCinclude.h | 20 ++- src/main.cpp | 309 ++++++++++++++++++--------------- src/main.h | 42 +++-- src/test-komodo/test_block.cpp | 263 +++++++++++++++++++++++++++- src/test-komodo/test_pow.cpp | 232 ------------------------- 6 files changed, 479 insertions(+), 390 deletions(-) diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 72b3296ec37..04852a8beb7 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -24,7 +24,8 @@ komodo_test_SOURCES = \ test-komodo/test_mempool.cpp \ test-komodo/test_pow.cpp \ test-komodo/test_txid.cpp \ - test-komodo/test_coins.cpp + test-komodo/test_coins.cpp \ + main.cpp komodo_test_CPPFLAGS = $(komodod_CPPFLAGS) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 5f689f7a5f1..3f935564c05 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -266,10 +266,13 @@ static uint256 ignoretxid; static int32_t ignorevin; /// \endcond -/// myGetTransaction is non-locking version of GetTransaction -/// @param hash hash of transaction to get (txid) -/// @param[out] txOut returned transaction object -/// @param[out] hashBlock hash of the block where the tx resides +/***** + * @brief get a transaction by its hash (without locks) + * @param[in] hash what to look for + * @param[out] txOut the found transaction + * @param[out] hashBlock the hash of the block (all zeros if still in mempool) + * @returns true if found + */ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock); /// NSPV_myGetTransaction is called in NSPV mode @@ -290,7 +293,14 @@ int64_t CCgettxout(uint256 txid,int32_t vout,int32_t mempoolflag,int32_t lockfla /// \cond INTERNAL bool myIsutxo_spentinmempool(uint256 &spenttxid,int32_t &spentvini,uint256 txid,int32_t vout); -bool myAddtomempool(CTransaction &tx, CValidationState *pstate = NULL, bool fSkipExpiry = false); +/**** + * @brief add a transaction to the mempool + * @param[in] tx the transaction + * @param pstate where to store any error (can be nullptr) + * @param fSkipExpiry + * @returns true on success + */ +bool myAddtomempool(CTransaction &tx, CValidationState *pstate = nullptr, bool fSkipExpiry = false); bool mytxid_inmempool(uint256 txid); int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout); int32_t myGet_mempool_txs(std::vector &txs,uint8_t evalcode,uint8_t funcid); diff --git a/src/main.cpp b/src/main.cpp index 28f3a9eb92b..4fbe34e381a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1798,19 +1798,30 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF return nMinFee; } - +/***** + * @brief Try to add transaction to memory pool + * @param pool + * @param state + * @param tx + * @param fLimitFree + * @param pfMissingInputs + * @param fRejectAbsurdFee + * @param dosLevel + * @returns true on success + */ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,bool* pfMissingInputs, bool fRejectAbsurdFee, int dosLevel) { AssertLockHeld(cs_main); - if (pfMissingInputs) + if (pfMissingInputs != nullptr) *pfMissingInputs = false; uint32_t tiptime; - int flag=0,nextBlockHeight = chainActive.Height() + 1; + int flag=0; + int nextBlockHeight = chainActive.Height() + 1; auto consensusBranchId = CurrentEpochBranchId(nextBlockHeight, Params().GetConsensus()); if ( nextBlockHeight <= 1 || chainActive.LastTip() == 0 ) tiptime = (uint32_t)time(NULL); - else tiptime = (uint32_t)chainActive.LastTip()->nTime; -//fprintf(stderr,"addmempool 0\n"); + else + tiptime = (uint32_t)chainActive.LastTip()->nTime; // Node operator can choose to reject tx by number of transparent inputs static_assert(std::numeric_limits::max() >= std::numeric_limits::max(), "size_t too small"); size_t limit = (size_t) GetArg("-mempooltxinputlimit", 0); @@ -1824,7 +1835,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa return false; } } -//fprintf(stderr,"addmempool 1\n"); auto verifier = libzcash::ProofVerifier::Strict(); if ( ASSETCHAINS_SYMBOL[0] == 0 && chainActive.LastTip() != nullptr && komodo_validate_interest(tx,chainActive.LastTip()->GetHeight()+1, @@ -1845,8 +1855,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { return error("AcceptToMemoryPool: ContextualCheckTransaction failed"); } -//fprintf(stderr,"addmempool 2\n"); - // Coinbase is only valid in a block, not as a loose transaction + // Coinbase is only valid in a block, not as a loose transaction if (tx.IsCoinBase()) { fprintf(stderr,"AcceptToMemoryPool coinbase as individual tx\n"); @@ -1857,8 +1866,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa string reason; if (Params().RequireStandard() && !IsStandardTx(tx, reason, nextBlockHeight)) { - // - //fprintf(stderr,"AcceptToMemoryPool reject nonstandard transaction: %s\nscriptPubKey: %s\n",reason.c_str(),tx.vout[0].scriptPubKey.ToString().c_str()); return state.DoS(0,error("AcceptToMemoryPool: nonstandard transaction: %s", reason),REJECT_NONSTANDARD, reason); } @@ -1867,15 +1874,12 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // be mined yet. if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) { - //fprintf(stderr,"AcceptToMemoryPool reject non-final\n"); return state.DoS(0, false, REJECT_NONSTANDARD, "non-final"); } -//fprintf(stderr,"addmempool 3\n"); // is it already in the memory pool? uint256 hash = tx.GetHash(); if (pool.exists(hash)) { - //fprintf(stderr,"already in mempool\n"); return state.Invalid(false, REJECT_DUPLICATE, "already in mempool"); } @@ -1905,7 +1909,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } } -//fprintf(stderr,"addmempool 4\n"); { CCoinsView dummy; CCoinsViewCache view(&dummy); @@ -1919,7 +1922,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // do we already have it? if (view.HaveCoins(hash)) { - //fprintf(stderr,"view.HaveCoins(hash) error\n"); return state.Invalid(false, REJECT_DUPLICATE, "already have coins"); } @@ -1940,7 +1942,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa { if (pfMissingInputs) *pfMissingInputs = true; - //fprintf(stderr,"missing inputs\n"); return false; /* https://github.com/zcash/zcash/blob/master/src/main.cpp#L1490 @@ -1951,7 +1952,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // are the actual inputs available? if (!view.HaveInputs(tx)) { - //fprintf(stderr,"accept failure.1\n"); return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent"); } } @@ -1959,7 +1959,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa // are the joinsplit's requirements met? if (!view.HaveJoinSplitRequirements(tx)) { - //fprintf(stderr,"accept failure.2\n"); return state.Invalid(error("AcceptToMemoryPool: joinsplit requirements not met"),REJECT_DUPLICATE, "bad-txns-joinsplit-requirements-not-met"); } @@ -2005,7 +2004,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } } -//fprintf(stderr,"addmempool 5\n"); // Grab the branch ID we expect this transaction to commit to. We don't // yet know if it does, but if the entry gets added to the mempool, then // it has passed ContextualCheckInputs and therefore this is correct. @@ -2067,7 +2065,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa LogPrint("mempool", errmsg.c_str()); return state.Error("AcceptToMemoryPool: " + errmsg); } -//fprintf(stderr,"addmempool 6\n"); // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. @@ -2093,7 +2090,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa flag = 1; KOMODO_CONNECTING = (1<<30) + (int32_t)chainActive.LastTip()->GetHeight() + 1; } -//fprintf(stderr,"addmempool 7\n"); if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId)) { @@ -2122,17 +2118,21 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa } } } - // This should be here still? - //SyncWithWallets(tx, NULL); return true; } +/**** + * @brief Add a transaction to the memory pool without the checks of AcceptToMemoryPool + * @param pool the memory pool to add the transaction to + * @param tx the transaction + * @returns true + */ bool CCTxFixAcceptToMemPoolUnchecked(CTxMemPool& pool, const CTransaction &tx) { // called from CheckBlock which is in cs_main and mempool.cs locks already. auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - CTxMemPoolEntry entry(tx, 0, GetTime(), 0, chainActive.Height(), mempool.HasNoInputsOf(tx), false, consensusBranchId); - //fprintf(stderr, "adding %s to mempool from block %d\n",tx.GetHash().ToString().c_str(),chainActive.GetHeight()); + CTxMemPoolEntry entry(tx, 0, GetTime(), 0, chainActive.Height(), + mempool.HasNoInputsOf(tx), false, consensusBranchId); pool.addUnchecked(tx.GetHash(), entry, false); return true; } @@ -2200,41 +2200,49 @@ struct CompareBlocksByHeightMain } }; -/*uint64_t myGettxout(uint256 hash,int32_t n) -{ - CCoins coins; - LOCK2(cs_main,mempool.cs); - CCoinsViewMemPool view(pcoinsTip, mempool); - if (!view.GetCoins(hash, coins)) - return(0); - if ( n < 0 || (unsigned int)n >= coins.vout.size() || coins.vout[n].IsNull() ) - return(0); - else return(coins.vout[n].nValue); -}*/ - -bool myAddtomempool(CTransaction &tx, CValidationState *pstate, bool fSkipExpiry) +/**** + * @brief add a transaction to the mempool + * @param[in] tx the transaction + * @param pstate where to store any error (can be nullptr) + * @param fSkipExpiry set to false to add to pool without many checks + * @returns true on success + */ +bool myAddtomempool(const CTransaction &tx, CValidationState *pstate, bool fSkipExpiry) { CValidationState state; - if (!pstate) + if (pstate == nullptr) pstate = &state; - CTransaction Ltx; bool fMissingInputs,fOverrideFees = false; - if ( mempool.lookup(tx.GetHash(),Ltx) == 0 ) + + CTransaction Ltx; + if ( mempool.lookup(tx.GetHash(),Ltx) == false ) // does not already exist { if ( !fSkipExpiry ) + { + bool fMissingInputs; + bool fOverrideFees = false; return(AcceptToMemoryPool(mempool, *pstate, tx, false, &fMissingInputs, !fOverrideFees, -1)); + } else return(CCTxFixAcceptToMemPoolUnchecked(mempool,tx)); } - else return(true); + return true; } +/***** + * @brief get a transaction by its hash (without locks) + * @param[in] hash what to look for + * @param[out] txOut the found transaction + * @param[out] hashBlock the hash of the block (all zeros if still in mempool) + * @returns true if found + */ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock) { memset(&hashBlock,0,sizeof(hashBlock)); if ( KOMODO_NSPV_SUPERLITE ) { - int64_t rewardsum = 0; int32_t i,retval,txheight,currentheight,height=0,vout = 0; - for (i=0; iReadTxIndex(hash, postx)) { - //fprintf(stderr,"OpenBlockFile\n"); + if (pblocktree->ReadTxIndex(hash, postx)) + { + // Found the transaction in the index. Load the block to get the block hash CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION); if (file.IsNull()) return error("%s: OpenBlockFile failed", __func__); CBlockHeader header; - //fprintf(stderr,"seek and read\n"); try { file >> header; fseek(file.Get(), postx.nTxOffset, SEEK_CUR); @@ -2274,11 +2280,9 @@ bool myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlo hashBlock = header.GetHash(); if (txOut.GetHash() != hash) return error("%s: txid mismatch", __func__); - //fprintf(stderr,"found on disk %s\n",hash.GetHex().c_str()); return true; } } - //fprintf(stderr,"not found on disk %s\n",hash.GetHex().c_str()); return false; } @@ -2300,10 +2304,16 @@ bool NSPV_myGetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &ha return false; } -/** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */ +/** + * @brief Find a transaction (uses locks) + * @param[in] hash the transaction to look for + * @param[out] txOut the transaction found + * @param[out] hashBlock the block where the transaction was found (all zeros if found in mempool) + * @param[in] fAllowSlow true to continue searching even if there are no transaction indexes + * @returns true if found + */ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) { - CBlockIndex *pindexSlow = NULL; memset(&hashBlock,0,sizeof(hashBlock)); LOCK(cs_main); @@ -2334,26 +2344,33 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock } } + CBlockIndex *pindexSlow = nullptr; if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it int nHeight = -1; { - CCoinsViewCache &view = *pcoinsTip; - const CCoins* coins = view.AccessCoins(hash); - if (coins) + const CCoins* coins = pcoinsTip->AccessCoins(hash); + if (coins != nullptr) + { nHeight = coins->nHeight; - } - if (nHeight > 0) - pindexSlow = chainActive[nHeight]; - } - - if (pindexSlow) { - CBlock block; - if (ReadBlockFromDisk(block, pindexSlow,1)) { - BOOST_FOREACH(const CTransaction &tx, block.vtx) { - if (tx.GetHash() == hash) { - txOut = tx; - hashBlock = pindexSlow->GetBlockHash(); - return true; + if (nHeight > 0) + { + CBlockIndex *pindexSlow = chainActive[nHeight]; + if (pindexSlow != nullptr) + { + CBlock block; + if (ReadBlockFromDisk(block, pindexSlow,1)) + { + for(const CTransaction &tx : block.vtx) + { + if (tx.GetHash() == hash) + { + txOut = tx; + hashBlock = pindexSlow->GetBlockHash(); + return true; + } + } + } + } } } } @@ -2362,21 +2379,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock return false; } -/*char *komodo_getspendscript(uint256 hash,int32_t n) - { - CTransaction tx; uint256 hashBlock; - if ( !GetTransaction(hash,tx,hashBlock,true) ) - { - printf("null GetTransaction\n"); - return(0); - } - if ( n >= 0 && n < tx.vout.size() ) - return((char *)tx.vout[n].scriptPubKey.ToString().c_str()); - else printf("getspendscript illegal n.%d\n",n); - return(0); - }*/ - - ////////////////////////////////////////////////////////////////////////////// // // CBlock and CBlockIndex @@ -4233,13 +4235,16 @@ static int64_t nTimeFlush = 0; static int64_t nTimeChainState = 0; static int64_t nTimePostConnect = 0; -/** - * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock - * corresponding to pindexNew, to bypass loading it again from disk. - * You probably want to call mempool.removeWithoutBranchId after this, with cs_main held. +/*** + * @brief Connect a new block to chainActive. + * @note You probably want to call mempool.removeWithoutBranchId after this, with cs_main held. + * @param[out] state holds the state + * @param pindexNew the new index + * @param pblock a pointer to a CBlock (nullptr will load it from disk) + * @returns true on success */ -bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) { - +bool ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) +{ assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. int64_t nTime1 = GetTimeMicros(); @@ -4544,8 +4549,10 @@ static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBloc nHeight = nTargetHeight; // Connect new blocks. - BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { - if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) { + for(CBlockIndex *pindexConnect : vpindexToConnect) + { + if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) + { if (state.IsInvalid()) { // The block violates a consensus rule. if (!state.CorruptionPossible()) @@ -5105,13 +5112,26 @@ bool CheckBlockHeader(int32_t *futureblockp,int32_t height,CBlockIndex *pindex, int32_t komodo_check_deposit(int32_t height,const CBlock& block,uint32_t prevtime); int32_t komodo_checkPOW(int64_t stakeTxValue,int32_t slowflag,CBlock *pblock,int32_t height); -bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const CBlock& block, CValidationState& state, - libzcash::ProofVerifier& verifier, - bool fCheckPOW, bool fCheckMerkleRoot) +/**** + * @brief various checks of block validity + * @param[out] futureblockp pointer to the future block + * @param[in] height the new height + * @param[out] pindex the block index + * @param[in] block the block to check + * @param[out] state stores results + * @param[in] verifier verification routine + * @param[in] fCheckPOW pass true to check PoW + * @param[in] fCheckMerkleRoot pass true to check merkle root + * @returns true on success, on error, state will contain info + */ +bool CheckBlock(int32_t *futureblockp, int32_t height, CBlockIndex *pindex, const CBlock& block, + CValidationState& state, libzcash::ProofVerifier& verifier, bool fCheckPOW, + bool fCheckMerkleRoot) { - uint8_t pubkey33[33]; uint256 hash; uint32_t tiptime = (uint32_t)block.nTime; + uint8_t pubkey33[33]; + uint32_t tiptime = (uint32_t)block.nTime; // These are checks that are independent of context. - hash = block.GetHash(); + uint256 hash = block.GetHash(); // Check that the header is valid (particularly PoW). This is mostly redundant with the call in AcceptBlockHeader. if (!CheckBlockHeader(futureblockp,height,pindex,block,state,fCheckPOW)) { @@ -5121,22 +5141,21 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C return false; } } - if ( pindex != 0 && pindex->pprev != 0 ) + if ( pindex != nullptr && pindex->pprev != nullptr ) tiptime = (uint32_t)pindex->pprev->nTime; if ( fCheckPOW ) { - //if ( !CheckEquihashSolution(&block, Params()) ) - // return state.DoS(100, error("CheckBlock: Equihash solution invalid"),REJECT_INVALID, "invalid-solution"); komodo_block2pubkey33(pubkey33,(CBlock *)&block); if ( !CheckProofOfWork(block,pubkey33,height,Params().GetConsensus()) ) { - int32_t z; for (z=31; z>=0; z--) + for (int32_t z = 31; z >= 0; z--) fprintf(stderr,"%02x",((uint8_t *)&hash)[z]); fprintf(stderr," failed hash ht.%d\n",height); return state.DoS(50, error("CheckBlock: proof of work failed"),REJECT_INVALID, "high-hash"); } if ( ASSETCHAINS_STAKED == 0 && komodo_checkPOW(0,1,(CBlock *)&block,height) < 0 ) // checks Equihash - return state.DoS(100, error("CheckBlock: failed slow_checkPOW"),REJECT_INVALID, "failed-slow_checkPOW"); + return state.DoS(100, error("CheckBlock: failed slow_checkPOW"),REJECT_INVALID, + "failed-slow_checkPOW"); } if ( height > nDecemberHardforkHeight && ASSETCHAINS_SYMBOL[0] == 0 ) // December 2019 hardfork { @@ -5147,14 +5166,17 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C CBlock blockcopy = block; // block shouldn't be changed below, so let's make it's copy CBlock *pblockcopy = (CBlock *)&blockcopy; if (!komodo_checkopret(pblockcopy, merkleroot)) { - fprintf(stderr, "failed or missing merkleroot expected.%s != merkleroot.%s\n", komodo_makeopret(pblockcopy, false).ToString().c_str(), merkleroot.ToString().c_str()); - return state.DoS(100, error("CheckBlock: failed or missing merkleroot opret in easy-mined"),REJECT_INVALID, "failed-merkle-opret-in-easy-mined"); + fprintf(stderr, "failed or missing merkleroot expected.%s != merkleroot.%s\n", + komodo_makeopret(pblockcopy, false).ToString().c_str(), merkleroot.ToString().c_str()); + return state.DoS(100, error("CheckBlock: failed or missing merkleroot opret in easy-mined"), + REJECT_INVALID, "failed-merkle-opret-in-easy-mined"); } } } // Check the merkle root. - if (fCheckMerkleRoot) { + if (fCheckMerkleRoot) + { bool mutated; uint256 hashMerkleRoot2 = block.BuildMerkleTree(&mutated); if (block.hashMerkleRoot != hashMerkleRoot2) @@ -5174,8 +5196,8 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C // because we receive the wrong transactions for it. // Size limits - //fprintf(stderr,"%s checkblock %d -> %d vs blocksize.%d\n",ASSETCHAINS_SYMBOL,height,MAX_BLOCK_SIZE(height),(int32_t)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)); - if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE(height) || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE(height)) + if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE(height) + || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE(height)) return state.DoS(100, error("CheckBlock: size limits failed"), REJECT_INVALID, "bad-blk-length"); @@ -5190,18 +5212,17 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C REJECT_INVALID, "bad-cb-multiple"); // Check transactions - CTransaction sTx; - CTransaction *ptx = NULL; if ( ASSETCHAINS_CC != 0 && !fCheckPOW ) return true; + CTransaction sTx; + CTransaction *ptx = nullptr; + if ( ASSETCHAINS_CC != 0 ) // CC contracts might refer to transactions in the current block, from a CC spend within the same block and out of order { int32_t i,j,rejects=0,lastrejects=0; - //fprintf(stderr,"put block's tx into mempool\n"); // Copy all non Z-txs in mempool to temporary mempool because there can be tx in local mempool that make the block invalid. LOCK2(cs_main,mempool.cs); - //fprintf(stderr, "starting... mempoolsize.%ld\n",mempool.size()); list transactionsToRemove; BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) { const CTransaction &tx = e.GetTx(); @@ -5216,43 +5237,43 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C mempool.remove(tx, removed, false); } // add all the txs in the block to the empty mempool. - // CC validation shouldnt (cant) depend on the state of mempool! - while ( 1 ) + // CC validation shouldn't (can't) depend on the state of mempool! + while ( true ) { list removed; for (i=0; i all tx in mempool\n",lastrejects); break; } - //fprintf(stderr,"addtomempool ht.%d for CC checking: n.%d rejects.%d last.%d\n",height,(int32_t)block.vtx.size(),rejects,lastrejects); lastrejects = rejects; rejects = 0; } - //fprintf(stderr,"done putting block's tx into mempool\n"); } for (uint32_t i = 0; i < block.vtx.size(); i++) @@ -5749,13 +5770,29 @@ CBlockIndex *oldkomodo_ensure(CBlock *pblock, uint256 hash) return(pindex); } -bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) +/***** + * @brief Process a new block + * @note can come from the network or locally mined + * @note This only returns after the best known valid + * block is made active. Note that it does not, however, guarantee that the + * specific block passed to it has been checked for validity! + * @param from_miner no longer used + * @param height the new height + * @param[out] state the results + * @param pfrom the node that produced the block (nullptr for local) + * @param pblock the block to process + * @param fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers. + * @param[out] dbp set to position on disk for block + * @returns true on success + */ +bool ProcessNewBlock(bool from_miner, int32_t height, CValidationState &state, CNode* pfrom, + CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp) { // Preliminary checks - bool checked; uint256 hash; int32_t futureblock=0; + bool checked; + int32_t futureblock=0; auto verifier = libzcash::ProofVerifier::Disabled(); - hash = pblock->GetHash(); - //fprintf(stderr,"ProcessBlock %d\n",(int32_t)chainActive.LastTip()->GetHeight()); + uint256 hash = pblock->GetHash(); { LOCK(cs_main); if ( chainActive.LastTip() != 0 ) @@ -5763,14 +5800,13 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo checked = CheckBlock(&futureblock,height!=0?height:komodo_block2height(pblock),0,*pblock, state, verifier,0); bool fRequested = MarkBlockAsReceived(hash); fRequested |= fForceProcessing; - if ( checked != 0 && komodo_checkPOW(0,0,pblock,height) < 0 ) //from_miner && ASSETCHAINS_STAKED == 0 + if ( checked && komodo_checkPOW(0,0,pblock,height) < 0 ) { - checked = 0; - //fprintf(stderr,"passed checkblock but failed checkPOW.%d\n",from_miner && ASSETCHAINS_STAKED == 0); + checked = false; } if (!checked && futureblock == 0) { - if ( pfrom != 0 ) + if ( pfrom != nullptr ) { Misbehaving(pfrom->GetId(), 1); } @@ -5786,20 +5822,13 @@ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNo CheckBlockIndex(); if (!ret && futureblock == 0) { - /*if ( ASSETCHAINS_SYMBOL[0] == 0 ) - { - //fprintf(stderr,"request headers from failed process block peer\n"); - pfrom->PushMessage("getheaders", chainActive.GetLocator(chainActive.LastTip()), uint256()); - }*/ komodo_longestchain(); return error("%s: AcceptBlock FAILED", __func__); } - //else fprintf(stderr,"added block %s %p\n",pindex->GetBlockHash().ToString().c_str(),pindex->pprev); } if (futureblock == 0 && !ActivateBestChain(false, state, pblock)) return error("%s: ActivateBestChain failed", __func__); - //fprintf(stderr,"finished ProcessBlock %d\n",(int32_t)chainActive.LastTip()->GetHeight()); return true; } diff --git a/src/main.h b/src/main.h index 696922b4b39..de9130d3751 100644 --- a/src/main.h +++ b/src/main.h @@ -202,17 +202,20 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals); /** Unregister a network node */ void UnregisterNodeSignals(CNodeSignals& nodeSignals); -/** - * Process an incoming block. This only returns after the best known valid +/***** + * @brief Process a new block + * @note can come from the network or locally mined + * @note This only returns after the best known valid * block is made active. Note that it does not, however, guarantee that the * specific block passed to it has been checked for validity! - * - * @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface (see validationinterface.h) - this will have its BlockChecked method called whenever *any* block completes validation. - * @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. - * @param[in] pblock The block we want to process. - * @param[in] fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers. - * @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. - * @return True if state.IsValid() + * @param from_miner no longer used + * @param height the new height + * @param[out] state the results + * @param pfrom the node that produced the block (nullptr for local) + * @param pblock the block to process + * @param fForceProcessing Process this block even if unrequested; used for non-network block sources and whitelisted peers. + * @param[out] dbp set to position on disk for block + * @returns true on success */ bool ProcessNewBlock(bool from_miner,int32_t height,CValidationState &state, CNode* pfrom, CBlock* pblock, bool fForceProcessing, CDiskBlockPos *dbp); /** Check whether enough disk space is available for an incoming block */ @@ -252,7 +255,14 @@ bool IsInitialBlockDownload(); int IsNotInSync(); /** Format a string that describes several potential problems detected by the core */ std::string GetWarnings(const std::string& strFor); -/** Retrieve a transaction (from memory pool, or from disk, if possible) */ +/** + * @brief Find a transaction (uses locks) + * @param[in] hash the transaction to look for + * @param[out] txOut the transaction found + * @param[out] hashBlock the block where the transaction was found (all zeros if found in mempool) + * @param[in] fAllowSlow true to continue searching even if there are no transaction indexes + * @returns true if found + */ bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock, bool fAllowSlow = false); /** Find the best known block, and make it the tip of the block chain */ bool ActivateBestChain(bool fSkipdpow, CValidationState &state, CBlock *pblock = NULL); @@ -291,7 +301,17 @@ void FlushStateToDisk(); /** Prune block files and flush state to disk. */ void PruneAndFlush(); -/** (try to) add transaction to memory pool **/ +/** + * @brief Try to add transaction to memory pool + * @param pool + * @param state + * @param tx + * @param fLimitFree + * @param pfMissingInputs + * @param fRejectAbsurdFee + * @param dosLevel + * @returns true on success + */ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree, bool* pfMissingInputs, bool fRejectAbsurdFee=false, int dosLevel=-1); diff --git a/src/test-komodo/test_block.cpp b/src/test-komodo/test_block.cpp index 972cc64e78c..812a0c653ba 100644 --- a/src/test-komodo/test_block.cpp +++ b/src/test-komodo/test_block.cpp @@ -1,6 +1,10 @@ +#include "primitives/block.h" +#include "testutils.h" +#include "komodo_extern_globals.h" +#include "consensus/validation.h" + #include -#include "primitives/block.h" TEST(block_tests, header_size_is_expected) { // Header with an empty Equihash solution. @@ -12,3 +16,260 @@ TEST(block_tests, header_size_is_expected) { // ss.size is +1 due to data stream header of 1 byte EXPECT_EQ(ss.size(), stream_size); } + +TEST(block_tests, TestStopAt) +{ + TestChain chain; + auto notary = chain.AddWallet(chain.getNotaryKey()); + CBlock lastBlock = chain.generateBlock(); // genesis block + ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); + lastBlock = chain.generateBlock(); // now we should be above 1 + ASSERT_GT( chain.GetIndex()->GetHeight(), 1); + CBlock block; + CValidationState state; + KOMODO_STOPAT = 1; + EXPECT_FALSE( ConnectBlock(block, state, chain.GetIndex(), *chain.GetCoinsViewCache(), false, true) ); +} + +TEST(block_tests, TestConnectWithoutChecks) +{ + TestChain chain; + auto notary = chain.AddWallet(chain.getNotaryKey()); + auto alice = chain.AddWallet(); + CBlock lastBlock = chain.generateBlock(); // genesis block + ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); + // Add some transaction to a block + int32_t newHeight = chain.GetIndex()->GetHeight() + 1; + auto notaryPrevOut = notary->GetAvailable(100000); + ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); + CMutableTransaction tx; + CTxIn notaryIn; + notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); + notaryIn.prevout.n = notaryPrevOut.second; + tx.vin.push_back(notaryIn); + CTxOut aliceOut; + aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceOut.nValue = 100000; + tx.vout.push_back(aliceOut); + CTxOut notaryOut; + notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); + notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; + tx.vout.push_back(notaryOut); + // sign it + uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); + tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); + CTransaction fundAlice(tx); + // construct the block + CBlock block; + // first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // then the actual tx + block.vtx.push_back(fundAlice); + CValidationState state; + // create a new CBlockIndex to forward to ConnectBlock + auto view = chain.GetCoinsViewCache(); + auto index = chain.GetIndex(); + CBlockIndex newIndex; + newIndex.pprev = index; + EXPECT_TRUE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); + if (!state.IsValid() ) + FAIL() << state.GetRejectReason(); +} + +TEST(block_tests, TestSpendInSameBlock) +{ + TestChain chain; + auto notary = chain.AddWallet(chain.getNotaryKey()); + auto alice = chain.AddWallet(); + auto bob = chain.AddWallet(); + CBlock lastBlock = chain.generateBlock(); // genesis block + ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); + // Add some transaction to a block + int32_t newHeight = chain.GetIndex()->GetHeight() + 1; + auto notaryPrevOut = notary->GetAvailable(100000); + ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); + CMutableTransaction tx; + CTxIn notaryIn; + notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); + notaryIn.prevout.n = notaryPrevOut.second; + tx.vin.push_back(notaryIn); + CTxOut aliceOut; + aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceOut.nValue = 100000; + tx.vout.push_back(aliceOut); + CTxOut notaryOut; + notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); + notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; + tx.vout.push_back(notaryOut); + // sign it + uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); + tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); + CTransaction fundAlice(tx); + // now have Alice move some funds to Bob in the same block + CMutableTransaction aliceToBobMutable; + CTxIn aliceIn; + aliceIn.prevout.hash = fundAlice.GetHash(); + aliceIn.prevout.n = 0; + aliceToBobMutable.vin.push_back(aliceIn); + CTxOut bobOut; + bobOut.scriptPubKey = GetScriptForDestination(bob->GetPubKey()); + bobOut.nValue = 10000; + aliceToBobMutable.vout.push_back(bobOut); + CTxOut aliceRemainder; + aliceRemainder.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceRemainder.nValue = aliceOut.nValue - 10000; + aliceToBobMutable.vout.push_back(aliceRemainder); + hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); + aliceToBobMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); + CTransaction aliceToBobTx(aliceToBobMutable); + // construct the block + CBlock block; + // first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // then the actual txs + block.vtx.push_back(fundAlice); + block.vtx.push_back(aliceToBobTx); + CValidationState state; + // create a new CBlockIndex to forward to ConnectBlock + auto index = chain.GetIndex(); + CBlockIndex newIndex; + newIndex.pprev = index; + EXPECT_TRUE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); + if (!state.IsValid() ) + FAIL() << state.GetRejectReason(); +} + +TEST(block_tests, TestDoubleSpendInSameBlock) +{ + TestChain chain; + auto notary = chain.AddWallet(chain.getNotaryKey()); + auto alice = chain.AddWallet(); + auto bob = chain.AddWallet(); + auto charlie = chain.AddWallet(); + CBlock lastBlock = chain.generateBlock(); // genesis block + ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); + // Add some transaction to a block + int32_t newHeight = chain.GetIndex()->GetHeight() + 1; + auto notaryPrevOut = notary->GetAvailable(100000); + ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); + CMutableTransaction tx; + CTxIn notaryIn; + notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); + notaryIn.prevout.n = notaryPrevOut.second; + tx.vin.push_back(notaryIn); + CTxOut aliceOut; + aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceOut.nValue = 100000; + tx.vout.push_back(aliceOut); + CTxOut notaryOut; + notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); + notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; + tx.vout.push_back(notaryOut); + // sign it + uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); + tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); + CTransaction fundAlice(tx); + // now have Alice move some funds to Bob in the same block + CMutableTransaction aliceToBobMutable; + CTxIn aliceIn; + aliceIn.prevout.hash = fundAlice.GetHash(); + aliceIn.prevout.n = 0; + aliceToBobMutable.vin.push_back(aliceIn); + CTxOut bobOut; + bobOut.scriptPubKey = GetScriptForDestination(bob->GetPubKey()); + bobOut.nValue = 10000; + aliceToBobMutable.vout.push_back(bobOut); + CTxOut aliceRemainder; + aliceRemainder.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceRemainder.nValue = aliceOut.nValue - 10000; + aliceToBobMutable.vout.push_back(aliceRemainder); + hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); + aliceToBobMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); + CTransaction aliceToBobTx(aliceToBobMutable); + // alice attempts to double spend and send the same to charlie + CMutableTransaction aliceToCharlieMutable; + CTxIn aliceIn2; + aliceIn2.prevout.hash = fundAlice.GetHash(); + aliceIn2.prevout.n = 0; + aliceToCharlieMutable.vin.push_back(aliceIn2); + CTxOut charlieOut; + charlieOut.scriptPubKey = GetScriptForDestination(charlie->GetPubKey()); + charlieOut.nValue = 10000; + aliceToCharlieMutable.vout.push_back(charlieOut); + CTxOut aliceRemainder2; + aliceRemainder2.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); + aliceRemainder2.nValue = aliceOut.nValue - 10000; + aliceToCharlieMutable.vout.push_back(aliceRemainder2); + hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToCharlieMutable, 0, SIGHASH_ALL, 0, 0); + aliceToCharlieMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); + CTransaction aliceToCharlieTx(aliceToCharlieMutable); + // construct the block + CBlock block; + // first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // then the actual txs + block.vtx.push_back(fundAlice); + block.vtx.push_back(aliceToBobTx); + block.vtx.push_back(aliceToCharlieTx); + CValidationState state; + // create a new CBlockIndex to forward to ConnectBlock + auto index = chain.GetIndex(); + CBlockIndex newIndex; + newIndex.pprev = index; + EXPECT_FALSE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); + EXPECT_EQ(state.GetRejectReason(), "bad-txns-inputs-missingorspent"); +} + +TEST(block_tests, TestProcessBadBlock) +{ + TestChain chain; + auto notary = chain.AddWallet(chain.getNotaryKey()); + auto alice = chain.AddWallet(); + auto bob = chain.AddWallet(); + auto charlie = chain.AddWallet(); + CBlock lastBlock = chain.generateBlock(); // genesis block + // construct the block + CBlock block; + int32_t newHeight = chain.GetIndex()->GetHeight() + 1; + CValidationState state; + // no transactions + EXPECT_FALSE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); + EXPECT_EQ(state.GetRejectReason(), "bad-blk-length"); + // add first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // Add no PoW, should fail on merkle error + EXPECT_FALSE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); + EXPECT_EQ(state.GetRejectReason(), "bad-txnmrklroot"); +} \ No newline at end of file diff --git a/src/test-komodo/test_pow.cpp b/src/test-komodo/test_pow.cpp index ebe6ee0b500..b7a61976285 100644 --- a/src/test-komodo/test_pow.cpp +++ b/src/test-komodo/test_pow.cpp @@ -3,9 +3,6 @@ #include "chainparams.h" #include "pow.h" #include "random.h" -#include "testutils.h" -#include "komodo_extern_globals.h" -#include "consensus/validation.h" #include TEST(PoW, DifficultyAveraging) { @@ -149,232 +146,3 @@ TEST(PoW, MinDifficultyRules) { bnRes.GetCompact()); } - -TEST(PoW, TestStopAt) -{ - TestChain chain; - auto notary = chain.AddWallet(chain.getNotaryKey()); - CBlock lastBlock = chain.generateBlock(); // genesis block - ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); - lastBlock = chain.generateBlock(); // now we should be above 1 - ASSERT_GT( chain.GetIndex()->GetHeight(), 1); - CBlock block; - CValidationState state; - KOMODO_STOPAT = 1; - EXPECT_FALSE( ConnectBlock(block, state, chain.GetIndex(), *chain.GetCoinsViewCache(), false, true) ); -} - - -TEST(PoW, TestConnectWithoutChecks) -{ - TestChain chain; - auto notary = chain.AddWallet(chain.getNotaryKey()); - auto alice = chain.AddWallet(); - CBlock lastBlock = chain.generateBlock(); // genesis block - ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); - // Add some transaction to a block - int32_t newHeight = chain.GetIndex()->GetHeight() + 1; - auto notaryPrevOut = notary->GetAvailable(100000); - ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); - CMutableTransaction tx; - CTxIn notaryIn; - notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); - notaryIn.prevout.n = notaryPrevOut.second; - tx.vin.push_back(notaryIn); - CTxOut aliceOut; - aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceOut.nValue = 100000; - tx.vout.push_back(aliceOut); - CTxOut notaryOut; - notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); - notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; - tx.vout.push_back(notaryOut); - // sign it - uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); - tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); - CTransaction fundAlice(tx); - // construct the block - CBlock block; - // first a coinbase tx - auto consensusParams = Params().GetConsensus(); - CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); - txNew.vin.resize(1); - txNew.vin[0].prevout.SetNull(); - txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; - txNew.vout.resize(1); - txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); - txNew.nExpiryHeight = 0; - block.vtx.push_back(CTransaction(txNew)); - // then the actual tx - block.vtx.push_back(fundAlice); - CValidationState state; - // create a new CBlockIndex to forward to ConnectBlock - auto view = chain.GetCoinsViewCache(); - auto index = chain.GetIndex(); - CBlockIndex newIndex; - newIndex.pprev = index; - EXPECT_TRUE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); - if (!state.IsValid() ) - FAIL() << state.GetRejectReason(); -} - -TEST(PoW, TestSpendInSameBlock) -{ - TestChain chain; - auto notary = chain.AddWallet(chain.getNotaryKey()); - auto alice = chain.AddWallet(); - auto bob = chain.AddWallet(); - CBlock lastBlock = chain.generateBlock(); // genesis block - ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); - // Add some transaction to a block - int32_t newHeight = chain.GetIndex()->GetHeight() + 1; - auto notaryPrevOut = notary->GetAvailable(100000); - ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); - CMutableTransaction tx; - CTxIn notaryIn; - notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); - notaryIn.prevout.n = notaryPrevOut.second; - tx.vin.push_back(notaryIn); - CTxOut aliceOut; - aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceOut.nValue = 100000; - tx.vout.push_back(aliceOut); - CTxOut notaryOut; - notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); - notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; - tx.vout.push_back(notaryOut); - // sign it - uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); - tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); - CTransaction fundAlice(tx); - // now have Alice move some funds to Bob in the same block - CMutableTransaction aliceToBobMutable; - CTxIn aliceIn; - aliceIn.prevout.hash = fundAlice.GetHash(); - aliceIn.prevout.n = 0; - aliceToBobMutable.vin.push_back(aliceIn); - CTxOut bobOut; - bobOut.scriptPubKey = GetScriptForDestination(bob->GetPubKey()); - bobOut.nValue = 10000; - aliceToBobMutable.vout.push_back(bobOut); - CTxOut aliceRemainder; - aliceRemainder.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceRemainder.nValue = aliceOut.nValue - 10000; - aliceToBobMutable.vout.push_back(aliceRemainder); - hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); - aliceToBobMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); - CTransaction aliceToBobTx(aliceToBobMutable); - // construct the block - CBlock block; - // first a coinbase tx - auto consensusParams = Params().GetConsensus(); - CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); - txNew.vin.resize(1); - txNew.vin[0].prevout.SetNull(); - txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; - txNew.vout.resize(1); - txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); - txNew.nExpiryHeight = 0; - block.vtx.push_back(CTransaction(txNew)); - // then the actual txs - block.vtx.push_back(fundAlice); - block.vtx.push_back(aliceToBobTx); - CValidationState state; - // create a new CBlockIndex to forward to ConnectBlock - auto index = chain.GetIndex(); - CBlockIndex newIndex; - newIndex.pprev = index; - EXPECT_TRUE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); - if (!state.IsValid() ) - FAIL() << state.GetRejectReason(); -} - -TEST(PoW, TestDoubleSpendInSameBlock) -{ - TestChain chain; - auto notary = chain.AddWallet(chain.getNotaryKey()); - auto alice = chain.AddWallet(); - auto bob = chain.AddWallet(); - auto charlie = chain.AddWallet(); - CBlock lastBlock = chain.generateBlock(); // genesis block - ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); - // Add some transaction to a block - int32_t newHeight = chain.GetIndex()->GetHeight() + 1; - auto notaryPrevOut = notary->GetAvailable(100000); - ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); - CMutableTransaction tx; - CTxIn notaryIn; - notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); - notaryIn.prevout.n = notaryPrevOut.second; - tx.vin.push_back(notaryIn); - CTxOut aliceOut; - aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceOut.nValue = 100000; - tx.vout.push_back(aliceOut); - CTxOut notaryOut; - notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); - notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; - tx.vout.push_back(notaryOut); - // sign it - uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); - tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); - CTransaction fundAlice(tx); - // now have Alice move some funds to Bob in the same block - CMutableTransaction aliceToBobMutable; - CTxIn aliceIn; - aliceIn.prevout.hash = fundAlice.GetHash(); - aliceIn.prevout.n = 0; - aliceToBobMutable.vin.push_back(aliceIn); - CTxOut bobOut; - bobOut.scriptPubKey = GetScriptForDestination(bob->GetPubKey()); - bobOut.nValue = 10000; - aliceToBobMutable.vout.push_back(bobOut); - CTxOut aliceRemainder; - aliceRemainder.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceRemainder.nValue = aliceOut.nValue - 10000; - aliceToBobMutable.vout.push_back(aliceRemainder); - hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); - aliceToBobMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); - CTransaction aliceToBobTx(aliceToBobMutable); - // alice attempts to double spend and send the same to charlie - CMutableTransaction aliceToCharlieMutable; - CTxIn aliceIn2; - aliceIn2.prevout.hash = fundAlice.GetHash(); - aliceIn2.prevout.n = 0; - aliceToCharlieMutable.vin.push_back(aliceIn2); - CTxOut charlieOut; - charlieOut.scriptPubKey = GetScriptForDestination(charlie->GetPubKey()); - charlieOut.nValue = 10000; - aliceToCharlieMutable.vout.push_back(charlieOut); - CTxOut aliceRemainder2; - aliceRemainder2.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceRemainder2.nValue = aliceOut.nValue - 10000; - aliceToCharlieMutable.vout.push_back(aliceRemainder2); - hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToCharlieMutable, 0, SIGHASH_ALL, 0, 0); - aliceToCharlieMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); - CTransaction aliceToCharlieTx(aliceToCharlieMutable); - // construct the block - CBlock block; - // first a coinbase tx - auto consensusParams = Params().GetConsensus(); - CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); - txNew.vin.resize(1); - txNew.vin[0].prevout.SetNull(); - txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; - txNew.vout.resize(1); - txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); - txNew.nExpiryHeight = 0; - block.vtx.push_back(CTransaction(txNew)); - // then the actual txs - block.vtx.push_back(fundAlice); - block.vtx.push_back(aliceToBobTx); - block.vtx.push_back(aliceToCharlieTx); - CValidationState state; - // create a new CBlockIndex to forward to ConnectBlock - auto index = chain.GetIndex(); - CBlockIndex newIndex; - newIndex.pprev = index; - EXPECT_FALSE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); - EXPECT_EQ(state.GetRejectReason(), "bad-txns-inputs-missingorspent"); -} - From c096f6e82b5e3e8f54eb02f3a55e74e69f232b3d Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 9 Nov 2021 16:52:43 -0500 Subject: [PATCH 22/47] const in myAddtomempool --- src/cc/CCinclude.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc/CCinclude.h b/src/cc/CCinclude.h index 3f935564c05..35a5e72163e 100644 --- a/src/cc/CCinclude.h +++ b/src/cc/CCinclude.h @@ -300,7 +300,7 @@ bool myIsutxo_spentinmempool(uint256 &spenttxid,int32_t &spentvini,uint256 txid, * @param fSkipExpiry * @returns true on success */ -bool myAddtomempool(CTransaction &tx, CValidationState *pstate = nullptr, bool fSkipExpiry = false); +bool myAddtomempool(const CTransaction &tx, CValidationState *pstate = nullptr, bool fSkipExpiry = false); bool mytxid_inmempool(uint256 txid); int32_t myIsutxo_spent(uint256 &spenttxid,uint256 txid,int32_t vout); int32_t myGet_mempool_txs(std::vector &txs,uint8_t evalcode,uint8_t funcid); From 4cf000ae2a8a5c950e1d0738c11cbec2f223531f Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 10 Nov 2021 08:27:30 -0500 Subject: [PATCH 23/47] reverse iterate --- qa/pytest_komodo/ci_cleanup.sh | 5 +++++ src/main.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100755 qa/pytest_komodo/ci_cleanup.sh diff --git a/qa/pytest_komodo/ci_cleanup.sh b/qa/pytest_komodo/ci_cleanup.sh new file mode 100755 index 00000000000..a15baf38427 --- /dev/null +++ b/qa/pytest_komodo/ci_cleanup.sh @@ -0,0 +1,5 @@ +#!/bin/bash +rm -Rf node_0 +rm -Rf node_1 +rm -Rf __pycache__/ +rm TONYCI_7776 diff --git a/src/main.cpp b/src/main.cpp index 4fbe34e381a..148cba70450 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4549,7 +4549,7 @@ static bool ActivateBestChainStep(bool fSkipdpow, CValidationState &state, CBloc nHeight = nTargetHeight; // Connect new blocks. - for(CBlockIndex *pindexConnect : vpindexToConnect) + BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { if (!ConnectTip(state, pindexConnect, pindexConnect == pindexMostWork ? pblock : NULL)) { From 6d62418161727eb2cfca20e3ea84ec4cb0b29de3 Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 15 Nov 2021 09:43:05 -0500 Subject: [PATCH 24/47] More block tests --- src/chainparams.cpp | 2 - src/main.cpp | 52 +++++++----- src/miner.cpp | 95 ++++++++-------------- src/miner.h | 11 ++- src/rpc/mining.cpp | 95 ++++++++++++---------- src/test-komodo/test_block.cpp | 139 ++++++++++++++++++--------------- src/test-komodo/testutils.cpp | 16 +++- src/test-komodo/testutils.h | 16 +++- 8 files changed, 227 insertions(+), 199 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 8ce4b709712..94ee6e2f38a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -398,8 +398,6 @@ class CRegTestParams : public CChainParams { 1296688602, uint256S("0x0000000000000000000000000000000000000000000000000000000000000009"), ParseHex("01936b7db1eb4ac39f151b8704642d0a8bda13ec547d54cd5e43ba142fc6d8877cab07b3"), - - KOMODO_MINDIFF_NBITS, 4, 0); consensus.hashGenesisBlock = genesis.GetHash(); assert(consensus.hashGenesisBlock == uint256S("0x029f11d80ef9765602235e1bc9727e3eb6ba20839319f761fee920d63401e327")); diff --git a/src/main.cpp b/src/main.cpp index 148cba70450..34700e39813 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5218,25 +5218,29 @@ bool CheckBlock(int32_t *futureblockp, int32_t height, CBlockIndex *pindex, cons CTransaction sTx; CTransaction *ptx = nullptr; - if ( ASSETCHAINS_CC != 0 ) // CC contracts might refer to transactions in the current block, from a CC spend within the same block and out of order + // CC contracts might refer to transactions in the current block, from a + // CC spend within the same block and out of order + if ( ASSETCHAINS_CC != 0 ) { int32_t i,j,rejects=0,lastrejects=0; - // Copy all non Z-txs in mempool to temporary mempool because there can be tx in local mempool that make the block invalid. + // Copy all non Z-txs in mempool to temporary mempool because there can + // be tx in local mempool that make the block invalid. LOCK2(cs_main,mempool.cs); list transactionsToRemove; - BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) { + for(const CTxMemPoolEntry& e : mempool.mapTx) + { const CTransaction &tx = e.GetTx(); - const uint256 &hash = tx.GetHash(); - if ( tx.vjoinsplit.empty() && tx.vShieldedSpend.empty()) { + if ( tx.vjoinsplit.empty() && tx.vShieldedSpend.empty()) + { transactionsToRemove.push_back(tx); - tmpmempool.addUnchecked(hash,e,true); + tmpmempool.addUnchecked(tx.GetHash(),e,true); } } - BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) { + for(const CTransaction& tx : transactionsToRemove) { list removed; mempool.remove(tx, removed, false); } - // add all the txs in the block to the empty mempool. + // add all the txs in the block to the (somewhat) empty mempool. // CC validation shouldn't (can't) depend on the state of mempool! while ( true ) { @@ -5249,8 +5253,10 @@ bool CheckBlock(int32_t *futureblockp, int32_t height, CBlockIndex *pindex, cons || (i == block.vtx.size()-1 && komodo_isPoS((CBlock *)&block,height,0) != 0) ) continue; Tx = tx; - if ( myAddtomempool(Tx, &state, true) == false ) // happens with out of order tx in block on resync + if ( myAddtomempool(Tx, &state, true) == false ) { + // This happens with out of order tx in block on resync. + // take advantage of other checks, but if we were only rejected because it is a valid // staking transaction, sync with wallets and don't mark as a reject if (i == (block.vtx.size() - 1) && ASSETCHAINS_LWMAPOS && block.IsVerusPOSBlock() @@ -5267,8 +5273,6 @@ bool CheckBlock(int32_t *futureblockp, int32_t height, CBlockIndex *pindex, cons } if ( rejects == 0 || rejects == lastrejects ) { - if ( 0 && lastrejects != 0 ) - fprintf(stderr,"lastrejects.%d -> all tx in mempool\n",lastrejects); break; } lastrejects = rejects; @@ -5289,7 +5293,7 @@ bool CheckBlock(int32_t *futureblockp, int32_t height, CBlockIndex *pindex, cons } unsigned int nSigOps = 0; - BOOST_FOREACH(const CTransaction& tx, block.vtx) + for(const CTransaction& tx : block.vtx) { nSigOps += GetLegacySigOpCount(tx); } @@ -5298,9 +5302,6 @@ bool CheckBlock(int32_t *futureblockp, int32_t height, CBlockIndex *pindex, cons REJECT_INVALID, "bad-blk-sigops", true); if ( fCheckPOW && komodo_check_deposit(height,block,(pindex==0||pindex->pprev==0)?0:pindex->pprev->nTime) < 0 ) { - //static uint32_t counter; - //if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 ) - // fprintf(stderr,"check deposit rejection\n"); LogPrintf("CheckBlockHeader komodo_check_deposit error"); return(false); } @@ -5314,13 +5315,12 @@ bool CheckBlock(int32_t *futureblockp, int32_t height, CBlockIndex *pindex, cons { LOCK2(cs_main,mempool.cs); // here we add back all txs from the temp mempool to the main mempool. - BOOST_FOREACH(const CTxMemPoolEntry& e, tmpmempool.mapTx) + for(const CTxMemPoolEntry& e : tmpmempool.mapTx) { const CTransaction &tx = e.GetTx(); const uint256 &hash = tx.GetHash(); mempool.addUnchecked(hash,e,true); } - //fprintf(stderr, "finished adding back. mempoolsize.%ld\n",mempool.size()); // empty the temp mempool for next time. tmpmempool.clear(); } @@ -5556,7 +5556,18 @@ bool AcceptBlockHeader(int32_t *futureblockp,const CBlockHeader& block, CValidat uint256 Queued_reconsiderblock; -bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool fRequested, CDiskBlockPos* dbp) +/***** + * @brief + * @param futureblockp + * @param block + * @param state + * @param ppindex + * @param fRequested + * @param dbp + * @returns true if block accepted + */ +bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, CBlockIndex** ppindex, + bool fRequested, CDiskBlockPos* dbp) { const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); @@ -5576,7 +5587,6 @@ bool AcceptBlock(int32_t *futureblockp,CBlock& block, CValidationState& state, C *futureblockp = true; return false; } - //fprintf(stderr,"acceptblockheader passed\n"); // Try to process all requested blocks that we don't have, but only // process an unrequested block if it's new and has enough work to // advance our tip, and isn't too many blocks ahead. @@ -5815,12 +5825,12 @@ bool ProcessNewBlock(bool from_miner, int32_t height, CValidationState &state, C // Store to disk CBlockIndex *pindex = NULL; - bool ret = AcceptBlock(&futureblock,*pblock, state, &pindex, fRequested, dbp); + bool accepted = AcceptBlock(&futureblock,*pblock, state, &pindex, fRequested, dbp); if (pindex && pfrom) { mapBlockSource[pindex->GetBlockHash()] = pfrom->GetId(); } CheckBlockIndex(); - if (!ret && futureblock == 0) + if (!accepted && futureblock == 0) { komodo_longestchain(); return error("%s: AcceptBlock FAILED", __func__); diff --git a/src/miner.cpp b/src/miner.cpp index 28a7a62a1b0..29ae63637a7 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -186,7 +186,15 @@ int32_t komodo_waituntilelegible(uint32_t blocktime, int32_t stakeHeight, uint32 return(1); } -CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake) +/***** + * @breif Generate a new block based on mempool txs, without valid proof-of-work + * @param _pk the public key + * @param _scriptPubKeyIn the script for the public key + * @param gpucount assists in calculating the block's nTime + * @param isStake + * @returns the block template + */ +CBlockTemplate* CreateNewBlock(const CPubKey _pk, const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake) { CScript scriptPubKeyIn(_scriptPubKeyIn); @@ -916,49 +924,6 @@ CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& _scriptPubKeyIn, int32 return pblocktemplate.release(); } -/* - #ifdef ENABLE_WALLET - boost::optional GetMinerScriptPubKey(CReserveKey& reservekey) - #else - boost::optional GetMinerScriptPubKey() - #endif - { - CKeyID keyID; - CBitcoinAddress addr; - if (addr.SetString(GetArg("-mineraddress", ""))) { - addr.GetKeyID(keyID); - } else { - #ifdef ENABLE_WALLET - CPubKey pubkey; - if (!reservekey.GetReservedKey(pubkey)) { - return boost::optional(); - } - keyID = pubkey.GetID(); - #else - return boost::optional(); - #endif - } - - CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; - return scriptPubKey; - } - - #ifdef ENABLE_WALLET - CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey) - { - boost::optional scriptPubKey = GetMinerScriptPubKey(reservekey); - #else - CBlockTemplate* CreateNewBlockWithKey() - { - boost::optional scriptPubKey = GetMinerScriptPubKey(); - #endif - - if (!scriptPubKey) { - return NULL; - } - return CreateNewBlock(*scriptPubKey); - }*/ - ////////////////////////////////////////////////////////////////////////////// // // Internal miner @@ -991,6 +956,14 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& // Internal miner // +/***** + * Create a new block + * @param reserveKey + * @param nHeight + * @param gpucount + * @param isStake + * @returns the block template + */ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake) { CPubKey pubkey; CScript scriptPubKey; uint8_t *script,*ptr; int32_t i,len; @@ -1012,30 +985,26 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, } else if ( USE_EXTERNAL_PUBKEY != 0 ) { - //fprintf(stderr,"use notary pubkey\n"); pubkey = ParseHex(NOTARY_PUBKEY); scriptPubKey = CScript() << ParseHex(HexStr(pubkey)) << OP_CHECKSIG; } else { - //if ( !isStake || ASSETCHAINS_STAKED != 0 ) - { - if (!GetBoolArg("-disablewallet", false)) { - // wallet enabled - if (!reservekey.GetReservedKey(pubkey)) - return NULL; - scriptPubKey.clear(); - scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; - } else { - // wallet disabled - CTxDestination dest = DecodeDestination(GetArg("-mineraddress", "")); - if (IsValidDestination(dest)) { - // CKeyID keyID = boost::get(dest); - // scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; - scriptPubKey = GetScriptForDestination(dest); - } else - return NULL; - } + if (!GetBoolArg("-disablewallet", false)) { + // wallet enabled + if (!reservekey.GetReservedKey(pubkey)) + return NULL; + scriptPubKey.clear(); + scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; + } else { + // wallet disabled + CTxDestination dest = DecodeDestination(GetArg("-mineraddress", "")); + if (IsValidDestination(dest)) { + // CKeyID keyID = boost::get(dest); + // scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG; + scriptPubKey = GetScriptForDestination(dest); + } else + return NULL; } } return CreateNewBlock(pubkey, scriptPubKey, gpucount, isStake); diff --git a/src/miner.h b/src/miner.h index a3bedd29204..3d2cf4d32cc 100644 --- a/src/miner.h +++ b/src/miner.h @@ -42,8 +42,15 @@ struct CBlockTemplate }; #define KOMODO_MAXGPUCOUNT 65 -/** Generate a new block, without valid proof-of-work */ -CBlockTemplate* CreateNewBlock(CPubKey _pk,const CScript& scriptPubKeyIn, int32_t gpucount, bool isStake = false); +/***** + * @breif Generate a new block based on mempool txs, without valid proof-of-work + * @param _pk the public key + * @param _scriptPubKeyIn the script for the public key + * @param gpucount assists in calculating the block's nTime + * @param isStake + * @returns the block template + */ +CBlockTemplate* CreateNewBlock(const CPubKey _pk,const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake = false); #ifdef ENABLE_WALLET boost::optional GetMinerScriptPubKey(CReserveKey& reservekey); CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake = false); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index d2e891556c2..d6036920c9f 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -196,6 +196,58 @@ UniValue getgenerate(const UniValue& params, bool fHelp, const CPubKey& mypk) extern uint8_t NOTARY_PUBKEY33[33]; +/***** + * Calculate the PoW value for a block + * @param pblock the block to work on + * @returns true when the PoW is completed + */ +bool CalcPoW(CBlock *pblock) +{ + unsigned int n = Params().EquihashN(); + unsigned int k = Params().EquihashK(); + // Hash state + crypto_generichash_blake2b_state eh_state; + EhInitialiseState(n, k, eh_state); + + // I = the block header minus nonce and solution. + CEquihashInput I{*pblock}; + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << I; + + // H(I||... + crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size()); + + while (true) { + // Yes, there is a chance every nonce could fail to satisfy the -regtest + // target -- 1 in 2^(2^256). That ain't gonna happen + pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); + + // H(I||V||... + crypto_generichash_blake2b_state curr_state; + curr_state = eh_state; + crypto_generichash_blake2b_update(&curr_state, + pblock->nNonce.begin(), + pblock->nNonce.size()); + + // (x_1, x_2, ...) = A(I, V, n, k) + std::function)> validBlock = + [&pblock](std::vector soln) + { + LOCK(cs_main); + pblock->nSolution = soln; + solutionTargetChecks.increment(); + return CheckProofOfWork(*pblock,NOTARY_PUBKEY33,chainActive.Height(),Params().GetConsensus()); + }; + bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock); + ehSolverRuns.increment(); + if (found) { + return true; + } + } + // this should never get hit + return false; +} + //Value generate(const Array& params, bool fHelp) UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk) { @@ -252,8 +304,6 @@ UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk) } unsigned int nExtraNonce = 0; UniValue blockHashes(UniValue::VARR); - unsigned int n = Params().EquihashN(); - unsigned int k = Params().EquihashK(); uint64_t lastTime = 0; while (nHeight < nHeightEnd) { @@ -274,46 +324,7 @@ UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk) IncrementExtraNonce(pblock, chainActive.LastTip(), nExtraNonce); } - // Hash state - crypto_generichash_blake2b_state eh_state; - EhInitialiseState(n, k, eh_state); - - // I = the block header minus nonce and solution. - CEquihashInput I{*pblock}; - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << I; - - // H(I||... - crypto_generichash_blake2b_update(&eh_state, (unsigned char*)&ss[0], ss.size()); - - while (true) { - // Yes, there is a chance every nonce could fail to satisfy the -regtest - // target -- 1 in 2^(2^256). That ain't gonna happen - pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); - - // H(I||V||... - crypto_generichash_blake2b_state curr_state; - curr_state = eh_state; - crypto_generichash_blake2b_update(&curr_state, - pblock->nNonce.begin(), - pblock->nNonce.size()); - - // (x_1, x_2, ...) = A(I, V, n, k) - std::function)> validBlock = - [&pblock](std::vector soln) - { - LOCK(cs_main); - pblock->nSolution = soln; - solutionTargetChecks.increment(); - return CheckProofOfWork(*pblock,NOTARY_PUBKEY33,chainActive.Height(),Params().GetConsensus()); - }; - bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock); - ehSolverRuns.increment(); - if (found) { - goto endloop; - } - } -endloop: + CalcPoW(pblock); // add PoW CValidationState state; if (!ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1,state, NULL, pblock, true, NULL)) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); diff --git a/src/test-komodo/test_block.cpp b/src/test-komodo/test_block.cpp index 812a0c653ba..e06474699d8 100644 --- a/src/test-komodo/test_block.cpp +++ b/src/test-komodo/test_block.cpp @@ -2,6 +2,7 @@ #include "testutils.h" #include "komodo_extern_globals.h" #include "consensus/validation.h" +#include "miner.h" #include @@ -29,6 +30,7 @@ TEST(block_tests, TestStopAt) CValidationState state; KOMODO_STOPAT = 1; EXPECT_FALSE( ConnectBlock(block, state, chain.GetIndex(), *chain.GetCoinsViewCache(), false, true) ); + KOMODO_STOPAT = 0; // to not stop other tests } TEST(block_tests, TestConnectWithoutChecks) @@ -40,25 +42,7 @@ TEST(block_tests, TestConnectWithoutChecks) ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); // Add some transaction to a block int32_t newHeight = chain.GetIndex()->GetHeight() + 1; - auto notaryPrevOut = notary->GetAvailable(100000); - ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); - CMutableTransaction tx; - CTxIn notaryIn; - notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); - notaryIn.prevout.n = notaryPrevOut.second; - tx.vin.push_back(notaryIn); - CTxOut aliceOut; - aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceOut.nValue = 100000; - tx.vout.push_back(aliceOut); - CTxOut notaryOut; - notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); - notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; - tx.vout.push_back(notaryOut); - // sign it - uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); - tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); - CTransaction fundAlice(tx); + CTransaction fundAlice = notary->CreateSpendTransaction(alice, 100000); // construct the block CBlock block; // first a coinbase tx @@ -92,27 +76,9 @@ TEST(block_tests, TestSpendInSameBlock) auto bob = chain.AddWallet(); CBlock lastBlock = chain.generateBlock(); // genesis block ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); - // Add some transaction to a block + // Start to build a block int32_t newHeight = chain.GetIndex()->GetHeight() + 1; - auto notaryPrevOut = notary->GetAvailable(100000); - ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); - CMutableTransaction tx; - CTxIn notaryIn; - notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); - notaryIn.prevout.n = notaryPrevOut.second; - tx.vin.push_back(notaryIn); - CTxOut aliceOut; - aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceOut.nValue = 100000; - tx.vout.push_back(aliceOut); - CTxOut notaryOut; - notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); - notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; - tx.vout.push_back(notaryOut); - // sign it - uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); - tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); - CTransaction fundAlice(tx); + CTransaction fundAlice = notary->CreateSpendTransaction(alice, 100000); // now have Alice move some funds to Bob in the same block CMutableTransaction aliceToBobMutable; CTxIn aliceIn; @@ -125,9 +91,9 @@ TEST(block_tests, TestSpendInSameBlock) aliceToBobMutable.vout.push_back(bobOut); CTxOut aliceRemainder; aliceRemainder.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceRemainder.nValue = aliceOut.nValue - 10000; + aliceRemainder.nValue = fundAlice.vout[0].nValue - 10000; aliceToBobMutable.vout.push_back(aliceRemainder); - hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); + uint256 hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); aliceToBobMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); CTransaction aliceToBobTx(aliceToBobMutable); // construct the block @@ -164,27 +130,9 @@ TEST(block_tests, TestDoubleSpendInSameBlock) auto charlie = chain.AddWallet(); CBlock lastBlock = chain.generateBlock(); // genesis block ASSERT_GT( chain.GetIndex()->GetHeight(), 0 ); - // Add some transaction to a block + // Start to build a block int32_t newHeight = chain.GetIndex()->GetHeight() + 1; - auto notaryPrevOut = notary->GetAvailable(100000); - ASSERT_TRUE(notaryPrevOut.first.vout.size() > 0); - CMutableTransaction tx; - CTxIn notaryIn; - notaryIn.prevout.hash = notaryPrevOut.first.GetHash(); - notaryIn.prevout.n = notaryPrevOut.second; - tx.vin.push_back(notaryIn); - CTxOut aliceOut; - aliceOut.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceOut.nValue = 100000; - tx.vout.push_back(aliceOut); - CTxOut notaryOut; - notaryOut.scriptPubKey = GetScriptForDestination(notary->GetPubKey()); - notaryOut.nValue = notaryPrevOut.first.vout[notaryPrevOut.second].nValue - 100000; - tx.vout.push_back(notaryOut); - // sign it - uint256 hash = SignatureHash(notaryPrevOut.first.vout[notaryPrevOut.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); - tx.vin[0].scriptSig << notary->Sign(hash, SIGHASH_ALL); - CTransaction fundAlice(tx); + CTransaction fundAlice = notary->CreateSpendTransaction(alice, 100000); // now have Alice move some funds to Bob in the same block CMutableTransaction aliceToBobMutable; CTxIn aliceIn; @@ -197,12 +145,12 @@ TEST(block_tests, TestDoubleSpendInSameBlock) aliceToBobMutable.vout.push_back(bobOut); CTxOut aliceRemainder; aliceRemainder.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceRemainder.nValue = aliceOut.nValue - 10000; + aliceRemainder.nValue = fundAlice.vout[0].nValue - 10000; aliceToBobMutable.vout.push_back(aliceRemainder); - hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); + uint256 hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); aliceToBobMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); CTransaction aliceToBobTx(aliceToBobMutable); - // alice attempts to double spend and send the same to charlie + // alice attempts to double spend the vout and send something to charlie CMutableTransaction aliceToCharlieMutable; CTxIn aliceIn2; aliceIn2.prevout.hash = fundAlice.GetHash(); @@ -214,7 +162,7 @@ TEST(block_tests, TestDoubleSpendInSameBlock) aliceToCharlieMutable.vout.push_back(charlieOut); CTxOut aliceRemainder2; aliceRemainder2.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceRemainder2.nValue = aliceOut.nValue - 10000; + aliceRemainder2.nValue = fundAlice.vout[0].nValue - 10000; aliceToCharlieMutable.vout.push_back(aliceRemainder2); hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToCharlieMutable, 0, SIGHASH_ALL, 0, 0); aliceToCharlieMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); @@ -244,6 +192,61 @@ TEST(block_tests, TestDoubleSpendInSameBlock) EXPECT_EQ(state.GetRejectReason(), "bad-txns-inputs-missingorspent"); } +bool CalcPoW(CBlock *pblock); + +TEST(block_tests, TestProcessBlock) +{ + TestChain chain; + EXPECT_EQ(chain.GetIndex()->GetHeight(), 0); + auto notary = chain.AddWallet(chain.getNotaryKey()); + auto alice = chain.AddWallet(); + auto bob = chain.AddWallet(); + auto charlie = chain.AddWallet(); + CBlock lastBlock = chain.generateBlock(); // gives notary everything + EXPECT_EQ(chain.GetIndex()->GetHeight(), 1); + chain.IncrementChainTime(); + auto notaryPrevOut = notary->GetAvailable(100000); + // add a transaction to the mempool + CTransaction fundAlice = notary->CreateSpendTransaction(alice, 100000); + EXPECT_TRUE( chain.acceptTx(fundAlice).IsValid() ); + // construct the block + CBlock block; + int32_t newHeight = chain.GetIndex()->GetHeight() + 1; + CValidationState state; + // no transactions + EXPECT_FALSE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); + EXPECT_EQ(state.GetRejectReason(), "bad-blk-length"); + EXPECT_EQ(chain.GetIndex()->GetHeight(), 1); + // add first a coinbase tx + auto consensusParams = Params().GetConsensus(); + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); + txNew.vin.resize(1); + txNew.vin[0].prevout.SetNull(); + txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; + txNew.vout.resize(1); + txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); + txNew.nExpiryHeight = 0; + block.vtx.push_back(CTransaction(txNew)); + // no PoW, no merkle root should fail on merkle error + EXPECT_FALSE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); + EXPECT_EQ(state.GetRejectReason(), "bad-txnmrklroot"); + // Verify transaction is still in mempool + EXPECT_EQ(mempool.size(), 1); + // finish constructing the block + block.nBits = GetNextWorkRequired( chain.GetIndex(), &block, Params().GetConsensus()); + block.nTime = GetTime(); + block.hashPrevBlock = lastBlock.GetHash(); + block.hashMerkleRoot = block.BuildMerkleTree(); + // Add the PoW + EXPECT_TRUE(CalcPoW(&block)); + state = CValidationState(); + EXPECT_TRUE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); + if (!state.IsValid()) + FAIL() << state.GetRejectReason(); + // Verify transaction is still in mempool + EXPECT_EQ(mempool.size(), 1); +} + TEST(block_tests, TestProcessBadBlock) { TestChain chain; @@ -252,6 +255,10 @@ TEST(block_tests, TestProcessBadBlock) auto bob = chain.AddWallet(); auto charlie = chain.AddWallet(); CBlock lastBlock = chain.generateBlock(); // genesis block + auto notaryPrevOut = notary->GetAvailable(100000); + // add a transaction to the mempool + CTransaction fundAlice = notary->CreateSpendTransaction(alice, 100000); + EXPECT_TRUE( chain.acceptTx(fundAlice).IsValid() ); // construct the block CBlock block; int32_t newHeight = chain.GetIndex()->GetHeight() + 1; @@ -272,4 +279,6 @@ TEST(block_tests, TestProcessBadBlock) // Add no PoW, should fail on merkle error EXPECT_FALSE( ProcessNewBlock(false, newHeight, state, nullptr, &block, false, nullptr) ); EXPECT_EQ(state.GetRejectReason(), "bad-txnmrklroot"); + // Verify transaction is still in mempool + EXPECT_EQ(mempool.size(), 1); } \ No newline at end of file diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index 23b6a0ebc5c..9baff2339d3 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -203,6 +203,11 @@ CBlockIndex *TestChain::GetIndex(uint32_t height) } +void TestChain::IncrementChainTime() +{ + SetMockTime(nMockTime += 100); +} + CCoinsViewCache *TestChain::GetCoinsViewCache() { return pcoinsTip; @@ -353,6 +358,12 @@ void TestWallet::AddOut(CTransaction tx, uint32_t n) * @returns the results */ CValidationState TestWallet::Transfer(std::shared_ptr to, CAmount amount, CAmount fee) +{ + CTransaction fundTo(CreateSpendTransaction(to, amount, fee)); + return chain->acceptTx(fundTo); +} + +CTransaction TestWallet::CreateSpendTransaction(std::shared_ptr to, CAmount amount, CAmount fee) { std::pair available = GetAvailable(amount + fee); CMutableTransaction tx; @@ -364,7 +375,7 @@ CValidationState TestWallet::Transfer(std::shared_ptr to, CAmount am out1.scriptPubKey = GetScriptForDestination(to->GetPubKey()); out1.nValue = amount; tx.vout.push_back(out1); - // give the rest back to the notary + // give the rest back to wallet owner CTxOut out2; out2.scriptPubKey = GetScriptForDestination(key.GetPubKey()); out2.nValue = available.first.vout[available.second].nValue - amount - fee; @@ -373,6 +384,5 @@ CValidationState TestWallet::Transfer(std::shared_ptr to, CAmount am uint256 hash = SignatureHash(available.first.vout[available.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); tx.vin[0].scriptSig << Sign(hash, SIGHASH_ALL); - CTransaction fundTo(tx); - return chain->acceptTx(fundTo); + return CTransaction(tx); } diff --git a/src/test-komodo/testutils.h b/src/test-komodo/testutils.h index a976c403073..c1a02a38053 100644 --- a/src/test-komodo/testutils.h +++ b/src/test-komodo/testutils.h @@ -63,6 +63,12 @@ class TestChain * @returns the block generated */ CBlock generateBlock(); + /**** + * @brief set the chain time to something reasonable + * @note must be called after generateBlock if you + * want to produce another block + */ + void IncrementChainTime(); /*** * @returns the notary's key */ @@ -139,8 +145,16 @@ class TestWallet * @param n the n value of the vout */ void AddOut(CTransaction tx, uint32_t n); + /***** + * @brief create a transaction with 1 recipient (signed) + * @param to who to send funds to + * @param amount + * @param fee + * @returns the transaction + */ + CTransaction CreateSpendTransaction(std::shared_ptr to, CAmount amount, CAmount fee = 0); /*** - * Transfer to another user + * Transfer to another user (sends to mempool) * @param to who to transfer to * @param amount the amount * @returns the results From 6d87cceccd95d366f01fe01f9a42ba3320371b1b Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 2 Feb 2022 12:00:34 -0500 Subject: [PATCH 25/47] Notary tests --- src/Makefile.ktest.include | 1 + src/komodo_notary.cpp | 40 ++++++-- src/notaries_staked.cpp | 17 +++- src/test-komodo/test_notary.cpp | 165 ++++++++++++++++++++++++++++++++ 4 files changed, 212 insertions(+), 11 deletions(-) create mode 100644 src/test-komodo/test_notary.cpp diff --git a/src/Makefile.ktest.include b/src/Makefile.ktest.include index 04852a8beb7..4deffa5ae78 100644 --- a/src/Makefile.ktest.include +++ b/src/Makefile.ktest.include @@ -22,6 +22,7 @@ komodo_test_SOURCES = \ test-komodo/test_random.cpp \ test-komodo/test_block.cpp \ test-komodo/test_mempool.cpp \ + test-komodo/test_notary.cpp \ test-komodo/test_pow.cpp \ test-komodo/test_txid.cpp \ test-komodo/test_coins.cpp \ diff --git a/src/komodo_notary.cpp b/src/komodo_notary.cpp index e6605bc0b80..472d34da10b 100644 --- a/src/komodo_notary.cpp +++ b/src/komodo_notary.cpp @@ -81,17 +81,43 @@ int32_t getacseason(uint32_t timestamp) return(0); } +/*** + * Static variables to tell if something has been initialized + */ +static bool didinit_NOTARIES[NUM_KMD_SEASONS]; // komodo_notaries() +static int32_t hwmheight = 0; // komodo_notariesinit() +static bool didinit = false; // komodo_init() + +/***** + * 2 Helpers for unit tests that reset statics (among other things) + * DO NOT USE for anything other than unit tests + */ +void undo_init_STAKED(); // see notaries_staked.cpp +void undo_init_notaries() +{ + undo_init_STAKED(); + memset(didinit_NOTARIES, 0, NUM_KMD_SEASONS * sizeof(bool) ); + if (Pubkeys != nullptr) + { + free(Pubkeys); + Pubkeys = nullptr; + } + hwmheight = 0; + didinit = false; +} + int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestamp) { int32_t i,htind,n; uint64_t mask = 0; struct knotary_entry *kp,*tmp; - static uint8_t kmd_pubkeys[NUM_KMD_SEASONS][64][33],didinit[NUM_KMD_SEASONS]; + static uint8_t kmd_pubkeys[NUM_KMD_SEASONS][64][33]; if ( timestamp == 0 && ASSETCHAINS_SYMBOL[0] != 0 ) timestamp = komodo_heightstamp(height); else if ( ASSETCHAINS_SYMBOL[0] == 0 ) timestamp = 0; - // If this chain is not a staked chain, use the normal Komodo logic to determine notaries. This allows KMD to still sync and use its proper pubkeys for dPoW. + // If this chain is not a staked chain, use the normal Komodo logic to determine notaries. + // This allows KMD to still sync and use its proper pubkeys for dPoW. if ( is_STAKED(ASSETCHAINS_SYMBOL) == 0 ) { int32_t kmd_season = 0; @@ -108,7 +134,7 @@ int32_t komodo_notaries(uint8_t pubkeys[64][33],int32_t height,uint32_t timestam } if ( kmd_season != 0 ) { - if ( didinit[kmd_season-1] == 0 ) + if ( !didinit_NOTARIES[kmd_season-1] ) { for (i=0; i= 0 ) @@ -499,7 +523,7 @@ void komodo_init(int32_t height) } komodo_notarysinit(0,pubkeys,k); } - didinit = 1; + didinit = true; komodo_stateupdate(0,0,0,0,zero,0,0,0,0,0,0,0,0,0,0,zero,0); } } diff --git a/src/notaries_staked.cpp b/src/notaries_staked.cpp index 0a804db2083..6b5ad4a1769 100644 --- a/src/notaries_staked.cpp +++ b/src/notaries_staked.cpp @@ -9,12 +9,23 @@ extern pthread_mutex_t staked_mutex; +static bool doneinit_STAKED = false; + +/***** + * Reset the doneinit static (for unit testing) + */ +void undo_init_STAKED() +{ + doneinit_STAKED = false; +} + + int8_t is_STAKED(const char *chain_name) { - static int8_t STAKED,doneinit; + static int8_t STAKED; if ( chain_name[0] == 0 ) return(0); - if (doneinit == 1 && ASSETCHAINS_SYMBOL[0] != 0) + if (doneinit_STAKED && ASSETCHAINS_SYMBOL[0] != 0) return(STAKED); else STAKED = 0; if ( (strcmp(chain_name, "LABS") == 0) ) @@ -27,7 +38,7 @@ int8_t is_STAKED(const char *chain_name) STAKED = 4; // These chains are for testing consensus to create a chain etc. Not meant to be actually used for anything important. else if ( (strcmp(chain_name, "THIS_CHAIN_IS_BANNED") == 0) ) STAKED = 255; // Any chain added to this group is banned, no notarisations are valid, as a consensus rule. Can be used to remove a chain from cluster if needed. - doneinit = 1; + doneinit_STAKED = true; return(STAKED); }; diff --git a/src/test-komodo/test_notary.cpp b/src/test-komodo/test_notary.cpp new file mode 100644 index 00000000000..fc93d6dad26 --- /dev/null +++ b/src/test-komodo/test_notary.cpp @@ -0,0 +1,165 @@ +#include "testutils.h" +#include "chainparams.h" +#include "komodo_notary.h" + +#include + +void undo_init_notaries(); // test helper + +namespace TestNotary +{ + +/*** + * A little class to help with the different formats keys come in + */ +class my_key +{ +public: + my_key(uint8_t in[33]) + { + for(int i = 0; i < 33; ++i) + key.push_back(in[i]); + } + my_key(const std::string& in) + { + for(int i = 0; i < 33; ++i) + key.push_back( + (unsigned int)strtol(in.substr(i*2, 2).c_str(), nullptr, 16) ); + } + bool fill(uint8_t in[33]) + { + memcpy(in, key.data(), 33); + return true; + } +private: + std::vector key; + friend bool operator==(const my_key& lhs, const my_key& rhs); +}; + +bool operator==(const my_key& lhs, const my_key& rhs) +{ + if (lhs.key == rhs.key) + return true; + return false; +} + +TEST(TestNotary, KomodoNotaries) +{ + // Test komodo_notaries(), getkmdseason() + ASSETCHAINS_SYMBOL[0] = 0; + undo_init_notaries(); + uint8_t pubkeys[64][33]; + int32_t height = 0; + uint32_t timestamp = 0; + // Get the pubkeys of the first era + int32_t result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 35); + // the first notary didn't change between era 1 and 2, so look at the 2nd notary + EXPECT_EQ( my_key(pubkeys[1]), my_key("02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344")); + // make sure the era hasn't changed before it is supposed to + for(;height <= 179999; ++height) + { + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 35); + EXPECT_EQ( getkmdseason(height), 1); + EXPECT_EQ( my_key(pubkeys[1]), my_key("02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344")); + } + EXPECT_EQ(height, 180000); + // at 180000 we start using notaries_elected(komodo_defs.h) instead of Notaries_genesis(komodo_notary.cpp) + for(;height <= 814000; ++height) + { + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 64); + EXPECT_EQ( getkmdseason(height), 1); + EXPECT_EQ( my_key(pubkeys[1]), my_key("02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344")); + } + // make sure the era changes when it was supposed to, and we have a new key + EXPECT_EQ(height, 814001); + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 64); + EXPECT_EQ( getkmdseason(height), 2); + EXPECT_EQ( my_key(pubkeys[1]), my_key("030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961") ); + + // now try the same thing with notaries_staked, which uses timestamp instead of height + // NOTE: If height is passed instead of timestamp, the timestamp is computed based on block timestamps + // notaries come from notaries_STAKED(notaries_staked.h) + // also tests STAKED_era() + height = 0; + timestamp = 1; + undo_init_notaries(); + strcpy(ASSETCHAINS_SYMBOL, "LABS"); + // we should be in era 1 now + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 22); + EXPECT_EQ( STAKED_era(timestamp), 1); + EXPECT_EQ( my_key(pubkeys[13]), my_key("03669457b2934d98b5761121dd01b243aed336479625b293be9f8c43a6ae7aaeff")); + timestamp = 1572523200; + EXPECT_EQ(result, 22); + EXPECT_EQ( STAKED_era(timestamp), 1); + EXPECT_EQ( my_key(pubkeys[13]), my_key("03669457b2934d98b5761121dd01b243aed336479625b293be9f8c43a6ae7aaeff")); + // Moving to era 2 should change the notaries. But there is a gap of 777 that uses komodo notaries for some reason + // (NOTE: the first 12 are the same, so use the 13th) + timestamp++; + EXPECT_EQ(timestamp, 1572523201); + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 64); + EXPECT_EQ( STAKED_era(timestamp), 0); + EXPECT_EQ( pubkeys[13][0], 0); + // advance past the gap + timestamp += 778; + result = komodo_notaries(pubkeys, height, timestamp); + EXPECT_EQ(result, 24); + EXPECT_EQ( STAKED_era(timestamp), 2); + EXPECT_EQ( my_key(pubkeys[13]), my_key("02d1dd4c5d5c00039322295aa965f9787a87d234ed4f8174231bbd6162e384eba8")); + + // now test getacseason() + EXPECT_EQ( getacseason(0), 1); + EXPECT_EQ( getacseason(1), 1); + EXPECT_EQ( getacseason(1525132800), 1); + EXPECT_EQ( getacseason(1525132801), 2); + EXPECT_EQ( getacseason(1751328000), 6); + EXPECT_EQ( getacseason(1751328001), 0); + + // cleanup + undo_init_notaries(); +} + +TEST(TestNotary, ElectedNotary) +{ + // exercise the routine that checks to see if a particular public key is a notary at the current height + + // setup + undo_init_notaries(); + my_key first_era("02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344"); + my_key second_era("030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961"); + + int32_t numnotaries; + uint8_t pubkey[33]; + first_era.fill(pubkey); + int32_t height = 0; + uint32_t timestamp = 0; + + // check the KMD chain, first era + ASSETCHAINS_SYMBOL[0] = 0; + int32_t result = komodo_electednotary(&numnotaries, pubkey, height, timestamp); + EXPECT_EQ(result, 1); + EXPECT_EQ( numnotaries, 35); + // now try a wrong key + second_era.fill(pubkey); + result = komodo_electednotary(&numnotaries, pubkey, height, timestamp); + EXPECT_EQ(result, -1); + EXPECT_EQ(numnotaries, 35); + + // KMD chain, second era + height = 814001; + result = komodo_electednotary(&numnotaries, pubkey, height, timestamp); + EXPECT_EQ(result, 1); + EXPECT_EQ( numnotaries, 64); + // now try a wrong key + first_era.fill(pubkey); + result = komodo_electednotary(&numnotaries, pubkey, height, timestamp); + EXPECT_EQ(result, -1); + EXPECT_EQ(numnotaries, 64); +} + +} // namespace TestNotary \ No newline at end of file From ee02430a09773720c181190e3008dde3bf392623 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 21 Sep 2021 11:18:15 -0500 Subject: [PATCH 26/47] allow debug builds --- .gitignore | 2 +- depends/hosts/linux.mk | 5 +- qa/pytest_komodo/chainconfig.json | 4 +- src/Makefile.am | 53 ++-- src/cryptoconditions/Makefile.am | 4 +- src/komodo_defs.h | 423 +---------------------------- src/komodo_globals.h | 1 + src/komodo_hardfork.h | 425 ++++++++++++++++++++++++++++++ src/komodo_notary.h | 1 + src/leveldb/Makefile | 12 +- src/notaries_staked.cpp | 1 + src/secp256k1/Makefile.am | 4 +- src/snark/Makefile | 10 +- zcutil/build-mac.sh | 9 +- zcutil/build.sh | 24 +- 15 files changed, 483 insertions(+), 495 deletions(-) create mode 100644 src/komodo_hardfork.h diff --git a/.gitignore b/.gitignore index 2f85c6d195f..f875a16f921 100644 --- a/.gitignore +++ b/.gitignore @@ -161,5 +161,5 @@ Makefile.in configure doc/man/Makefile.in src/Makefile.in -src/cc/customcc.so +src/cc/libcc.so src/libcc.so diff --git a/depends/hosts/linux.mk b/depends/hosts/linux.mk index 31748d66226..08a30684d13 100644 --- a/depends/hosts/linux.mk +++ b/depends/hosts/linux.mk @@ -1,12 +1,11 @@ linux_CFLAGS=-pipe linux_CXXFLAGS=$(linux_CFLAGS) -linux_release_CFLAGS=-O1 +linux_release_CFLAGS=-O3 linux_release_CXXFLAGS=$(linux_release_CFLAGS) -linux_debug_CFLAGS=-O1 +linux_debug_CFLAGS=-g -O0 linux_debug_CXXFLAGS=$(linux_debug_CFLAGS) - linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC ifeq (86,$(findstring 86,$(build_arch))) diff --git a/qa/pytest_komodo/chainconfig.json b/qa/pytest_komodo/chainconfig.json index 47f376e425f..7fea510b364 100644 --- a/qa/pytest_komodo/chainconfig.json +++ b/qa/pytest_komodo/chainconfig.json @@ -2,10 +2,10 @@ "TONYCI": { "rpc_user": "test", "rpcpassword": "test", - "rpcallowip": "0.0.0.0/0", + "rpcallowip": "127.0.0.1", "rpcport": 7000, "port": 6000, - "rpcbind": "0.0.0.0", + "rpcbind": "127.0.0.1", "ac_name": "TONYCI", "ac_reward": "100000000000", "ac_supply": "10000000000", diff --git a/src/Makefile.am b/src/Makefile.am index 2266258bd7e..f3dfeb4058c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,7 @@ LIBMEMENV += $(builddir)/leveldb/libmemenv.a $(LIBLEVELDB): $(LIBMEMENV) $(LIBLEVELDB) $(LIBMEMENV): - @echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \ + $(AM_V_at)$(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \ CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \ OPT="$(AM_CXXFLAGS) $(PIE_FLAGS) $(CXXFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -D__STDC_LIMIT_MACROS" endif @@ -40,11 +40,11 @@ LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a LIBVERUS_CRYPTO=crypto/libverus_crypto.a LIBVERUS_PORTABLE_CRYPTO=crypto/libverus_portable_crypto.a LIBSECP256K1=secp256k1/libsecp256k1.la -LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.la +LIBCRYPTOCONDITIONS=cryptoconditions/libcryptoconditions_core.a LIBSNARK=snark/libsnark.a LIBUNIVALUE=univalue/libunivalue.la +LIBCC=libcc.a LIBZCASH=libzcash.a -LIBCJSON=libcjson.a if ENABLE_ZMQ LIBBITCOIN_ZMQ=libbitcoin_zmq.a @@ -55,15 +55,13 @@ endif if BUILD_BITCOIN_LIBS LIBZCASH_CONSENSUS=libzcashconsensus.la endif -if ENABLE_WALLET -LIBBITCOIN_WALLET=libbitcoin_wallet.a -endif $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " LIBSNARK_CXXFLAGS = $(AM_CXXFLAGS) $(PIC_FLAGS) -DBINARY_OUTPUT -DNO_PT_COMPRESSION=1 -fstack-protector-all LIBSNARK_CONFIG_FLAGS = CURVE=ALT_BN128 NO_PROCPS=1 NO_DOCS=1 STATIC=1 NO_SUPERCOP=1 FEATUREFLAGS=-DMONTGOMERY_OUTPUT NO_COPY_DEPINST=1 NO_COMPILE_LIBGTEST=1 +LIBSNARK_OPTFLAGS = $(CPPFLAGS) -march=x86-64 if HAVE_OPENMP LIBSNARK_CONFIG_FLAGS += MULTICORE=1 endif @@ -72,10 +70,10 @@ LIBSNARK_CONFIG_FLAGS += PLATFORM=darwin endif $(LIBSNARK): $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" + $(AM_V_at)CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" libsnark-tests: $(wildcard snark/src/*) - $(AM_V_at) CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" + $(AM_V_at)CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " @@ -118,7 +116,7 @@ if ENABLE_PROTON EXTRA_LIBRARIES += $(LIBBITCOIN_PROTON) endif -lib_LTLIBRARIES = $(LIBZCASH_CONSENSUS) +lib_LTLIBRARIES = $(LIBZCASH_CONSENSUS) $(LIBCC) bin_PROGRAMS = noinst_PROGRAMS = @@ -410,6 +408,11 @@ libbitcoin_wallet_a_SOURCES = \ $(BITCOIN_CORE_H) \ $(LIBZCASH_H) +# a shared library for cryptoconditions +libcc_a_SOURCES = cc/cclib.cpp +libcc_a_CXXFLAGS = -DBUILD_CUSTOMCC -I../secp256k1/include -I../depends/$(shell echo `../depends/config.guess`/include) -I./univalue/include -I./cryptoconditions/include -I./cryptoconditions/src -I./cryptoconditions/src/asn -I. -I./cc +libcc_a_LDFLAGS = -version-info 0:0:0 + # crypto primitives library crypto_libbitcoin_crypto_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_CONFIG_INCLUDES) crypto_libbitcoin_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) @@ -502,7 +505,7 @@ libbitcoin_common_a_SOURCES = \ komodo_kv.cpp \ komodo_notary.cpp \ komodo_pax.cpp \ - komodo_utils.cpp \ + komodo_utils.cpp \ netbase.cpp \ metrics.cpp \ primitives/block.cpp \ @@ -614,18 +617,9 @@ komodod_LDADD += \ $(LIBVERUS_CRYPTO) \ $(LIBVERUS_PORTABLE_CRYPTO) \ $(LIBZCASH_LIBS) \ + $(LIBCC) \ -lcurl -if TARGET_DARWIN -komodod_LDADD += libcc.dylib $(LIBSECP256K1) -endif -if TARGET_WINDOWS -komodod_LDADD += libcc.dll $(LIBSECP256K1) -endif -if TARGET_LINUX -komodod_LDADD += libcc.so $(LIBSECP256K1) -endif - if ENABLE_PROTON komodod_LDADD += $(LIBBITCOIN_PROTON) $(PROTON_LIBS) endif @@ -713,7 +707,6 @@ komodo_tx_LDADD = \ $(LIBCRYPTOCONDITIONS) komodo_tx_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) -# # zcash protocol primitives # libzcash_a_SOURCES = \ @@ -733,12 +726,11 @@ libzcash_a_SOURCES = \ zcash/circuit/prfs.tcc \ zcash/circuit/utils.tcc -libzcash_a_CPPFLAGS = -DMULTICORE -fopenmp -fPIC -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS $(HARDENED_CPPFLAGS) $(HARDENED_CXXFLAGS) $(HARDENED_LDFLAGS) -pipe $(SAN_LDFLAGS) -O1 -g -Wstack-protector $(SAN_CXXFLAGS) -fstack-protector-all -fPIE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES) - -#libzcash_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -#libzcash_a_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -#libzcash_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -DMONTGOMERY_OUTPUT - +libzcash_a_CPPFLAGS = -DMULTICORE -fopenmp -fPIC -DBINARY_OUTPUT -DCURVE_ALT_BN128 \ + -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS $(HARDENED_CPPFLAGS) \ + $(HARDENED_CXXFLAGS) $(HARDENED_LDFLAGS) -pipe $(SAN_LDFLAGS) \ + -Wstack-protector $(SAN_CXXFLAGS) -fstack-protector-all -fPIE -fvisibility=hidden \ + -DSTATIC $(BITCOIN_INCLUDES) libzcash_a_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) -fwrapv -fno-strict-aliasing libzcash_a_LDFLAGS = $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) libzcash_a_CPPFLAGS += -DMONTGOMERY_OUTPUT @@ -789,6 +781,13 @@ clean-local: rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno -rm -f config.h +clean-all: clean-local + -$(MAKE) -C snark clean-all + -$(MAKE) -C univalue clean-all + -$(RM) *.a + -$(RM) crypto/*.a + -$(RM) cryptoconditions/.libs/*.a + .rc.o: @test -f $(WINDRES) $(AM_V_GEN) $(WINDRES) -DWINDRES_PREPROC -i $< -o $@ diff --git a/src/cryptoconditions/Makefile.am b/src/cryptoconditions/Makefile.am index 787b11ac6f1..f347a1a2933 100644 --- a/src/cryptoconditions/Makefile.am +++ b/src/cryptoconditions/Makefile.am @@ -17,9 +17,9 @@ LIBSECP256K1=src/include/secp256k1/libsecp256k1.la $(LIBSECP256K1): $(wildcard src/secp256k1/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) -march:x86-64 -g -CRYPTOCONDITIONS_CORE=libcryptoconditions_core.la +CRYPTOCONDITIONS_CORE=libcryptoconditions_core.a -libcryptoconditions_core_la_SOURCES = \ +libcryptoconditions_core_a_SOURCES = \ src/cryptoconditions.c \ src/utils.c \ src/include/cJSON.c \ diff --git a/src/komodo_defs.h b/src/komodo_defs.h index c9a2c0587fa..66ff4c5d4d1 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -47,425 +47,6 @@ // 7113400 = 5x current KMD blockheight. // to add 4th season, change NUM_KMD_SEASONS to 4, and add timestamp and height of activation to these arrays. -#define NUM_KMD_SEASONS 6 -#define NUM_KMD_NOTARIES 64 - -extern const uint32_t nStakedDecemberHardforkTimestamp; //December 2019 hardfork -extern const int32_t nDecemberHardforkHeight; //December 2019 hardfork - -extern const uint32_t nS4Timestamp; //dPoW Season 4 2020 hardfork -extern const int32_t nS4HardforkHeight; //dPoW Season 4 2020 hardfork - -extern const uint32_t nS5Timestamp; //dPoW Season 5 June 14th, 2021 hardfork (03:00:00 PM UTC) (defined in komodo_globals.h) -extern const int32_t nS5HardforkHeight; //dPoW Season 5 June 14th, 2021 hardfork estimated block height (defined in komodo_globals.h) - -static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, 1751328000}; -static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, 7113400}; - -// Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. -static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = -{ - { - { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, - { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, - { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, - { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, - { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, - { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, - { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, - { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 - { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, - { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, - { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, - { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, - { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15 - { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, - { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, - { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, - { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, - { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 - { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, - { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, - { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, - { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, - { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 - { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, - { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, - { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, - { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, - { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, - { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, - { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, - { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, - { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 - { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, - { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, - { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, - { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, - { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, - { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, - { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, - { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, - { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 - { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, - { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, - { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, - { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, - { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, - { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, - { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, - { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, - { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, - { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 - { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, - { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, - { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } - }, - { - {"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - {"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" }, - {"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" }, - {"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" }, - {"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, - {"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, - {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, - {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 - {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, - {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, - {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, - {"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" }, - {"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" }, - {"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, - {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 - {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, - {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, - {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, - {"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" }, - {"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" }, - {"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" }, - {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, - {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" }, - {"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" }, - {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, - {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, - {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, - {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 - {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, - {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" }, - {"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" }, - {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, - {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, - {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 - {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, - {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, - {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, - {"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, - {"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, - {"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" }, - {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, - {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, - {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, - {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 - {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, - {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, - {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, - }, - { - {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 - {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, - {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, - {"dwy_EU", "021c7cf1f10c4dc39d13451123707ab780a741feedab6ac449766affe37515a29e" }, - {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, - {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, - {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, - {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, - {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, - {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, - {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, - {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, - {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, - {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, - {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 - {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, - {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, - {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, - {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, - {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, - {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, - {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, - {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 - {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, - {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, - {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, - {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, - {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, - {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, - {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, - {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 - {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, - {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, - {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, - {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, - {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, - {"dwy_SH", "036536d2d52d85f630b68b050f29ea1d7f90f3b42c10f8c5cdf3dbe1359af80aff" }, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 - {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, - {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, - {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 - }, - { - // Season 3.5 - {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 - {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, - {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, - {"hunter_EU", "0378224b4e9d8a0083ce36f2963ec0a4e231ec06b0c780de108e37f41181a89f6a" }, // FIXME verify this, kolo. Change name if you want - {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, - {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, - {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, - {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, - {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, - {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, - {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, - {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, - {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, - {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, - {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 - {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, - {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, - {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, - {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, - {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, - {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, - {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, - {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 - {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, - {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, - {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, - {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, - {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, - {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, - {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, - {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 - {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, - {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, - {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, - {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, - {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, - {"hunter_SH", "02407db70ad30ce4dfaee8b4ae35fae88390cad2b0ba0373fdd6231967537ccfdf" }, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 - {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, - {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, - {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 - }, - { - // Season 4 - { "alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - { "alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, - { "strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405" }, - { "titomane_SH", "020014ad4eedf6b1aeb0ad3b101a58d0a2fc570719e46530fd98d4e585f63eb4ae" }, - { "fullmoon_AR", "03b251095e747f759505ec745a4bbff9a768b8dce1f65137300b7c21efec01a07a" }, - { "phba2061_EU", "03a9492d2a1601d0d98cfe94d8adf9689d1bb0e600088127a4f6ca937761fb1c66" }, - { "fullmoon_NA", "03931c1d654a99658998ce0ddae108d825943a821d1cddd85e948ac1d483f68fb6" }, - { "fullmoon_SH", "03c2a1ed9ddb7bb8344328946017b9d8d1357b898957dd6aaa8c190ae26740b9ff" }, - { "madmax_AR", "022be5a2829fa0291f9a51ff7aeceef702eef581f2611887c195e29da49092e6de" }, - { "titomane_EU", "0285cf1fdba761daf6f1f611c32d319cd58214972ef822793008b69dde239443dd" }, - { "cipi_NA", "022c6825a24792cc3b010b1531521eba9b5e2662d640ed700fd96167df37e75239" }, - { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - { "decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, - { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - { "madmax_NA", "02997b7ab21b86bbea558ae79acc35d62c9cedf441578f78112f986d72e8eece08" }, - { "chainzilla_SH", "02288ba6dc57936b59d60345e397d62f5d7e7d975f34ed5c2f2e23288325661563" }, - { "peer2cloud_AR", "0250e7e43a3535731b051d1bcc7dc88fbb5163c3fe41c5dee72bd973bcc4dca9f2" }, - { "pirate_EU", "0231c0f50a06655c3d2edf8d7e722d290195d49c78d50de7786b9d196e8820c848" }, - { "webworker01_NA", "02dfd5f3cef1142879a7250752feb91ddd722c497fb98c7377c0fcc5ccc201bd55" }, - { "zatjum_SH", "036066fd638b10e555597623e97e032b28b4d1fa5a13c2b0c80c420dbddad236c2" }, - { "titomane_AR", "0268203a4c80047edcd66385c22e764ea5fb8bc42edae389a438156e7dca9a8251" }, - { "chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d" }, - { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - { "patchkez_SH", "02cabd6c5fc0b5476c7a01e9d7b907e9f0a051d7f4f731959955d3f6b18ee9a242" }, - { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - { "etszombi_EU", "0341adbf238f33a33cc895633db996c3ad01275313ac6641e046a3db0b27f1c880" }, - { "pirate_NA", "02207f27a13625a0b8caef6a7bb9de613ff16e4a5f232da8d7c235c7c5bad72ffe" }, - { "metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - { "chainmakers_NA", "029415a1609c33dfe4a1016877ba35f9265d25d737649f307048efe96e76512877" }, - { "mihailo_EU", "037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941" }, - { "tonyl_AR", "0299684d7291abf90975fa493bf53212cf1456c374aa36f83cc94daece89350ae9" }, - { "alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8" }, - { "pungocloud_SH", "025b97d8c23effaca6fa7efacce20bf54df73081b63004a0fe22f3f98fece5669f" }, - { "node9_EU", "029ffa793b5c3248f8ea3da47fa3cf1810dada5af032ecd0e37bab5b92dd63b34e" }, - { "smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac" }, - { "nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b" }, - { "gcharang_SH", "02ec4172eab854a0d8cd32bc691c83e93975a3df5a4a453a866736c56e025dc359" }, - { "cipi_EU", "02f2b6defff1c544202f66e47cfd6909c54d67c7c39b9c2a99f137dbaf6d0bd8fa" }, - { "etszombi_AR", "0329944b0ac65b6760787ede042a2fde0be9fca1d80dd756bc0ee0b98d389b7682" }, - { "pbca26_NA", "0387e0fb6f2ca951154c87e16c6cbf93a69862bb165c1a96bcd8722b3af24fe533" }, - { "mylo_SH", "03b58f57822e90fe105e6efb63fd8666033ea503d6cc165b1e479bbd8c2ba033e8" }, - { "swisscertifiers_EU", "03ebcc71b42d88994b8b2134bcde6cb269bd7e71a9dd7616371d9294ec1c1902c5" }, - { "marmarachain_AR", "035bbd81a098172592fe97f50a0ce13cbbf80e55cc7862eccdbd7310fab8a90c4c" }, - { "karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d" }, - { "phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - { "oszy_EU", "03d1ffd680491b98a3ec5541715681d1a45293c8efb1722c32392a1d792622596a" }, - { "chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005" }, - { "dragonhound_NA", "0227e5cad3731e381df157de189527aac8eb50d82a13ce2bd81153984ebc749515" }, - { "strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a" }, - { "madmax_EU", "02ea0cf4d6d151d0528b07efa79cc7403d77cb9195e2e6c8374f5074b9a787e287" }, - { "dudezmobi_AR", "027ecd974ff2a27a37ee69956cd2e6bb31a608116206f3e31ef186823420182450" }, - { "daemonfox_NA", "022d6f4885f53cbd668ad7d03d4f8e830c233f74e3a918da1ed247edfc71820b3d" }, - { "nutellalicka_SH", "02f4b1e71bc865a79c05fe333952b97cb040d8925d13e83925e170188b3011269b" }, - { "starfleet_EU", "025c7275bd750936862b47793f1f0bb3cbed60fb75a48e7da016e557925fe375eb" }, - { "mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4" }, - { "greer_NA", "03e0995615d7d3cf1107effa6bdb1133e0876cf1768e923aa533a4e2ee675ec383" }, - { "mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043" }, - { "decker_EU", "03777777caebce56e17ca3aae4e16374335b156f1dd62ee3c7f8799c6b885f5560" }, - { "dappvader_SH", "02962e2e5af746632016bc7b24d444f7c90141a5f42ce54e361b302cf455d90e6a" }, - { "alright_DEV", "02b73a589d61691efa2ada15c006d27bc18493fea867ce6c14db3d3d28751f8ce3" }, - { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, - { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, - { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } - }, - { - // Season 5 - {"alrighttt_DEV", "03483166d8663beeb48a493eec161bf506df1906153b6259f7ca617e4cb8110260"}, // 0 - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, - {"artempikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, - {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, - {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, - {"shadowbit_AR", "02909c79a198179c193fb85bbd4ba09b875a5a9bd481fec284658188b96ed43519"}, - {"goldenman_AR", "0345b888e5de9c11871c080212ccaebf8a3d77b05fe3d535336efc5c7df334bbc7"}, - {"kolo_AR", "0281d3c7bf067088b9572b4d906afca2083a71a38b1011878ecd347651d00af433"}, - {"madmax_AR", "02f729b8df4dacdc8d811416eb32e98a5cc37023b42c81b77d1c00881de879a99a"}, - {"mcrypt_AR", "029bdb33b08f96524082490f4373bc6026b92bcaef9bc521a840a799c73b75ed80"}, - {"mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4"}, // 10 - {"ocean_AR", "03c2bc8c57a001a788851fedc33ce72797ee8fe26eaa3abb1b807727e4867a3105"}, - {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, - {"tokel_AR", "03f3bf697173e47de7bae2ae02b3d3bcf28133a47db72f2a0266061597aaa7779d"}, - {"tonyl_AR", "029ad03929ec295e9164e2bfb9f0e0102c280d5e5212503d079d2d99ab492a9106"}, - {"tonyl_DEV", "02342ec82b31a016b71cd1eb2f482a74f63172e1029ba2fb18f0def3bd4fc0668a"}, - {"artem_DEV", "036b9848396ddcdb9bb58ddab2c24b710b8e4e9b0ee084a00518505ecd9e9fe174"}, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, - {"alienx_EU", "026afe5b112d1b39e0edafd5e051e261a676104460581f3673f26ceff7f1e6c56c"}, - {"ca333_EU", "03ffb8072f78304c42ae9b60435f6c3296cbc72de129ae49bba175a65c31c9a7e2"}, - {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, // 20 - {"cipi_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, - {"cipi2_EU", "0202e430157486503f4bde3d3ca770c8f1e2447cf480a6b273b5265b9620f585e3"}, - {"shadowbit_EU", "02668f5f723584f97f5e6f9196fc31018f36a6cf824c60328ad0c097a785df4745"}, - {"komodopioneers_EU", "0351f7f2a6ecce863e4e774bfafe2e59e151c08bf8f350286763a6b8ed97274b82"}, - {"madmax_EU", "028d04f7ccae0d9d57bfa801c4f1e32c707c17589b3c08a0ce08d44eab637eb66b"}, - {"marmarachain_EU", "023a858bbc3f0c6df5b74243315028e968c2f299d84ea8ecc0b28b5f0e2ad24c3c"}, - {"node-9_EU", "03c375924aac39d0c49de6690199e4d08d10fed6725988dcf5d2486661b5e3a656"}, - {"slyris_EU", "021cb6365c13cb35aad4b70aa18b63a75d1d4b9797a0754d3d0142d6fedc83b24e"}, - {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, - {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, // 30 - {"shadowbit_DEV", "02ca882f153e715091a2dbc5409096f8c109d9fe6506ca7a918056dd37162b6f6e"}, - {"gcharang_DEV", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, - {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, - {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, - {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, - {"dragonhound_NA", "02e650819f4d1cabeaad6bc5ec8c0722a89e63059a10f8b5e97c983c321608329b"}, - {"hyper_NA", "030994a303b26df6e7c6ed456f069c5de9e200e1380bebc5ed8ebe0f834f477f3d"}, - {"madmax_NA", "03898aec46014e8619e2369cc85073048dad05d3c5bf696d8b524db78a39ae5beb"}, - {"node-9_NA", "02f697eed99fd21f2f0eaad81d13543a75c576f669bfddbcbeef0f7625fea2e9d5"}, // 40 - {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, - {"pbca26_NA", "0332543ff1287604afd67f63af0aa0b263aef14fe1850b85db16b81462eed834fd"}, - {"ptyx_NA", "02cbda9c43a794f2134a11815fe86dca017990269accb139e962d764c011c9a4d7"}, - {"strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405"}, - {"karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d"}, - {"webworker01_NA", "0376558d13c31cf9c664a1b5e58f4fff7153777069bef7a66ed8c8526b99787a9e"}, - {"yurii_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, - {"ca333_DEV", "03d885e292842912bd990299ebce33451a5a01cb14e4874d90770efb22e82ef40f"}, - {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, - {"collider_SH", "03bd0022a55a2ead52fd65b317186743374ad320f3704d459f41797e264d1ec854"}, // 50 - {"dappvader_SH", "02bffea7911e09ad9a7df54af0c225516478d3ba138e65061aa8d4b9756bb4c8f4"}, - {"drkush_SH", "030b31cc9528566422e25f3e9b96541ab3626c0dea0e7aa3c0b0bd96039eae2f5a"}, - {"majora31_SH", "033bf21f039a1c832effad208d564e02e968f11e3a3aa41c42e3b748a232fb33f3"}, - {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309"}, - {"mylo_SH", "03458dca36e800d5bc121d8c0d35f9fc6282880a79fee2d7e050f887b797bc7d6e"}, - {"nutellaLicka_SH", "03a495962a9e9eca06ee3b8ab4cd94e6ea0d87dd39d334ad85a524c4fece1a3db7"}, - {"pbca26_SH", "02c62877e96fc414f2444edf0601abff9d5d2f9078e49fa867ba5305f3c5b3beb0"}, - {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, - {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, // 60 - {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, - {"strobnidan_SH", "02b967fde3686d45056343e488997d4c53f25cd7ad38548cd12b136010a09295ae"}, - {"dragonhound_DEV", "038e010c33c56b61389409eea5597fe17967398731e23185c84c472a16fc5d34ab"} - } -}; - #define SETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] |= (1 << ((bitoffset) & 7))) #define GETBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] & (1 << ((bitoffset) & 7))) #define CLEARBIT(bits,bitoffset) (((uint8_t *)bits)[(bitoffset) >> 3] &= ~(1 << ((bitoffset) & 7))) @@ -507,6 +88,7 @@ extern std::vector ASSETCHAINS_PRICES,ASSETCHAINS_STOCKS; extern int32_t VERUS_BLOCK_POSUNITS, VERUS_CONSECUTIVE_POS_THRESHOLD, VERUS_NOPOS_THRESHHOLD; extern uint256 KOMODO_EARLYTXID; +extern bool IS_KOMODO_TESTNODE; extern bool IS_KOMODO_DEALERNODE; extern int32_t KOMODO_CONNECTING,KOMODO_CCACTIVATE; extern uint32_t ASSETCHAINS_CC; @@ -520,9 +102,6 @@ extern int32_t VERUS_MIN_STAKEAGE; extern std::string DONATION_PUBKEY; extern uint8_t ASSETCHAINS_PRIVATE; extern int32_t USE_EXTERNAL_PUBKEY; -extern char NOTARYADDRS[64][64]; -extern char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; -extern bool IS_KOMODO_TESTNODE; extern int32_t KOMODO_SNAPSHOT_INTERVAL,STAKED_NOTARY_ID,STAKED_ERA; extern int32_t ASSETCHAINS_EARLYTXIDCONTRACT; extern int32_t ASSETCHAINS_STAKED_SPLIT_PERCENTAGE; diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 578506f484a..8d2fc9f7971 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -15,6 +15,7 @@ #pragma once #include #include "komodo_defs.h" +#include "komodo_hardfork.h" #include "komodo_structs.h" void komodo_prefetch(FILE *fp); diff --git a/src/komodo_hardfork.h b/src/komodo_hardfork.h new file mode 100644 index 00000000000..be6d2d8b29f --- /dev/null +++ b/src/komodo_hardfork.h @@ -0,0 +1,425 @@ +#pragma once + +#include + +#define NUM_KMD_SEASONS 6 +#define NUM_KMD_NOTARIES 64 + +extern const uint32_t nStakedDecemberHardforkTimestamp; //December 2019 hardfork +extern const int32_t nDecemberHardforkHeight; //December 2019 hardfork + +extern const uint32_t nS4Timestamp; //dPoW Season 4 2020 hardfork +extern const int32_t nS4HardforkHeight; //dPoW Season 4 2020 hardfork + +extern const uint32_t nS5Timestamp; //dPoW Season 5 June 14th, 2021 hardfork (03:00:00 PM UTC) (defined in komodo_globals.h) +extern const int32_t nS5HardforkHeight; //dPoW Season 5 June 14th, 2021 hardfork estimated block height (defined in komodo_globals.h) + +static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, 1751328000}; +static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, 7113400}; + +// Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. +static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = +{ + { + { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, + { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, + { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, + { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, + { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 + { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, + { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, + { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, + { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, + { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15 + { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, + { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, + { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, + { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, + { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 + { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, + { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, + { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, + { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 + { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, + { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, + { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, + { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, + { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, + { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, + { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, + { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 + { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, + { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, + { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, + { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, + { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, + { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, + { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, + { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 + { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, + { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, + { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, + { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, + { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, + { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, + { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, + { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, + { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, + { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 + { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, + { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } + }, + { + {"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + {"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" }, + {"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" }, + {"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" }, + {"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + {"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 + {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, + {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, + {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, + {"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" }, + {"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" }, + {"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, + {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 + {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, + {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, + {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, + {"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" }, + {"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" }, + {"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" }, + {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, + {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" }, + {"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" }, + {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, + {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, + {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, + {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 + {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, + {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" }, + {"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" }, + {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, + {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, + {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 + {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, + {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, + {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, + {"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + {"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, + {"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" }, + {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, + {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, + {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, + {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 + {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, + {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, + {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + }, + { + {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 + {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, + {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, + {"dwy_EU", "021c7cf1f10c4dc39d13451123707ab780a741feedab6ac449766affe37515a29e" }, + {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, + {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, + {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, + {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, + {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, + {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, + {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, + {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, + {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, + {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, + {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 + {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, + {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, + {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, + {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, + {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, + {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, + {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, + {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 + {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, + {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, + {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, + {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, + {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, + {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, + {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, + {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 + {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, + {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, + {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, + {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, + {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, + {"dwy_SH", "036536d2d52d85f630b68b050f29ea1d7f90f3b42c10f8c5cdf3dbe1359af80aff" }, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 + {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, + {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, + {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 + }, + { + // Season 3.5 + {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 + {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, + {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, + {"hunter_EU", "0378224b4e9d8a0083ce36f2963ec0a4e231ec06b0c780de108e37f41181a89f6a" }, // FIXME verify this, kolo. Change name if you want + {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, + {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, + {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, + {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, + {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, + {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, + {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, + {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, + {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, + {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, + {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 + {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, + {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, + {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, + {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, + {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, + {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, + {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, + {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 + {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, + {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, + {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, + {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, + {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, + {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, + {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, + {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 + {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, + {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, + {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, + {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, + {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, + {"hunter_SH", "02407db70ad30ce4dfaee8b4ae35fae88390cad2b0ba0373fdd6231967537ccfdf" }, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 + {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, + {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, + {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 + }, + { + // Season 4 + { "alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + { "alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, + { "strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405" }, + { "titomane_SH", "020014ad4eedf6b1aeb0ad3b101a58d0a2fc570719e46530fd98d4e585f63eb4ae" }, + { "fullmoon_AR", "03b251095e747f759505ec745a4bbff9a768b8dce1f65137300b7c21efec01a07a" }, + { "phba2061_EU", "03a9492d2a1601d0d98cfe94d8adf9689d1bb0e600088127a4f6ca937761fb1c66" }, + { "fullmoon_NA", "03931c1d654a99658998ce0ddae108d825943a821d1cddd85e948ac1d483f68fb6" }, + { "fullmoon_SH", "03c2a1ed9ddb7bb8344328946017b9d8d1357b898957dd6aaa8c190ae26740b9ff" }, + { "madmax_AR", "022be5a2829fa0291f9a51ff7aeceef702eef581f2611887c195e29da49092e6de" }, + { "titomane_EU", "0285cf1fdba761daf6f1f611c32d319cd58214972ef822793008b69dde239443dd" }, + { "cipi_NA", "022c6825a24792cc3b010b1531521eba9b5e2662d640ed700fd96167df37e75239" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "madmax_NA", "02997b7ab21b86bbea558ae79acc35d62c9cedf441578f78112f986d72e8eece08" }, + { "chainzilla_SH", "02288ba6dc57936b59d60345e397d62f5d7e7d975f34ed5c2f2e23288325661563" }, + { "peer2cloud_AR", "0250e7e43a3535731b051d1bcc7dc88fbb5163c3fe41c5dee72bd973bcc4dca9f2" }, + { "pirate_EU", "0231c0f50a06655c3d2edf8d7e722d290195d49c78d50de7786b9d196e8820c848" }, + { "webworker01_NA", "02dfd5f3cef1142879a7250752feb91ddd722c497fb98c7377c0fcc5ccc201bd55" }, + { "zatjum_SH", "036066fd638b10e555597623e97e032b28b4d1fa5a13c2b0c80c420dbddad236c2" }, + { "titomane_AR", "0268203a4c80047edcd66385c22e764ea5fb8bc42edae389a438156e7dca9a8251" }, + { "chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "patchkez_SH", "02cabd6c5fc0b5476c7a01e9d7b907e9f0a051d7f4f731959955d3f6b18ee9a242" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "etszombi_EU", "0341adbf238f33a33cc895633db996c3ad01275313ac6641e046a3db0b27f1c880" }, + { "pirate_NA", "02207f27a13625a0b8caef6a7bb9de613ff16e4a5f232da8d7c235c7c5bad72ffe" }, + { "metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "chainmakers_NA", "029415a1609c33dfe4a1016877ba35f9265d25d737649f307048efe96e76512877" }, + { "mihailo_EU", "037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941" }, + { "tonyl_AR", "0299684d7291abf90975fa493bf53212cf1456c374aa36f83cc94daece89350ae9" }, + { "alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8" }, + { "pungocloud_SH", "025b97d8c23effaca6fa7efacce20bf54df73081b63004a0fe22f3f98fece5669f" }, + { "node9_EU", "029ffa793b5c3248f8ea3da47fa3cf1810dada5af032ecd0e37bab5b92dd63b34e" }, + { "smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac" }, + { "nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b" }, + { "gcharang_SH", "02ec4172eab854a0d8cd32bc691c83e93975a3df5a4a453a866736c56e025dc359" }, + { "cipi_EU", "02f2b6defff1c544202f66e47cfd6909c54d67c7c39b9c2a99f137dbaf6d0bd8fa" }, + { "etszombi_AR", "0329944b0ac65b6760787ede042a2fde0be9fca1d80dd756bc0ee0b98d389b7682" }, + { "pbca26_NA", "0387e0fb6f2ca951154c87e16c6cbf93a69862bb165c1a96bcd8722b3af24fe533" }, + { "mylo_SH", "03b58f57822e90fe105e6efb63fd8666033ea503d6cc165b1e479bbd8c2ba033e8" }, + { "swisscertifiers_EU", "03ebcc71b42d88994b8b2134bcde6cb269bd7e71a9dd7616371d9294ec1c1902c5" }, + { "marmarachain_AR", "035bbd81a098172592fe97f50a0ce13cbbf80e55cc7862eccdbd7310fab8a90c4c" }, + { "karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d" }, + { "phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + { "oszy_EU", "03d1ffd680491b98a3ec5541715681d1a45293c8efb1722c32392a1d792622596a" }, + { "chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005" }, + { "dragonhound_NA", "0227e5cad3731e381df157de189527aac8eb50d82a13ce2bd81153984ebc749515" }, + { "strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a" }, + { "madmax_EU", "02ea0cf4d6d151d0528b07efa79cc7403d77cb9195e2e6c8374f5074b9a787e287" }, + { "dudezmobi_AR", "027ecd974ff2a27a37ee69956cd2e6bb31a608116206f3e31ef186823420182450" }, + { "daemonfox_NA", "022d6f4885f53cbd668ad7d03d4f8e830c233f74e3a918da1ed247edfc71820b3d" }, + { "nutellalicka_SH", "02f4b1e71bc865a79c05fe333952b97cb040d8925d13e83925e170188b3011269b" }, + { "starfleet_EU", "025c7275bd750936862b47793f1f0bb3cbed60fb75a48e7da016e557925fe375eb" }, + { "mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4" }, + { "greer_NA", "03e0995615d7d3cf1107effa6bdb1133e0876cf1768e923aa533a4e2ee675ec383" }, + { "mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043" }, + { "decker_EU", "03777777caebce56e17ca3aae4e16374335b156f1dd62ee3c7f8799c6b885f5560" }, + { "dappvader_SH", "02962e2e5af746632016bc7b24d444f7c90141a5f42ce54e361b302cf455d90e6a" }, + { "alright_DEV", "02b73a589d61691efa2ada15c006d27bc18493fea867ce6c14db3d3d28751f8ce3" }, + { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, + { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, + { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } + }, + { + // Season 5 + {"alrighttt_DEV", "03483166d8663beeb48a493eec161bf506df1906153b6259f7ca617e4cb8110260"}, // 0 + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, + {"artempikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, + {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, + {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, + {"shadowbit_AR", "02909c79a198179c193fb85bbd4ba09b875a5a9bd481fec284658188b96ed43519"}, + {"goldenman_AR", "0345b888e5de9c11871c080212ccaebf8a3d77b05fe3d535336efc5c7df334bbc7"}, + {"kolo_AR", "0281d3c7bf067088b9572b4d906afca2083a71a38b1011878ecd347651d00af433"}, + {"madmax_AR", "02f729b8df4dacdc8d811416eb32e98a5cc37023b42c81b77d1c00881de879a99a"}, + {"mcrypt_AR", "029bdb33b08f96524082490f4373bc6026b92bcaef9bc521a840a799c73b75ed80"}, + {"mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4"}, // 10 + {"ocean_AR", "03c2bc8c57a001a788851fedc33ce72797ee8fe26eaa3abb1b807727e4867a3105"}, + {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, + {"tokel_AR", "03f3bf697173e47de7bae2ae02b3d3bcf28133a47db72f2a0266061597aaa7779d"}, + {"tonyl_AR", "029ad03929ec295e9164e2bfb9f0e0102c280d5e5212503d079d2d99ab492a9106"}, + {"tonyl_DEV", "02342ec82b31a016b71cd1eb2f482a74f63172e1029ba2fb18f0def3bd4fc0668a"}, + {"artem_DEV", "036b9848396ddcdb9bb58ddab2c24b710b8e4e9b0ee084a00518505ecd9e9fe174"}, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, + {"alienx_EU", "026afe5b112d1b39e0edafd5e051e261a676104460581f3673f26ceff7f1e6c56c"}, + {"ca333_EU", "03ffb8072f78304c42ae9b60435f6c3296cbc72de129ae49bba175a65c31c9a7e2"}, + {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, // 20 + {"cipi_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, + {"cipi2_EU", "0202e430157486503f4bde3d3ca770c8f1e2447cf480a6b273b5265b9620f585e3"}, + {"shadowbit_EU", "02668f5f723584f97f5e6f9196fc31018f36a6cf824c60328ad0c097a785df4745"}, + {"komodopioneers_EU", "0351f7f2a6ecce863e4e774bfafe2e59e151c08bf8f350286763a6b8ed97274b82"}, + {"madmax_EU", "028d04f7ccae0d9d57bfa801c4f1e32c707c17589b3c08a0ce08d44eab637eb66b"}, + {"marmarachain_EU", "023a858bbc3f0c6df5b74243315028e968c2f299d84ea8ecc0b28b5f0e2ad24c3c"}, + {"node-9_EU", "03c375924aac39d0c49de6690199e4d08d10fed6725988dcf5d2486661b5e3a656"}, + {"slyris_EU", "021cb6365c13cb35aad4b70aa18b63a75d1d4b9797a0754d3d0142d6fedc83b24e"}, + {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, + {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, // 30 + {"shadowbit_DEV", "02ca882f153e715091a2dbc5409096f8c109d9fe6506ca7a918056dd37162b6f6e"}, + {"gcharang_DEV", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, + {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, + {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, + {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, + {"dragonhound_NA", "02e650819f4d1cabeaad6bc5ec8c0722a89e63059a10f8b5e97c983c321608329b"}, + {"hyper_NA", "030994a303b26df6e7c6ed456f069c5de9e200e1380bebc5ed8ebe0f834f477f3d"}, + {"madmax_NA", "03898aec46014e8619e2369cc85073048dad05d3c5bf696d8b524db78a39ae5beb"}, + {"node-9_NA", "02f697eed99fd21f2f0eaad81d13543a75c576f669bfddbcbeef0f7625fea2e9d5"}, // 40 + {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, + {"pbca26_NA", "0332543ff1287604afd67f63af0aa0b263aef14fe1850b85db16b81462eed834fd"}, + {"ptyx_NA", "02cbda9c43a794f2134a11815fe86dca017990269accb139e962d764c011c9a4d7"}, + {"strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405"}, + {"karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d"}, + {"webworker01_NA", "0376558d13c31cf9c664a1b5e58f4fff7153777069bef7a66ed8c8526b99787a9e"}, + {"yurii_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, + {"ca333_DEV", "03d885e292842912bd990299ebce33451a5a01cb14e4874d90770efb22e82ef40f"}, + {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, + {"collider_SH", "03bd0022a55a2ead52fd65b317186743374ad320f3704d459f41797e264d1ec854"}, // 50 + {"dappvader_SH", "02bffea7911e09ad9a7df54af0c225516478d3ba138e65061aa8d4b9756bb4c8f4"}, + {"drkush_SH", "030b31cc9528566422e25f3e9b96541ab3626c0dea0e7aa3c0b0bd96039eae2f5a"}, + {"majora31_SH", "033bf21f039a1c832effad208d564e02e968f11e3a3aa41c42e3b748a232fb33f3"}, + {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309"}, + {"mylo_SH", "03458dca36e800d5bc121d8c0d35f9fc6282880a79fee2d7e050f887b797bc7d6e"}, + {"nutellaLicka_SH", "03a495962a9e9eca06ee3b8ab4cd94e6ea0d87dd39d334ad85a524c4fece1a3db7"}, + {"pbca26_SH", "02c62877e96fc414f2444edf0601abff9d5d2f9078e49fa867ba5305f3c5b3beb0"}, + {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, + {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, // 60 + {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, + {"strobnidan_SH", "02b967fde3686d45056343e488997d4c53f25cd7ad38548cd12b136010a09295ae"}, + {"dragonhound_DEV", "038e010c33c56b61389409eea5597fe17967398731e23185c84c472a16fc5d34ab"} + } +}; + +extern char NOTARYADDRS[64][64]; +extern char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; diff --git a/src/komodo_notary.h b/src/komodo_notary.h index 07af99b11db..e533dec0799 100644 --- a/src/komodo_notary.h +++ b/src/komodo_notary.h @@ -18,6 +18,7 @@ #include "komodo_cJSON.h" #include "notaries_staked.h" +#include "komodo_hardfork.h" #define KOMODO_MAINNET_START 178999 #define KOMODO_NOTARIES_HEIGHT1 814000 diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile index 2bd2cadcdde..486802d5424 100644 --- a/src/leveldb/Makefile +++ b/src/leveldb/Makefile @@ -107,8 +107,8 @@ clean: -rm -rf ios-x86/* ios-arm/* $(LIBRARY): $(LIBOBJECTS) - rm -f $@ - $(AR) -rs $@ $(LIBOBJECTS) + @rm -f $@ + @$(AR) -rs $@ $(LIBOBJECTS) db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) $(CXX) $(LDFLAGS) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) -o $@ $(LIBS) @@ -189,8 +189,8 @@ write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) $(CXX) $(LDFLAGS) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) $(MEMENVLIBRARY) : $(MEMENVOBJECTS) - rm -f $@ - $(AR) -rs $@ $(MEMENVOBJECTS) + @rm -f $@ + @$(AR) -rs $@ $(MEMENVOBJECTS) memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) $(CXX) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(LIBS) @@ -220,8 +220,8 @@ IOSARCH=-arch armv6 -arch armv7 -arch armv7s -arch arm64 else .cc.o: - $(CXX) $(CXXFLAGS) -c $< -o $@ + @$(CXX) $(CXXFLAGS) -c $< -o $@ .c.o: - $(CC) $(CFLAGS) -c $< -o $@ + @$(CC) $(CFLAGS) -c $< -o $@ endif diff --git a/src/notaries_staked.cpp b/src/notaries_staked.cpp index 14b86cbc8a9..0a804db2083 100644 --- a/src/notaries_staked.cpp +++ b/src/notaries_staked.cpp @@ -3,6 +3,7 @@ #include "crosschain.h" #include "cc/CCinclude.h" #include "komodo_defs.h" +#include "komodo_hardfork.h" #include "hex.h" #include diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am index c5fa00fc575..bf4d448bd03 100644 --- a/src/secp256k1/Makefile.am +++ b/src/secp256k1/Makefile.am @@ -153,10 +153,10 @@ CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function gen_context_OBJECTS = gen_context.o gen_context_BIN = gen_context$(BUILD_EXEEXT) gen_%.o: src/gen_%.c - $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ + $(AM_V_at)$(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ $(gen_context_BIN): $(gen_context_OBJECTS) - $(CC_FOR_BUILD) $^ -o $@ + $(AM_V_at)$(CC_FOR_BUILD) $^ -o $@ $(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h $(tests_OBJECTS): src/ecmult_static_context.h diff --git a/src/snark/Makefile b/src/snark/Makefile index 3ef82ab878a..26fd3ec356c 100644 --- a/src/snark/Makefile +++ b/src/snark/Makefile @@ -195,7 +195,7 @@ $(DEPINST_EXISTS): -include $(patsubst %.o,%.d, $(LIB_OBJS) $(GTEST_OBJS) $(EXEC_OBJS) ) $(LIB_OBJS) $(if $(NO_GTEST),,$(GTEST_OBJS)) $(EXEC_OBJS): %.o: %.cpp - $(CXX) -o $@ $< -c -MMD $(CXXFLAGS) + @$(CXX) -o $@ $< -c -MMD $(CXXFLAGS) LIBGTEST_A = $(DEPINST)/lib/libgtest.a @@ -205,12 +205,12 @@ $(LIBGTEST_A): $(GTESTDIR)/libsnark/gtest-all.cc $(DEPINST_EXISTS) # libsnark.a will contains all of our relevant object files, and we also mash in the .a files of relevant dependencies built by ./prepare-depends.sh $(LIBSNARK_A): $(LIB_OBJS) $(AR_LIBS) - $(AR) q $(LIBSNARK_A) $(LIB_OBJS) - if [ -n "$(AR_LIBS)" ]; then mkdir -p tmp-ar; cd tmp-ar; for AR_LIB in $(AR_LIBS); do $(AR) x $$AR_LIB; done; $(AR) qc $(LIBSNARK_A) tmp-ar/*; cd ..; rm -r tmp-ar; fi; - $(AR) s $(LIBSNARK_A) + @$(AR) q $(LIBSNARK_A) $(LIB_OBJS) + @if [ -n "$(AR_LIBS)" ]; then mkdir -p tmp-ar; cd tmp-ar; for AR_LIB in $(AR_LIBS); do $(AR) x $$AR_LIB; done; $(AR) qc $(LIBSNARK_A) tmp-ar/*; cd ..; rm -r tmp-ar; fi; + @$(AR) s $(LIBSNARK_A) libsnark.so: $(LIBSNARK_A) $(DEPINST_EXISTS) - $(CXX) -o $@ --shared -Wl,--whole-archive $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) -Wl,--no-whole-archive $(LDLIBS) + @$(CXX) -o $@ --shared -Wl,--whole-archive $(LIBSNARK_A) $(CXXFLAGS) $(LDFLAGS) -Wl,--no-whole-archive $(LDLIBS) libsnark/gadgetlib2/tests/gadgetlib2_test: \ libsnark/gadgetlib2/tests/adapters_UTEST.cpp \ diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index ea03242cc71..aa030b8a019 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -42,15 +42,8 @@ PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 -#BUILD CCLIB - -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD - ./autogen.sh + CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ ./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" diff --git a/zcutil/build.sh b/zcutil/build.sh index 6f625b185aa..a017d07b50b 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -59,8 +59,6 @@ EOF exit 0 fi -set -x - # If --enable-lcov is the first argument, enable lcov coverage support: LCOV_ARG='' HARDENING_ARG='--enable-hardening' @@ -92,24 +90,16 @@ then shift fi -eval "$MAKE" --version -as --version -ld -v +if [[ -z "${VERBOSE-}" ]]; then + VERBOSITY="--enable-silent-rules" +else + VERBOSITY="--disable-silent-rules" +fi HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 + ./autogen.sh CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' -#BUILD CCLIB - -WD=$PWD - -cd src/cc -echo $PWD -./makecustom - - -cd $WD - -"$MAKE" "$@" V=1 +"$MAKE" "$@" From a1213759bf4db2a90368e8f2c8afa1fef7a07d1a Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 8 Oct 2021 16:11:24 -0500 Subject: [PATCH 27/47] make clean .a files --- Makefile.am | 3 +++ src/Makefile.am | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 51d0430aca4..71a0d5f53b3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -344,3 +344,6 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-man clean-local: rm -rf test_bitcoin.coverage/ zcash-gtest.coverage/ total.coverage/ + +clean-all: clean-local + $(MAKE) -C src clean-all diff --git a/src/Makefile.am b/src/Makefile.am index f3dfeb4058c..d9b7a1bab40 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -780,13 +780,13 @@ clean-local: -$(MAKE) -C univalue clean rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno -rm -f config.h + -$(RM) *.a + -$(RM) crypto/*.a + -$(RM) cryptoconditions/.libs/*.a clean-all: clean-local -$(MAKE) -C snark clean-all -$(MAKE) -C univalue clean-all - -$(RM) *.a - -$(RM) crypto/*.a - -$(RM) cryptoconditions/.libs/*.a .rc.o: @test -f $(WINDRES) From 0eaff0939ed99f756b2b8a3d054419ded3a82a7b Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 13 Oct 2021 10:46:36 -0500 Subject: [PATCH 28/47] hardforks in own object --- src/Makefile.am | 1 + src/komodo_globals.h | 8 - src/komodo_hardfork.cpp | 417 ++++++++++++++++++++++++++++++++++++++++ src/komodo_hardfork.h | 407 +-------------------------------------- 4 files changed, 421 insertions(+), 412 deletions(-) create mode 100644 src/komodo_hardfork.cpp diff --git a/src/Makefile.am b/src/Makefile.am index d9b7a1bab40..642d437b2e8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -500,6 +500,7 @@ libbitcoin_common_a_SOURCES = \ komodo_events.cpp \ komodo_gateway.cpp \ komodo_globals.cpp \ + komodo_hardfork.cpp \ komodo_interest.cpp \ komodo_jumblr.cpp \ komodo_kv.cpp \ diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 8d2fc9f7971..a8c061e11df 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -42,14 +42,6 @@ int32_t NUM_PRICES; uint32_t *PVALS; struct knotaries_entry *Pubkeys; struct komodo_state KOMODO_STATES[34]; -const uint32_t nStakedDecemberHardforkTimestamp = 1576840000; //December 2019 hardfork 12/20/2019 @ 11:06am (UTC) -const int32_t nDecemberHardforkHeight = 1670000; //December 2019 hardfork - -const uint32_t nS4Timestamp = 1592146800; //dPoW Season 4 2020 hardfork Sunday, June 14th, 2020 03:00:00 PM UTC -const int32_t nS4HardforkHeight = 1922000; //dPoW Season 4 2020 hardfork Sunday, June 14th, 2020 - -const uint32_t nS5Timestamp = 1623682800; //dPoW Season 5 Monday, June 14th, 2021 (03:00:00 PM UTC) -const int32_t nS5HardforkHeight = 2437300; //dPoW Season 5 Monday, June 14th, 2021 #define _COINBASE_MATURITY 100 int COINBASE_MATURITY = _COINBASE_MATURITY;//100; diff --git a/src/komodo_hardfork.cpp b/src/komodo_hardfork.cpp new file mode 100644 index 00000000000..5f70f7bbba6 --- /dev/null +++ b/src/komodo_hardfork.cpp @@ -0,0 +1,417 @@ +#include "komodo_hardfork.h" + +const uint32_t nStakedDecemberHardforkTimestamp = 1576840000; //December 2019 hardfork 12/20/2019 @ 11:06am (UTC) +const int32_t nDecemberHardforkHeight = 1670000; //December 2019 hardfork + +const uint32_t nS4Timestamp = 1592146800; //dPoW Season 4 2020 hardfork Sunday, June 14th, 2020 03:00:00 PM UTC +const int32_t nS4HardforkHeight = 1922000; //dPoW Season 4 2020 hardfork Sunday, June 14th, 2020 + +const uint32_t nS5Timestamp = 1623682800; //dPoW Season 5 Monday, June 14th, 2021 (03:00:00 PM UTC) +const int32_t nS5HardforkHeight = 2437300; //dPoW Season 5 Monday, June 14th, 2021 + +const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, 1751328000}; +const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, 7113400}; + +// Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. +const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = +{ + { + { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, + { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, + { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, + { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, + { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 + { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, + { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, + { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, + { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, + { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15 + { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, + { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, + { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, + { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, + { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 + { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, + { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, + { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, + { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 + { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, + { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, + { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, + { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, + { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, + { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, + { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, + { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 + { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, + { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, + { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, + { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, + { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, + { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, + { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, + { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 + { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, + { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, + { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, + { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, + { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, + { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, + { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, + { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, + { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, + { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 + { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, + { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } + }, + { + {"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, + {"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" }, + {"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" }, + {"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" }, + {"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, + {"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, + {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, + {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, + {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, + {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 + {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, + {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, + {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, + {"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" }, + {"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" }, + {"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, + {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 + {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, + {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, + {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, + {"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" }, + {"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" }, + {"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" }, + {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, + {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" }, + {"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" }, + {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, + {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, + {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, + {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 + {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, + {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" }, + {"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" }, + {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, + {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, + {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, + {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 + {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, + {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, + {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, + {"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, + {"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, + {"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" }, + {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, + {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, + {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, + {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 + {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, + {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, + {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, + }, + { + {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 + {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, + {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, + {"dwy_EU", "021c7cf1f10c4dc39d13451123707ab780a741feedab6ac449766affe37515a29e" }, + {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, + {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, + {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, + {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, + {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, + {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, + {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, + {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, + {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, + {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, + {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 + {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, + {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, + {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, + {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, + {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, + {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, + {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, + {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 + {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, + {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, + {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, + {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, + {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, + {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, + {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, + {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 + {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, + {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, + {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, + {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, + {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, + {"dwy_SH", "036536d2d52d85f630b68b050f29ea1d7f90f3b42c10f8c5cdf3dbe1359af80aff" }, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 + {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, + {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, + {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 + }, + { + // Season 3.5 + {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 + {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, + {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, + {"hunter_EU", "0378224b4e9d8a0083ce36f2963ec0a4e231ec06b0c780de108e37f41181a89f6a" }, // FIXME verify this, kolo. Change name if you want + {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, + {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, + {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, + {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, + {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 + {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, + {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, + {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, + {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, + {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, + {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, + {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 + {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, + {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, + {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, + {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, + {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, + {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, + {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, + {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, + {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 + {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, + {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, + {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, + {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, + {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, + {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, + {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, + {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, + {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 + {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, + {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, + {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, + {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, + {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, + {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, + {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, + {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, + {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 + {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, + {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, + {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, + {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, + {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, + {"hunter_SH", "02407db70ad30ce4dfaee8b4ae35fae88390cad2b0ba0373fdd6231967537ccfdf" }, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 + {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, + {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, + {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 + }, + { + // Season 4 + { "alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, + { "alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, + { "strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405" }, + { "titomane_SH", "020014ad4eedf6b1aeb0ad3b101a58d0a2fc570719e46530fd98d4e585f63eb4ae" }, + { "fullmoon_AR", "03b251095e747f759505ec745a4bbff9a768b8dce1f65137300b7c21efec01a07a" }, + { "phba2061_EU", "03a9492d2a1601d0d98cfe94d8adf9689d1bb0e600088127a4f6ca937761fb1c66" }, + { "fullmoon_NA", "03931c1d654a99658998ce0ddae108d825943a821d1cddd85e948ac1d483f68fb6" }, + { "fullmoon_SH", "03c2a1ed9ddb7bb8344328946017b9d8d1357b898957dd6aaa8c190ae26740b9ff" }, + { "madmax_AR", "022be5a2829fa0291f9a51ff7aeceef702eef581f2611887c195e29da49092e6de" }, + { "titomane_EU", "0285cf1fdba761daf6f1f611c32d319cd58214972ef822793008b69dde239443dd" }, + { "cipi_NA", "022c6825a24792cc3b010b1531521eba9b5e2662d640ed700fd96167df37e75239" }, + { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, + { "decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, + { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, + { "madmax_NA", "02997b7ab21b86bbea558ae79acc35d62c9cedf441578f78112f986d72e8eece08" }, + { "chainzilla_SH", "02288ba6dc57936b59d60345e397d62f5d7e7d975f34ed5c2f2e23288325661563" }, + { "peer2cloud_AR", "0250e7e43a3535731b051d1bcc7dc88fbb5163c3fe41c5dee72bd973bcc4dca9f2" }, + { "pirate_EU", "0231c0f50a06655c3d2edf8d7e722d290195d49c78d50de7786b9d196e8820c848" }, + { "webworker01_NA", "02dfd5f3cef1142879a7250752feb91ddd722c497fb98c7377c0fcc5ccc201bd55" }, + { "zatjum_SH", "036066fd638b10e555597623e97e032b28b4d1fa5a13c2b0c80c420dbddad236c2" }, + { "titomane_AR", "0268203a4c80047edcd66385c22e764ea5fb8bc42edae389a438156e7dca9a8251" }, + { "chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d" }, + { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, + { "patchkez_SH", "02cabd6c5fc0b5476c7a01e9d7b907e9f0a051d7f4f731959955d3f6b18ee9a242" }, + { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, + { "etszombi_EU", "0341adbf238f33a33cc895633db996c3ad01275313ac6641e046a3db0b27f1c880" }, + { "pirate_NA", "02207f27a13625a0b8caef6a7bb9de613ff16e4a5f232da8d7c235c7c5bad72ffe" }, + { "metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, + { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, + { "chainmakers_NA", "029415a1609c33dfe4a1016877ba35f9265d25d737649f307048efe96e76512877" }, + { "mihailo_EU", "037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941" }, + { "tonyl_AR", "0299684d7291abf90975fa493bf53212cf1456c374aa36f83cc94daece89350ae9" }, + { "alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8" }, + { "pungocloud_SH", "025b97d8c23effaca6fa7efacce20bf54df73081b63004a0fe22f3f98fece5669f" }, + { "node9_EU", "029ffa793b5c3248f8ea3da47fa3cf1810dada5af032ecd0e37bab5b92dd63b34e" }, + { "smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac" }, + { "nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b" }, + { "gcharang_SH", "02ec4172eab854a0d8cd32bc691c83e93975a3df5a4a453a866736c56e025dc359" }, + { "cipi_EU", "02f2b6defff1c544202f66e47cfd6909c54d67c7c39b9c2a99f137dbaf6d0bd8fa" }, + { "etszombi_AR", "0329944b0ac65b6760787ede042a2fde0be9fca1d80dd756bc0ee0b98d389b7682" }, + { "pbca26_NA", "0387e0fb6f2ca951154c87e16c6cbf93a69862bb165c1a96bcd8722b3af24fe533" }, + { "mylo_SH", "03b58f57822e90fe105e6efb63fd8666033ea503d6cc165b1e479bbd8c2ba033e8" }, + { "swisscertifiers_EU", "03ebcc71b42d88994b8b2134bcde6cb269bd7e71a9dd7616371d9294ec1c1902c5" }, + { "marmarachain_AR", "035bbd81a098172592fe97f50a0ce13cbbf80e55cc7862eccdbd7310fab8a90c4c" }, + { "karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d" }, + { "phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, + { "oszy_EU", "03d1ffd680491b98a3ec5541715681d1a45293c8efb1722c32392a1d792622596a" }, + { "chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005" }, + { "dragonhound_NA", "0227e5cad3731e381df157de189527aac8eb50d82a13ce2bd81153984ebc749515" }, + { "strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a" }, + { "madmax_EU", "02ea0cf4d6d151d0528b07efa79cc7403d77cb9195e2e6c8374f5074b9a787e287" }, + { "dudezmobi_AR", "027ecd974ff2a27a37ee69956cd2e6bb31a608116206f3e31ef186823420182450" }, + { "daemonfox_NA", "022d6f4885f53cbd668ad7d03d4f8e830c233f74e3a918da1ed247edfc71820b3d" }, + { "nutellalicka_SH", "02f4b1e71bc865a79c05fe333952b97cb040d8925d13e83925e170188b3011269b" }, + { "starfleet_EU", "025c7275bd750936862b47793f1f0bb3cbed60fb75a48e7da016e557925fe375eb" }, + { "mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4" }, + { "greer_NA", "03e0995615d7d3cf1107effa6bdb1133e0876cf1768e923aa533a4e2ee675ec383" }, + { "mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043" }, + { "decker_EU", "03777777caebce56e17ca3aae4e16374335b156f1dd62ee3c7f8799c6b885f5560" }, + { "dappvader_SH", "02962e2e5af746632016bc7b24d444f7c90141a5f42ce54e361b302cf455d90e6a" }, + { "alright_DEV", "02b73a589d61691efa2ada15c006d27bc18493fea867ce6c14db3d3d28751f8ce3" }, + { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, + { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, + { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } + }, + { + // Season 5 + {"alrighttt_DEV", "03483166d8663beeb48a493eec161bf506df1906153b6259f7ca617e4cb8110260"}, // 0 + {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, + {"artempikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, + {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, + {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, + {"shadowbit_AR", "02909c79a198179c193fb85bbd4ba09b875a5a9bd481fec284658188b96ed43519"}, + {"goldenman_AR", "0345b888e5de9c11871c080212ccaebf8a3d77b05fe3d535336efc5c7df334bbc7"}, + {"kolo_AR", "0281d3c7bf067088b9572b4d906afca2083a71a38b1011878ecd347651d00af433"}, + {"madmax_AR", "02f729b8df4dacdc8d811416eb32e98a5cc37023b42c81b77d1c00881de879a99a"}, + {"mcrypt_AR", "029bdb33b08f96524082490f4373bc6026b92bcaef9bc521a840a799c73b75ed80"}, + {"mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4"}, // 10 + {"ocean_AR", "03c2bc8c57a001a788851fedc33ce72797ee8fe26eaa3abb1b807727e4867a3105"}, + {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, + {"tokel_AR", "03f3bf697173e47de7bae2ae02b3d3bcf28133a47db72f2a0266061597aaa7779d"}, + {"tonyl_AR", "029ad03929ec295e9164e2bfb9f0e0102c280d5e5212503d079d2d99ab492a9106"}, + {"tonyl_DEV", "02342ec82b31a016b71cd1eb2f482a74f63172e1029ba2fb18f0def3bd4fc0668a"}, + {"artem_DEV", "036b9848396ddcdb9bb58ddab2c24b710b8e4e9b0ee084a00518505ecd9e9fe174"}, + {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, + {"alienx_EU", "026afe5b112d1b39e0edafd5e051e261a676104460581f3673f26ceff7f1e6c56c"}, + {"ca333_EU", "03ffb8072f78304c42ae9b60435f6c3296cbc72de129ae49bba175a65c31c9a7e2"}, + {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, // 20 + {"cipi_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, + {"cipi2_EU", "0202e430157486503f4bde3d3ca770c8f1e2447cf480a6b273b5265b9620f585e3"}, + {"shadowbit_EU", "02668f5f723584f97f5e6f9196fc31018f36a6cf824c60328ad0c097a785df4745"}, + {"komodopioneers_EU", "0351f7f2a6ecce863e4e774bfafe2e59e151c08bf8f350286763a6b8ed97274b82"}, + {"madmax_EU", "028d04f7ccae0d9d57bfa801c4f1e32c707c17589b3c08a0ce08d44eab637eb66b"}, + {"marmarachain_EU", "023a858bbc3f0c6df5b74243315028e968c2f299d84ea8ecc0b28b5f0e2ad24c3c"}, + {"node-9_EU", "03c375924aac39d0c49de6690199e4d08d10fed6725988dcf5d2486661b5e3a656"}, + {"slyris_EU", "021cb6365c13cb35aad4b70aa18b63a75d1d4b9797a0754d3d0142d6fedc83b24e"}, + {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, + {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, // 30 + {"shadowbit_DEV", "02ca882f153e715091a2dbc5409096f8c109d9fe6506ca7a918056dd37162b6f6e"}, + {"gcharang_DEV", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, + {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, + {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, + {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, + {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, + {"dragonhound_NA", "02e650819f4d1cabeaad6bc5ec8c0722a89e63059a10f8b5e97c983c321608329b"}, + {"hyper_NA", "030994a303b26df6e7c6ed456f069c5de9e200e1380bebc5ed8ebe0f834f477f3d"}, + {"madmax_NA", "03898aec46014e8619e2369cc85073048dad05d3c5bf696d8b524db78a39ae5beb"}, + {"node-9_NA", "02f697eed99fd21f2f0eaad81d13543a75c576f669bfddbcbeef0f7625fea2e9d5"}, // 40 + {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, + {"pbca26_NA", "0332543ff1287604afd67f63af0aa0b263aef14fe1850b85db16b81462eed834fd"}, + {"ptyx_NA", "02cbda9c43a794f2134a11815fe86dca017990269accb139e962d764c011c9a4d7"}, + {"strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405"}, + {"karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d"}, + {"webworker01_NA", "0376558d13c31cf9c664a1b5e58f4fff7153777069bef7a66ed8c8526b99787a9e"}, + {"yurii_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, + {"ca333_DEV", "03d885e292842912bd990299ebce33451a5a01cb14e4874d90770efb22e82ef40f"}, + {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, + {"collider_SH", "03bd0022a55a2ead52fd65b317186743374ad320f3704d459f41797e264d1ec854"}, // 50 + {"dappvader_SH", "02bffea7911e09ad9a7df54af0c225516478d3ba138e65061aa8d4b9756bb4c8f4"}, + {"drkush_SH", "030b31cc9528566422e25f3e9b96541ab3626c0dea0e7aa3c0b0bd96039eae2f5a"}, + {"majora31_SH", "033bf21f039a1c832effad208d564e02e968f11e3a3aa41c42e3b748a232fb33f3"}, + {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, + {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309"}, + {"mylo_SH", "03458dca36e800d5bc121d8c0d35f9fc6282880a79fee2d7e050f887b797bc7d6e"}, + {"nutellaLicka_SH", "03a495962a9e9eca06ee3b8ab4cd94e6ea0d87dd39d334ad85a524c4fece1a3db7"}, + {"pbca26_SH", "02c62877e96fc414f2444edf0601abff9d5d2f9078e49fa867ba5305f3c5b3beb0"}, + {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, + {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, // 60 + {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, + {"strobnidan_SH", "02b967fde3686d45056343e488997d4c53f25cd7ad38548cd12b136010a09295ae"}, + {"dragonhound_DEV", "038e010c33c56b61389409eea5597fe17967398731e23185c84c472a16fc5d34ab"} + } +}; diff --git a/src/komodo_hardfork.h b/src/komodo_hardfork.h index be6d2d8b29f..85cbcb1d156 100644 --- a/src/komodo_hardfork.h +++ b/src/komodo_hardfork.h @@ -14,412 +14,11 @@ extern const int32_t nS4HardforkHeight; //dPoW Season 4 2020 hardfork extern const uint32_t nS5Timestamp; //dPoW Season 5 June 14th, 2021 hardfork (03:00:00 PM UTC) (defined in komodo_globals.h) extern const int32_t nS5HardforkHeight; //dPoW Season 5 June 14th, 2021 hardfork estimated block height (defined in komodo_globals.h) -static const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS] = {1525132800, 1563148800, nStakedDecemberHardforkTimestamp, nS4Timestamp, nS5Timestamp, 1751328000}; -static const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS] = {814000, 1444000, nDecemberHardforkHeight, nS4HardforkHeight, nS5HardforkHeight, 7113400}; +extern const uint32_t KMD_SEASON_TIMESTAMPS[NUM_KMD_SEASONS]; +extern const int32_t KMD_SEASON_HEIGHTS[NUM_KMD_SEASONS]; // Era array of pubkeys. Add extra seasons to bottom as requried, after adding appropriate info above. -static const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2] = -{ - { - { "0_jl777_testA", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - { "0_jl777_testB", "02ebfc784a4ba768aad88d44d1045d240d47b26e248cafaf1c5169a42d7a61d344" }, - { "0_kolo_testA", "0287aa4b73988ba26cf6565d815786caf0d2c4af704d7883d163ee89cd9977edec" }, - { "artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, - { "artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, - { "artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - { "artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, - { "badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - { "badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, - { "badass_SH", "026b49dd3923b78a592c1b475f208e23698d3f085c4c3b4906a59faf659fd9530b" }, - { "crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, // 10 - { "crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, - { "crackers_SH", "02be28310e6312d1dd44651fd96f6a44ccc269a321f907502aae81d246fabdb03e" }, - { "durerus_EU", "02bcbd287670bdca2c31e5d50130adb5dea1b53198f18abeec7211825f47485d57" }, - { "etszombi_AR", "031c79168d15edabf17d9ec99531ea9baa20039d0cdc14d9525863b83341b210e9" }, - { "etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, // 15 - { "etszombi_SH", "025d7a193c0757f7437fad3431f027e7b5ed6c925b77daba52a8755d24bf682dde" }, - { "farl4web_EU", "0300ecf9121cccf14cf9423e2adb5d98ce0c4e251721fa345dec2e03abeffbab3f" }, - { "farl4web_SH", "0396bb5ed3c57aa1221d7775ae0ff751e4c7dc9be220d0917fa8bbdf670586c030" }, - { "fullmoon_AR", "0254b1d64840ce9ff6bec9dd10e33beb92af5f7cee628f999cb6bc0fea833347cc" }, - { "fullmoon_NA", "031fb362323b06e165231c887836a8faadb96eda88a79ca434e28b3520b47d235b" }, // 20 - { "fullmoon_SH", "030e12b42ec33a80e12e570b6c8274ce664565b5c3da106859e96a7208b93afd0d" }, - { "grewal_NA", "03adc0834c203d172bce814df7c7a5e13dc603105e6b0adabc942d0421aefd2132" }, - { "grewal_SH", "03212a73f5d38a675ee3cdc6e82542a96c38c3d1c79d25a1ed2e42fcf6a8be4e68" }, - { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - { "jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - { "jsgalt_NA", "027b3fb6fede798cd17c30dbfb7baf9332b3f8b1c7c513f443070874c410232446" }, - { "karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, // 30 - { "kashifali_EU", "033777c52a0190f261c6f66bd0e2bb299d30f012dcb8bfff384103211edb8bb207" }, - { "kolo_AR", "03016d19344c45341e023b72f9fb6e6152fdcfe105f3b4f50b82a4790ff54e9dc6" }, - { "kolo_SH", "02aa24064500756d9b0959b44d5325f2391d8e95c6127e109184937152c384e185" }, - { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - { "movecrypto_AR", "022783d94518e4dc77cbdf1a97915b29f427d7bc15ea867900a76665d3112be6f3" }, - { "movecrypto_EU", "021ab53bc6cf2c46b8a5456759f9d608966eff87384c2b52c0ac4cc8dd51e9cc42" }, - { "movecrypto_NA", "02efb12f4d78f44b0542d1c60146738e4d5506d27ec98a469142c5c84b29de0a80" }, - { "movecrypto_SH", "031f9739a3ebd6037a967ce1582cde66e79ea9a0551c54731c59c6b80f635bc859" }, - { "muros_AR", "022d77402fd7179335da39479c829be73428b0ef33fb360a4de6890f37c2aa005e" }, - { "noashh_AR", "029d93ef78197dc93892d2a30e5a54865f41e0ca3ab7eb8e3dcbc59c8756b6e355" }, // 40 - { "noashh_EU", "02061c6278b91fd4ac5cab4401100ffa3b2d5a277e8f71db23401cc071b3665546" }, - { "noashh_NA", "033c073366152b6b01535e15dd966a3a8039169584d06e27d92a69889b720d44e1" }, - { "nxtswe_EU", "032fb104e5eaa704a38a52c126af8f67e870d70f82977e5b2f093d5c1c21ae5899" }, - { "polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - { "pondsea_AR", "032e1c213787312099158f2d74a89e8240a991d162d4ce8017d8504d1d7004f735" }, - { "pondsea_EU", "0225aa6f6f19e543180b31153d9e6d55d41bc7ec2ba191fd29f19a2f973544e29d" }, - { "pondsea_NA", "031bcfdbb62268e2ff8dfffeb9ddff7fe95fca46778c77eebff9c3829dfa1bb411" }, - { "pondsea_SH", "02209073bc0943451498de57f802650311b1f12aa6deffcd893da198a544c04f36" }, - { "popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, - { "popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, // 50 - { "ptytrader_NA", "0328c61467148b207400b23875234f8a825cce65b9c4c9b664f47410b8b8e3c222" }, - { "ptytrader_SH", "0250c93c492d8d5a6b565b90c22bee07c2d8701d6118c6267e99a4efd3c7748fa4" }, - { "rnr_AR", "029bdb08f931c0e98c2c4ba4ef45c8e33a34168cb2e6bf953cef335c359d77bfcd" }, - { "rnr_EU", "03f5c08dadffa0ffcafb8dd7ffc38c22887bd02702a6c9ac3440deddcf2837692b" }, - { "rnr_NA", "02e17c5f8c3c80f584ed343b8dcfa6d710dfef0889ec1e7728ce45ce559347c58c" }, - { "rnr_SH", "037536fb9bdfed10251f71543fb42679e7c52308bcd12146b2568b9a818d8b8377" }, - { "titomane_AR", "03cda6ca5c2d02db201488a54a548dbfc10533bdc275d5ea11928e8d6ab33c2185" }, - { "titomane_EU", "02e41feded94f0cc59f55f82f3c2c005d41da024e9a805b41105207ef89aa4bfbd" }, - { "titomane_SH", "035f49d7a308dd9a209e894321f010d21b7793461b0c89d6d9231a3fe5f68d9960" }, - { "vanbreuk_EU", "024f3cad7601d2399c131fd070e797d9cd8533868685ddbe515daa53c2e26004c3" }, // 60 - { "xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, - { "xxspot1_XX", "02ef445a392fcaf3ad4176a5da7f43580e8056594e003eba6559a713711a27f955" }, - { "xxspot2_XX", "03d85b221ea72ebcd25373e7961f4983d12add66a92f899deaf07bab1d8b6f5573" } - }, - { - {"0dev1_jl777", "03b7621b44118017a16043f19b30cc8a4cfe068ac4e42417bae16ba460c80f3828" }, - {"0dev2_kolo", "030f34af4b908fb8eb2099accb56b8d157d49f6cfb691baa80fdd34f385efed961" }, - {"0dev3_kolo", "025af9d2b2a05338478159e9ac84543968fd18c45fd9307866b56f33898653b014" }, - {"0dev4_decker", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"a-team_SH", "03b59ad322b17cb94080dc8e6dc10a0a865de6d47c16fb5b1a0b5f77f9507f3cce" }, - {"artik_AR", "029acf1dcd9f5ff9c455f8bb717d4ae0c703e089d16cf8424619c491dff5994c90" }, - {"artik_EU", "03f54b2c24f82632e3cdebe4568ba0acf487a80f8a89779173cdb78f74514847ce" }, - {"artik_NA", "0224e31f93eff0cc30eaf0b2389fbc591085c0e122c4d11862c1729d090106c842" }, - {"artik_SH", "02bdd8840a34486f38305f311c0e2ae73e84046f6e9c3dd3571e32e58339d20937" }, - {"badass_EU", "0209d48554768dd8dada988b98aca23405057ac4b5b46838a9378b95c3e79b9b9e" }, - {"badass_NA", "02afa1a9f948e1634a29dc718d218e9d150c531cfa852843a1643a02184a63c1a7" }, // 10 - {"batman_AR", "033ecb640ec5852f42be24c3bf33ca123fb32ced134bed6aa2ba249cf31b0f2563" }, - {"batman_SH", "02ca5898931181d0b8aafc75ef56fce9c43656c0b6c9f64306e7c8542f6207018c" }, - {"ca333_EU", "03fc87b8c804f12a6bd18efd43b0ba2828e4e38834f6b44c0bfee19f966a12ba99" }, - {"chainmakers_EU", "02f3b08938a7f8d2609d567aebc4989eeded6e2e880c058fdf092c5da82c3bc5ee" }, - {"chainmakers_NA", "0276c6d1c65abc64c8559710b8aff4b9e33787072d3dda4ec9a47b30da0725f57a" }, - {"chainstrike_SH", "0370bcf10575d8fb0291afad7bf3a76929734f888228bc49e35c5c49b336002153" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"crackers_EU", "03bc819982d3c6feb801ec3b720425b017d9b6ee9a40746b84422cbbf929dc73c3" }, - {"crackers_NA", "03205049103113d48c7c7af811b4c8f194dafc43a50d5313e61a22900fc1805b45" }, // 20 - {"dwy_EU", "0259c646288580221fdf0e92dbeecaee214504fdc8bbdf4a3019d6ec18b7540424" }, - {"emmanux_SH", "033f316114d950497fc1d9348f03770cd420f14f662ab2db6172df44c389a2667a" }, - {"etszombi_EU", "0281b1ad28d238a2b217e0af123ce020b79e91b9b10ad65a7917216eda6fe64bf7" }, - {"fullmoon_AR", "03380314c4f42fa854df8c471618751879f9e8f0ff5dbabda2bd77d0f96cb35676" }, - {"fullmoon_NA", "030216211d8e2a48bae9e5d7eb3a42ca2b7aae8770979a791f883869aea2fa6eef" }, - {"fullmoon_SH", "03f34282fa57ecc7aba8afaf66c30099b5601e98dcbfd0d8a58c86c20d8b692c64" }, - {"goldenman_EU", "02d6f13a8f745921cdb811e32237bb98950af1a5952be7b3d429abd9152f8e388d" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, // 30 - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"jackson_AR", "038ff7cfe34cb13b524e0941d5cf710beca2ffb7e05ddf15ced7d4f14fbb0a6f69" }, - {"jeezy_EU", "023cb3e593fb85c5659688528e9a4f1c4c7f19206edc7e517d20f794ba686fd6d6" }, - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"komodoninja_EU", "038e567b99806b200b267b27bbca2abf6a3e8576406df5f872e3b38d30843cd5ba" }, - {"komodoninja_SH", "033178586896915e8456ebf407b1915351a617f46984001790f0cce3d6f3ada5c2" }, - {"komodopioneers_SH", "033ace50aedf8df70035b962a805431363a61cc4e69d99d90726a2d48fb195f68c" }, - {"libscott_SH", "03301a8248d41bc5dc926088a8cf31b65e2daf49eed7eb26af4fb03aae19682b95" }, - {"lukechilds_AR", "031aa66313ee024bbee8c17915cf7d105656d0ace5b4a43a3ab5eae1e14ec02696" }, - {"madmax_AR", "03891555b4a4393d655bf76f0ad0fb74e5159a615b6925907678edc2aac5e06a75" }, // 40 - {"meshbits_AR", "02957fd48ae6cb361b8a28cdb1b8ccf5067ff68eb1f90cba7df5f7934ed8eb4b2c" }, - {"meshbits_SH", "025c6e94877515dfd7b05682b9cc2fe4a49e076efe291e54fcec3add78183c1edb" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"patchkez_SH", "0296270f394140640f8fa15684fc11255371abb6b9f253416ea2734e34607799c4" }, - {"pbca26_NA", "0276aca53a058556c485bbb60bdc54b600efe402a8b97f0341a7c04803ce204cb5" }, - {"peer2cloud_AR", "034e5563cb885999ae1530bd66fab728e580016629e8377579493b386bf6cebb15" }, - {"peer2cloud_SH", "03396ac453b3f23e20f30d4793c5b8ab6ded6993242df4f09fd91eb9a4f8aede84" }, - {"polycryptoblog_NA", "02708dcda7c45fb54b78469673c2587bfdd126e381654819c4c23df0e00b679622" }, - {"hyper_AR", "020f2f984d522051bd5247b61b080b4374a7ab389d959408313e8062acad3266b4" }, // 50 - {"hyper_EU", "03d00cf9ceace209c59fb013e112a786ad583d7de5ca45b1e0df3b4023bb14bf51" }, - {"hyper_SH", "0383d0b37f59f4ee5e3e98a47e461c861d49d0d90c80e9e16f7e63686a2dc071f3" }, - {"hyper_NA", "03d91c43230336c0d4b769c9c940145a8c53168bf62e34d1bccd7f6cfc7e5592de" }, - {"popcornbag_AR", "02761f106fb34fbfc5ddcc0c0aa831ed98e462a908550b280a1f7bd32c060c6fa3" }, - {"popcornbag_NA", "03c6085c7fdfff70988fda9b197371f1caf8397f1729a844790e421ee07b3a93e8" }, - {"alien_AR", "0348d9b1fc6acf81290405580f525ee49b4749ed4637b51a28b18caa26543b20f0" }, - {"alien_EU", "020aab8308d4df375a846a9e3b1c7e99597b90497efa021d50bcf1bbba23246527" }, - {"thegaltmines_NA", "031bea28bec98b6380958a493a703ddc3353d7b05eb452109a773eefd15a32e421" }, - {"titomane_AR", "029d19215440d8cb9cc6c6b7a4744ae7fb9fb18d986e371b06aeb34b64845f9325" }, - {"titomane_EU", "0360b4805d885ff596f94312eed3e4e17cb56aa8077c6dd78d905f8de89da9499f" }, // 60 - {"titomane_SH", "03573713c5b20c1e682a2e8c0f8437625b3530f278e705af9b6614de29277a435b" }, - {"webworker01_NA", "03bb7d005e052779b1586f071834c5facbb83470094cff5112f0072b64989f97d7" }, - {"xrobesx_NA", "03f0cc6d142d14a40937f12dbd99dbd9021328f45759e26f1877f2a838876709e1" }, - }, - { - {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 - {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, - {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, - {"dwy_EU", "021c7cf1f10c4dc39d13451123707ab780a741feedab6ac449766affe37515a29e" }, - {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, - {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, - {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, - {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, - {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, - {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, - {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, - {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, - {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, - {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, - {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 - {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, - {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, - {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, - {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, - {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, - {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, - {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, - {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 - {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, - {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, - {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, - {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, - {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, - {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, - {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, - {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 - {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, - {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, - {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, - {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, - {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, - {"dwy_SH", "036536d2d52d85f630b68b050f29ea1d7f90f3b42c10f8c5cdf3dbe1359af80aff" }, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 - {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, - {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, - {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 - }, - { - // Season 3.5 - {"madmax_NA", "0237e0d3268cebfa235958808db1efc20cc43b31100813b1f3e15cc5aa647ad2c3" }, // 0 - {"alright_AR", "020566fe2fb3874258b2d3cf1809a5d650e0edc7ba746fa5eec72750c5188c9cc9" }, - {"strob_NA", "0206f7a2e972d9dfef1c424c731503a0a27de1ba7a15a91a362dc7ec0d0fb47685" }, - {"hunter_EU", "0378224b4e9d8a0083ce36f2963ec0a4e231ec06b0c780de108e37f41181a89f6a" }, // FIXME verify this, kolo. Change name if you want - {"phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - {"chainmakers_NA", "02285d813c30c0bf7eefdab1ff0a8ad08a07a0d26d8b95b3943ce814ac8e24d885" }, - {"indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - {"blackjok3r_SH", "021eac26dbad256cbb6f74d41b10763183ee07fb609dbd03480dd50634170547cc" }, - {"chainmakers_EU", "03fdf5a3fce8db7dee89724e706059c32e5aa3f233a6b6cc256fea337f05e3dbf7" }, - {"titomane_AR", "023e3aa9834c46971ff3e7cb86a200ec9c8074a9566a3ea85d400d5739662ee989" }, - {"fullmoon_SH", "023b7252968ea8a955cd63b9e57dee45a74f2d7ba23b4e0595572138ad1fb42d21" }, // 10 - {"indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - {"chmex_EU", "0281304ebbcc39e4f09fda85f4232dd8dacd668e20e5fc11fba6b985186c90086e" }, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - {"ca333_DEV", "02856843af2d9457b5b1c907068bef6077ea0904cc8bd4df1ced013f64bf267958" }, - {"cipi_NA", "02858904a2a1a0b44df4c937b65ee1f5b66186ab87a751858cf270dee1d5031f18" }, - {"pungocloud_SH", "024dfc76fa1f19b892be9d06e985d0c411e60dbbeb36bd100af9892a39555018f6" }, - {"voskcoin_EU", "034190b1c062a04124ad15b0fa56dfdf34aa06c164c7163b6aec0d654e5f118afb" }, - {"decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" }, - {"cryptoeconomy_EU", "0290ab4937e85246e048552df3e9a66cba2c1602db76e03763e16c671e750145d1" }, - {"etszombi_EU", "0293ea48d8841af7a419a24d9da11c34b39127ef041f847651bae6ab14dcd1f6b4" }, // 20 - {"karasugoi_NA", "02a348b03b9c1a8eac1b56f85c402b041c9bce918833f2ea16d13452309052a982" }, - {"pirate_AR", "03e29c90354815a750db8ea9cb3c1b9550911bb205f83d0355a061ac47c4cf2fde" }, - {"metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - {"zatjum_SH", "02d6b0c89cacd58a0af038139a9a90c9e02cd1e33803a1f15fceabea1f7e9c263a" }, - {"madmax_AR", "03c5941fe49d673c094bc8e9bb1a95766b4670c88be76d576e915daf2c30a454d3" }, - {"lukechilds_NA", "03f1051e62c2d280212481c62fe52aab0a5b23c95de5b8e9ad5f80d8af4277a64b" }, - {"cipi_AR", "02c4f89a5b382750836cb787880d30e23502265054e1c327a5bfce67116d757ce8" }, - {"tonyl_AR", "02cc8bc862f2b65ad4f99d5f68d3011c138bf517acdc8d4261166b0be8f64189e1" }, - {"infotech_DEV", "0345ad4ab5254782479f6322c369cec77a7535d2f2162d103d666917d5e4f30c4c" }, - {"fullmoon_NA", "032c716701fe3a6a3f90a97b9d874a9d6eedb066419209eed7060b0cc6b710c60b" }, // 30 - {"etszombi_AR", "02e55e104aa94f70cde68165d7df3e162d4410c76afd4643b161dea044aa6d06ce" }, - {"node-9_EU", "0372e5b51e86e2392bb15039bac0c8f975b852b45028a5e43b324c294e9f12e411" }, - {"phba2061_EU", "03f6bd15dba7e986f0c976ea19d8a9093cb7c989d499f1708a0386c5c5659e6c4e" }, - {"indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - {"and1-89_EU", "02736cbf8d7b50835afd50a319f162dd4beffe65f2b1dc6b90e64b32c8e7849ddd" }, - {"komodopioneers_SH", "032a238a5747777da7e819cfa3c859f3677a2daf14e4dce50916fc65d00ad9c52a" }, - {"komodopioneers_EU", "036d02425916444fff8cc7203fcbfc155c956dda5ceb647505836bef59885b6866" }, - {"d0ct0r_NA", "0303725d8525b6f969122faf04152653eb4bf34e10de92182263321769c334bf58" }, - {"kolo_DEV", "02849e12199dcc27ba09c3902686d2ad0adcbfcee9d67520e9abbdda045ba83227" }, - {"peer2cloud_AR", "02acc001fe1fe8fd68685ba26c0bc245924cb592e10cec71e9917df98b0e9d7c37" }, // 40 - {"webworker01_SH", "031e50ba6de3c16f99d414bb89866e578d963a54bde7916c810608966fb5700776" }, - {"webworker01_NA", "032735e9cad1bb00eaababfa6d27864fa4c1db0300c85e01e52176be2ca6a243ce" }, - {"pbca26_NA", "03a97606153d52338bcffd1bf19bb69ef8ce5a7cbdc2dbc3ff4f89d91ea6bbb4dc" }, - {"indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - {"pirate_NA", "0255e32d8a56671dee8aa7f717debb00efa7f0086ee802de0692f2d67ee3ee06ee" }, - {"lukechilds_AR", "025c6a73ff6d750b9ddf6755b390948cffdd00f344a639472d398dd5c6b4735d23" }, - {"dragonhound_NA", "0224a9d951d3a06d8e941cc7362b788bb1237bb0d56cc313e797eb027f37c2d375" }, - {"fullmoon_AR", "03da64dd7cd0db4c123c2f79d548a96095a5a103e5b9d956e9832865818ffa7872" }, - {"chainzilla_SH", "0360804b8817fd25ded6e9c0b50e3b0782ac666545b5416644198e18bc3903d9f9" }, - {"titomane_EU", "03772ac0aad6b0e9feec5e591bff5de6775d6132e888633e73d3ba896bdd8e0afb" }, // 50 - {"jeezy_EU", "037f182facbad35684a6e960699f5da4ba89e99f0d0d62a87e8400dd086c8e5dd7" }, - {"titomane_SH", "03850fdddf2413b51790daf51dd30823addb37313c8854b508ea6228205047ef9b" }, - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - {"pirate_EU", "03fff24efd5648870a23badf46e26510e96d9e79ce281b27cfe963993039dd1351" }, - {"thegaltmines_NA", "02db1a16c7043f45d6033ccfbd0a51c2d789b32db428902f98b9e155cf0d7910ed" }, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4" }, - {"nutellalicka_SH", "02f7d90d0510c598ce45915e6372a9cd0ba72664cb65ce231f25d526fc3c5479fc" }, - {"chainstrike_SH", "03b806be3bf7a1f2f6290ec5c1ea7d3ea57774dcfcf2129a82b2569e585100e1cb" }, - {"hunter_SH", "02407db70ad30ce4dfaee8b4ae35fae88390cad2b0ba0373fdd6231967537ccfdf" }, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, // 60 - {"gt_AR", "0348430538a4944d3162bb4749d8c5ed51299c2434f3ee69c11a1f7815b3f46135" }, - {"patchkez_SH", "03f45e9beb5c4cd46525db8195eb05c1db84ae7ef3603566b3d775770eba3b96ee" }, - {"decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, // 63 - }, - { - // Season 4 - { "alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f" }, - { "alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd" }, - { "strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405" }, - { "titomane_SH", "020014ad4eedf6b1aeb0ad3b101a58d0a2fc570719e46530fd98d4e585f63eb4ae" }, - { "fullmoon_AR", "03b251095e747f759505ec745a4bbff9a768b8dce1f65137300b7c21efec01a07a" }, - { "phba2061_EU", "03a9492d2a1601d0d98cfe94d8adf9689d1bb0e600088127a4f6ca937761fb1c66" }, - { "fullmoon_NA", "03931c1d654a99658998ce0ddae108d825943a821d1cddd85e948ac1d483f68fb6" }, - { "fullmoon_SH", "03c2a1ed9ddb7bb8344328946017b9d8d1357b898957dd6aaa8c190ae26740b9ff" }, - { "madmax_AR", "022be5a2829fa0291f9a51ff7aeceef702eef581f2611887c195e29da49092e6de" }, - { "titomane_EU", "0285cf1fdba761daf6f1f611c32d319cd58214972ef822793008b69dde239443dd" }, - { "cipi_NA", "022c6825a24792cc3b010b1531521eba9b5e2662d640ed700fd96167df37e75239" }, - { "indenodes_SH", "0334e6e1ec8285c4b85bd6dae67e17d67d1f20e7328efad17ce6fd24ae97cdd65e" }, - { "decker_AR", "03ffdf1a116300a78729608d9930742cd349f11a9d64fcc336b8f18592dd9c91bc" }, - { "indenodes_EU", "0221387ff95c44cb52b86552e3ec118a3c311ca65b75bf807c6c07eaeb1be8303c" }, - { "madmax_NA", "02997b7ab21b86bbea558ae79acc35d62c9cedf441578f78112f986d72e8eece08" }, - { "chainzilla_SH", "02288ba6dc57936b59d60345e397d62f5d7e7d975f34ed5c2f2e23288325661563" }, - { "peer2cloud_AR", "0250e7e43a3535731b051d1bcc7dc88fbb5163c3fe41c5dee72bd973bcc4dca9f2" }, - { "pirate_EU", "0231c0f50a06655c3d2edf8d7e722d290195d49c78d50de7786b9d196e8820c848" }, - { "webworker01_NA", "02dfd5f3cef1142879a7250752feb91ddd722c497fb98c7377c0fcc5ccc201bd55" }, - { "zatjum_SH", "036066fd638b10e555597623e97e032b28b4d1fa5a13c2b0c80c420dbddad236c2" }, - { "titomane_AR", "0268203a4c80047edcd66385c22e764ea5fb8bc42edae389a438156e7dca9a8251" }, - { "chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d" }, - { "indenodes_NA", "02698c6f1c9e43b66e82dbb163e8df0e5a2f62f3a7a882ca387d82f86e0b3fa988" }, - { "patchkez_SH", "02cabd6c5fc0b5476c7a01e9d7b907e9f0a051d7f4f731959955d3f6b18ee9a242" }, - { "metaphilibert_AR", "02adad675fae12b25fdd0f57250b0caf7f795c43f346153a31fe3e72e7db1d6ac6" }, - { "etszombi_EU", "0341adbf238f33a33cc895633db996c3ad01275313ac6641e046a3db0b27f1c880" }, - { "pirate_NA", "02207f27a13625a0b8caef6a7bb9de613ff16e4a5f232da8d7c235c7c5bad72ffe" }, - { "metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309" }, - { "indenodes_AR", "02ec0fa5a40f47fd4a38ea5c89e375ad0b6ddf4807c99733c9c3dc15fb978ee147" }, - { "chainmakers_NA", "029415a1609c33dfe4a1016877ba35f9265d25d737649f307048efe96e76512877" }, - { "mihailo_EU", "037f9563f30c609b19fd435a19b8bde7d6db703012ba1aba72e9f42a87366d1941" }, - { "tonyl_AR", "0299684d7291abf90975fa493bf53212cf1456c374aa36f83cc94daece89350ae9" }, - { "alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8" }, - { "pungocloud_SH", "025b97d8c23effaca6fa7efacce20bf54df73081b63004a0fe22f3f98fece5669f" }, - { "node9_EU", "029ffa793b5c3248f8ea3da47fa3cf1810dada5af032ecd0e37bab5b92dd63b34e" }, - { "smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac" }, - { "nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b" }, - { "gcharang_SH", "02ec4172eab854a0d8cd32bc691c83e93975a3df5a4a453a866736c56e025dc359" }, - { "cipi_EU", "02f2b6defff1c544202f66e47cfd6909c54d67c7c39b9c2a99f137dbaf6d0bd8fa" }, - { "etszombi_AR", "0329944b0ac65b6760787ede042a2fde0be9fca1d80dd756bc0ee0b98d389b7682" }, - { "pbca26_NA", "0387e0fb6f2ca951154c87e16c6cbf93a69862bb165c1a96bcd8722b3af24fe533" }, - { "mylo_SH", "03b58f57822e90fe105e6efb63fd8666033ea503d6cc165b1e479bbd8c2ba033e8" }, - { "swisscertifiers_EU", "03ebcc71b42d88994b8b2134bcde6cb269bd7e71a9dd7616371d9294ec1c1902c5" }, - { "marmarachain_AR", "035bbd81a098172592fe97f50a0ce13cbbf80e55cc7862eccdbd7310fab8a90c4c" }, - { "karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d" }, - { "phm87_SH", "021773a38db1bc3ede7f28142f901a161c7b7737875edbb40082a201c55dcf0add" }, - { "oszy_EU", "03d1ffd680491b98a3ec5541715681d1a45293c8efb1722c32392a1d792622596a" }, - { "chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005" }, - { "dragonhound_NA", "0227e5cad3731e381df157de189527aac8eb50d82a13ce2bd81153984ebc749515" }, - { "strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a" }, - { "madmax_EU", "02ea0cf4d6d151d0528b07efa79cc7403d77cb9195e2e6c8374f5074b9a787e287" }, - { "dudezmobi_AR", "027ecd974ff2a27a37ee69956cd2e6bb31a608116206f3e31ef186823420182450" }, - { "daemonfox_NA", "022d6f4885f53cbd668ad7d03d4f8e830c233f74e3a918da1ed247edfc71820b3d" }, - { "nutellalicka_SH", "02f4b1e71bc865a79c05fe333952b97cb040d8925d13e83925e170188b3011269b" }, - { "starfleet_EU", "025c7275bd750936862b47793f1f0bb3cbed60fb75a48e7da016e557925fe375eb" }, - { "mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4" }, - { "greer_NA", "03e0995615d7d3cf1107effa6bdb1133e0876cf1768e923aa533a4e2ee675ec383" }, - { "mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043" }, - { "decker_EU", "03777777caebce56e17ca3aae4e16374335b156f1dd62ee3c7f8799c6b885f5560" }, - { "dappvader_SH", "02962e2e5af746632016bc7b24d444f7c90141a5f42ce54e361b302cf455d90e6a" }, - { "alright_DEV", "02b73a589d61691efa2ada15c006d27bc18493fea867ce6c14db3d3d28751f8ce3" }, - { "artemii235_DEV", "03bb616b12430bdd0483653de18733597a4fd416623c7065c0e21fe9d96460add1" }, - { "tonyl_DEV", "02d5f7fd6e25d34ab2f3318d60cdb89ff3a812ec5d0212c4c113bb12d12616cfdc" }, - { "decker_DEV", "028eea44a09674dda00d88ffd199a09c9b75ba9782382cc8f1e97c0fd565fe5707" } - }, - { - // Season 5 - {"alrighttt_DEV", "03483166d8663beeb48a493eec161bf506df1906153b6259f7ca617e4cb8110260"}, // 0 - {"alien_AR", "03911a60395801082194b6834244fa78a3c30ff3e888667498e157b4aa80b0a65f"}, - {"artempikulin_AR", "026a8ed1e4eeeb023cfb8e003e1c1de6a2b771f37e112745ffb8b6e375a9cbfdec"}, - {"chmex_AR", "036c856ea778ea105b93c0be187004d4e51161eda32888aa307b8f72d490884005"}, - {"cipi_AR", "033ae024cdb748e083406a2e20037017a1292079ad6a8161ae5b43f398724fea74"}, - {"shadowbit_AR", "02909c79a198179c193fb85bbd4ba09b875a5a9bd481fec284658188b96ed43519"}, - {"goldenman_AR", "0345b888e5de9c11871c080212ccaebf8a3d77b05fe3d535336efc5c7df334bbc7"}, - {"kolo_AR", "0281d3c7bf067088b9572b4d906afca2083a71a38b1011878ecd347651d00af433"}, - {"madmax_AR", "02f729b8df4dacdc8d811416eb32e98a5cc37023b42c81b77d1c00881de879a99a"}, - {"mcrypt_AR", "029bdb33b08f96524082490f4373bc6026b92bcaef9bc521a840a799c73b75ed80"}, - {"mrlynch_AR", "031987dc82b087cd53e23df5480e265a5928e9243e0e11849fa12359739d8b18a4"}, // 10 - {"ocean_AR", "03c2bc8c57a001a788851fedc33ce72797ee8fe26eaa3abb1b807727e4867a3105"}, - {"smdmitry_AR", "022a2a45979a6631a25e4c96469423de720a2f4c849548957c35a35c91041ee7ac"}, - {"tokel_AR", "03f3bf697173e47de7bae2ae02b3d3bcf28133a47db72f2a0266061597aaa7779d"}, - {"tonyl_AR", "029ad03929ec295e9164e2bfb9f0e0102c280d5e5212503d079d2d99ab492a9106"}, - {"tonyl_DEV", "02342ec82b31a016b71cd1eb2f482a74f63172e1029ba2fb18f0def3bd4fc0668a"}, - {"artem_DEV", "036b9848396ddcdb9bb58ddab2c24b710b8e4e9b0ee084a00518505ecd9e9fe174"}, - {"alien_EU", "03bb749e337b9074465fa28e757b5aa92cb1f0fea1a39589bca91a602834d443cd"}, - {"alienx_EU", "026afe5b112d1b39e0edafd5e051e261a676104460581f3673f26ceff7f1e6c56c"}, - {"ca333_EU", "03ffb8072f78304c42ae9b60435f6c3296cbc72de129ae49bba175a65c31c9a7e2"}, - {"chmex_EU", "025b7209ba37df8d9695a23ea706ea2594863ab09055ca6bf485855937f3321d1d"}, // 20 - {"cipi_EU", "03d6e1f3a693b5d69049791005d7cb64c259a1ad85833f5a9c545d4fee29905009"}, - {"cipi2_EU", "0202e430157486503f4bde3d3ca770c8f1e2447cf480a6b273b5265b9620f585e3"}, - {"shadowbit_EU", "02668f5f723584f97f5e6f9196fc31018f36a6cf824c60328ad0c097a785df4745"}, - {"komodopioneers_EU", "0351f7f2a6ecce863e4e774bfafe2e59e151c08bf8f350286763a6b8ed97274b82"}, - {"madmax_EU", "028d04f7ccae0d9d57bfa801c4f1e32c707c17589b3c08a0ce08d44eab637eb66b"}, - {"marmarachain_EU", "023a858bbc3f0c6df5b74243315028e968c2f299d84ea8ecc0b28b5f0e2ad24c3c"}, - {"node-9_EU", "03c375924aac39d0c49de6690199e4d08d10fed6725988dcf5d2486661b5e3a656"}, - {"slyris_EU", "021cb6365c13cb35aad4b70aa18b63a75d1d4b9797a0754d3d0142d6fedc83b24e"}, - {"smdmitry_EU", "02eb3aad81778f8d6f7e5295c44ca224e5c812f5e43fc1e9ce4ebafc23324183c9"}, - {"van_EU", "03af7f8c82f20671ca1978116353839d3e501523e379bfb52b1e05d7816bb5812f"}, // 30 - {"shadowbit_DEV", "02ca882f153e715091a2dbc5409096f8c109d9fe6506ca7a918056dd37162b6f6e"}, - {"gcharang_DEV", "02cb445948bf0d89f8d61102e12a5ee6e98be61ac7c2cb9ba435219ea9db967117"}, - {"alien_NA", "03bea1ac333b95c8669ec091907ea8713cae26f74b9e886e13593400e21c4d30a8"}, - {"alienx_NA", "02f0b3ef87629509441b1ae95f28108f258a81910e483b90e0496205e24e7069b8"}, - {"cipi_NA", "036cc1d7476e4260601927be0fc8b748ae68d8fec8f5c498f71569a01bd92046c5"}, - {"computergenie_NA", "03a78ae070a5e9e935112cf7ea8293f18950f1011694ea0260799e8762c8a6f0a4"}, - {"dragonhound_NA", "02e650819f4d1cabeaad6bc5ec8c0722a89e63059a10f8b5e97c983c321608329b"}, - {"hyper_NA", "030994a303b26df6e7c6ed456f069c5de9e200e1380bebc5ed8ebe0f834f477f3d"}, - {"madmax_NA", "03898aec46014e8619e2369cc85073048dad05d3c5bf696d8b524db78a39ae5beb"}, - {"node-9_NA", "02f697eed99fd21f2f0eaad81d13543a75c576f669bfddbcbeef0f7625fea2e9d5"}, // 40 - {"nodeone_NA", "03f9dd0484e81174fd50775cb9099691c7d140ff00c0f088847e38dc87da67eb9b"}, - {"pbca26_NA", "0332543ff1287604afd67f63af0aa0b263aef14fe1850b85db16b81462eed834fd"}, - {"ptyx_NA", "02cbda9c43a794f2134a11815fe86dca017990269accb139e962d764c011c9a4d7"}, - {"strob_NA", "02a1c0bd40b294f06d3e44a52d1b2746c260c475c725e9351f1312e49e01c9a405"}, - {"karasugoi_NA", "0262cf2559703464151153c12e00c4b67a969e39b330301fdcaa6667d7eb02c57d"}, - {"webworker01_NA", "0376558d13c31cf9c664a1b5e58f4fff7153777069bef7a66ed8c8526b99787a9e"}, - {"yurii_DEV", "03e57c7341d2c8a3be62e1caaa28978d76a8277dea7bb484fdd8c55dc05e4e4e93"}, - {"ca333_DEV", "03d885e292842912bd990299ebce33451a5a01cb14e4874d90770efb22e82ef40f"}, - {"chmex_SH", "02698305eb3c27a2c724efd2152f9250739355116f201656c34b83aac2d3aebd19"}, - {"collider_SH", "03bd0022a55a2ead52fd65b317186743374ad320f3704d459f41797e264d1ec854"}, // 50 - {"dappvader_SH", "02bffea7911e09ad9a7df54af0c225516478d3ba138e65061aa8d4b9756bb4c8f4"}, - {"drkush_SH", "030b31cc9528566422e25f3e9b96541ab3626c0dea0e7aa3c0b0bd96039eae2f5a"}, - {"majora31_SH", "033bf21f039a1c832effad208d564e02e968f11e3a3aa41c42e3b748a232fb33f3"}, - {"mcrypt_SH", "025faab3cc2e83bf7dad6a9463cbff86c08800e937942126f258cf219bc2320043"}, - {"metaphilibert_SH", "0284af1a5ef01503e6316a2ca4abf8423a794e9fc17ac6846f042b6f4adedc3309"}, - {"mylo_SH", "03458dca36e800d5bc121d8c0d35f9fc6282880a79fee2d7e050f887b797bc7d6e"}, - {"nutellaLicka_SH", "03a495962a9e9eca06ee3b8ab4cd94e6ea0d87dd39d334ad85a524c4fece1a3db7"}, - {"pbca26_SH", "02c62877e96fc414f2444edf0601abff9d5d2f9078e49fa867ba5305f3c5b3beb0"}, - {"phit_SH", "02a9cef2141fb2af24349c1eea20f5fa8f5dba2835723778d19b23353ddcd877b1"}, - {"sheeba_SH", "03e6578015b7f0ab78a486070435031fff7bae11256ca6a9f3d358ab03029737cb"}, // 60 - {"strob_SH", "025ceac4256cef83ca4b110f837a71d70a5a977ecfdf807335e00bc78b560d451a"}, - {"strobnidan_SH", "02b967fde3686d45056343e488997d4c53f25cd7ad38548cd12b136010a09295ae"}, - {"dragonhound_DEV", "038e010c33c56b61389409eea5597fe17967398731e23185c84c472a16fc5d34ab"} - } -}; +extern const char *notaries_elected[NUM_KMD_SEASONS][NUM_KMD_NOTARIES][2]; extern char NOTARYADDRS[64][64]; extern char NOTARY_ADDRESSES[NUM_KMD_SEASONS][64][64]; From 5da51a35ff14e9593d28d19c81f61bbbd43fcd75 Mon Sep 17 00:00:00 2001 From: John Jones Date: Thu, 14 Oct 2021 10:59:40 -0500 Subject: [PATCH 29/47] adjust hardfork defines --- src/komodo_defs.h | 3 +++ src/komodo_hardfork.h | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/komodo_defs.h b/src/komodo_defs.h index 66ff4c5d4d1..2e0a8c7bfa9 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -19,6 +19,9 @@ #include "chain.h" #include "komodo_nk.h" +#define NUM_KMD_SEASONS 6 +#define NUM_KMD_NOTARIES 64 + #define KOMODO_EARLYTXID_HEIGHT 100 //#define ADAPTIVEPOW_CHANGETO_DEFAULTON 1572480000 #define ASSETCHAINS_MINHEIGHT 128 diff --git a/src/komodo_hardfork.h b/src/komodo_hardfork.h index 85cbcb1d156..47c3b992bef 100644 --- a/src/komodo_hardfork.h +++ b/src/komodo_hardfork.h @@ -1,9 +1,8 @@ #pragma once -#include +#include "komodo_defs.h" -#define NUM_KMD_SEASONS 6 -#define NUM_KMD_NOTARIES 64 +#include extern const uint32_t nStakedDecemberHardforkTimestamp; //December 2019 hardfork extern const int32_t nDecemberHardforkHeight; //December 2019 hardfork From 03229d5da9c1ed828937ced69f9690b6cceebb80 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 15 Oct 2021 09:16:55 -0500 Subject: [PATCH 30/47] Handle cryptoconditions changes --- src/Makefile.am | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 642d437b2e8..06fb2f6efd0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ DIST_SUBDIRS = secp256k1 univalue cryptoconditions - +SUBDIRS = cryptoconditions AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) AM_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) AM_CPPFLAGS = $(HARDENED_CPPFLAGS) @@ -78,15 +78,6 @@ libsnark-tests: $(wildcard snark/src/*) $(LIBUNIVALUE): $(wildcard univalue/lib/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " -$(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptoconditions/include/*) - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " - -#%.o: %.c -# $(CC) -c -o $@ $< - -#$(LIBCJSON): cJSON.o komodo_cJSON.o komodo_cutils.o -# $(AR) cr $(LIBCJSON) $^ - # libcjson build LIBCJSON=libcjson.a libcjson_a_SOURCES = cJSON.c \ From 10cbee93eaab887204ed5dfb6e6092c8009f8177 Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 22 Oct 2021 13:17:59 -0500 Subject: [PATCH 31/47] Rebuild libcc.so when dependencies change --- src/cc/Makefile_custom | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/cc/Makefile_custom b/src/cc/Makefile_custom index 79219ec96c1..364f9f4a121 100755 --- a/src/cc/Makefile_custom +++ b/src/cc/Makefile_custom @@ -10,9 +10,9 @@ RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program $(info $(OS)) OS := $(shell uname -s) $(info $(OS)) -TARGET = customcc.so -TARGET_DARWIN = customcc.dylib -TARGET_WIN = customcc.dll +TARGET = ../libcc.so +TARGET_DARWIN = ../libcc.dylib +TARGET_WIN = ../libcc.dll SOURCES = cclib.cpp #HEADERS = $(shell echo ../cryptoconditions/include/*.h) -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ @@ -22,16 +22,13 @@ $(TARGET): $(SOURCES) $(info Building cclib to src/) ifeq ($(OS),Darwin) $(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) -c $(SOURCES) - cp $(TARGET_DARWIN) ../libcc.dylib else ifeq ($(HOST),x86_64-w64-mingw32) $(info WINDOWS) $(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) -c $(SOURCES) - cp $(TARGET_WIN) ../libcc.dll #else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host else $(info LINUX) $(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) -c $(SOURCES) - cp $(TARGET) ../libcc.so endif clean: From 960fa3a2ecde4d132e852a32b1a4d8404098640f Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 5 Nov 2021 14:34:49 -0500 Subject: [PATCH 32/47] build cryptoconditions as static (incl Windows) --- depends/hosts/mingw32.mk | 11 +++++------ src/Makefile.am | 2 +- src/cryptoconditions/Makefile.am | 12 ++---------- zcutil/build-win-dtest.sh | 25 +++++++++++++------------ zcutil/build-win.sh | 22 +++++++++------------- 5 files changed, 30 insertions(+), 42 deletions(-) diff --git a/depends/hosts/mingw32.mk b/depends/hosts/mingw32.mk index b217bfdb547..2fe6ff51854 100644 --- a/depends/hosts/mingw32.mk +++ b/depends/hosts/mingw32.mk @@ -1,12 +1,11 @@ mingw32_CC=x86_64-w64-mingw32-gcc-posix mingw32_CXX=x86_64-w64-mingw32-g++-posix mingw32_CFLAGS=-pipe -std=c11 -mingw32_CXXFLAGS=$(mingw32_CFLAGS) -std=c++11 +mingw32_CXXFLAGS=-pipe -std=c++11 -mingw32_release_CFLAGS=-O1 -mingw32_release_CXXFLAGS=$(mingw32_release_CFLAGS) - -mingw32_debug_CFLAGS=-O1 -mingw32_debug_CXXFLAGS=$(mingw32_debug_CFLAGS) +mingw32_release_CFLAGS=-O3 +mingw32_release_CXXFLAGS=$(mingw32_CXXFLAGS) $(mingw32_release_CFLAGS) +mingw32_debug_CFLAGS=-g -O0 mingw32_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC +mingw32_debug_CXXFLAGS=$(mingw32_CXXFLAGS) $(mingw32_debug_CFLAGS) diff --git a/src/Makefile.am b/src/Makefile.am index 06fb2f6efd0..7f2ff22119e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -DIST_SUBDIRS = secp256k1 univalue cryptoconditions +DIST_SUBDIRS = secp256k1 univalue SUBDIRS = cryptoconditions AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(SAN_LDFLAGS) $(HARDENED_LDFLAGS) AM_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) diff --git a/src/cryptoconditions/Makefile.am b/src/cryptoconditions/Makefile.am index f347a1a2933..eab77eeff0f 100644 --- a/src/cryptoconditions/Makefile.am +++ b/src/cryptoconditions/Makefile.am @@ -1,24 +1,15 @@ -lib_LTLIBRARIES=libcryptoconditions.la -noinst_LTLIBRARIES=$(CRYPTOCONDITIONS_CORE) +noinst_LIBRARIES=libcryptoconditions_core.a SUBDIRS = src/include/secp256k1 include_HEADERS = include/cryptoconditions.h # Have a separate build target for cryptoconditions that does not contain secp256k1 -libcryptoconditions_la_SOURCES = include/cryptoconditions.h -libcryptoconditions_la_LIBADD = $(CRYPTOCONDITIONS_CORE) $(LIBSECP256K1) - -AM_CFLAGS = -I$(top_srcdir)/src/asn -I$(top_srcdir)/include -I$(top_srcdir)/src/include \ - -Wall -Wno-pointer-sign -Wno-discarded-qualifiers - LIBSECP256K1=src/include/secp256k1/libsecp256k1.la $(LIBSECP256K1): $(wildcard src/secp256k1/*) $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) -march:x86-64 -g -CRYPTOCONDITIONS_CORE=libcryptoconditions_core.a - libcryptoconditions_core_a_SOURCES = \ src/cryptoconditions.c \ src/utils.c \ @@ -74,6 +65,7 @@ libcryptoconditions_core_a_SOURCES = \ src/asn/per_decoder.c \ src/asn/per_encoder.c \ src/asn/per_opentype.c +libcryptoconditions_core_a_CPPFLAGS=-I. -I./src/include -I./src/asn test: bash -c '[ -d .env ] || virtualenv .env -p python3' diff --git a/zcutil/build-win-dtest.sh b/zcutil/build-win-dtest.sh index 00a64de5bf7..94bed448bde 100755 --- a/zcutil/build-win-dtest.sh +++ b/zcutil/build-win-dtest.sh @@ -2,23 +2,24 @@ export HOST=x86_64-w64-mingw32 CXX=x86_64-w64-mingw32-g++-posix CC=x86_64-w64-mingw32-gcc-posix -PREFIX="$(pwd)/depends/$HOST" set -eu -o pipefail - set -x -cd "$(dirname "$(readlink -f "$0")")/.." -cd depends/ && make HOST=$HOST V=1 NO_QT=1 -cd ../ -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD +UTIL_DIR="$(dirname "$(readlink -f "$0")")" +BASE_DIR="$(dirname "$(readlink -f "$UTIL_DIR")")" +PREFIX="$BASE_DIR/depends/$HOST" + +cd $BASE_DIR/depends +make HOST=$HOST NO_QT=1 "$@" +cd $BASE_DIR ./autogen.sh CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" CPPFLAGS=-DTESTMODE ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure -cd src/ -CC="${CC} -g " CXX="${CXX} -g " make V=1 komodod.exe komodo-cli.exe komodo-tx.exe + +cd $BASE_DIR/src/cryptoconditions +CC="${CC} -g " CXX="${CXX} -g " make V=1 +cd $BASE_DIR + +CC="${CC} -g " CXX="${CXX} -g " make V=1 src/komodod.exe src/komodo-cli.exe src/komodo-tx.exe diff --git a/zcutil/build-win.sh b/zcutil/build-win.sh index e8c0465d98b..ffd01134074 100755 --- a/zcutil/build-win.sh +++ b/zcutil/build-win.sh @@ -2,23 +2,19 @@ export HOST=x86_64-w64-mingw32 CXX=x86_64-w64-mingw32-g++-posix CC=x86_64-w64-mingw32-gcc-posix -PREFIX="$(pwd)/depends/$HOST" set -eu -o pipefail -set -x -cd "$(dirname "$(readlink -f "$0")")/.." +UTIL_DIR="$(dirname "$(readlink -f "$0")")" +BASE_DIR="$(dirname "$(readlink -f "$UTIL_DIR")")" +PREFIX="$BASE_DIR/depends/$HOST" -cd depends/ && make HOST=$HOST V=1 NO_QT=1 -cd ../ -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD +cd $BASE_DIR/depends +make HOST=$HOST NO_QT=1 "$@" +cd $BASE_DIR ./autogen.sh -CONFIG_SITE=$PWD/depends/x86_64-w64-mingw32/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix="${PREFIX}" --host=x86_64-w64-mingw32 --enable-static --disable-shared +CONFIG_SITE=$BASE_DIR/depends/$HOST/share/config.site CXXFLAGS="-DPTW32_STATIC_LIB -DCURL_STATICLIB -DCURVE_ALT_BN128 -fopenmp -pthread" ./configure --prefix=$PREFIX --host=$HOST --enable-static --disable-shared sed -i 's/-lboost_system-mt /-lboost_system-mt-s /' configure -cd src/ -CC="${CC} -g " CXX="${CXX} -g " make V=1 komodod.exe komodo-cli.exe komodo-tx.exe + +make "$@" From 4373f34dabc3404a787fc60039d1b7ac5372e95b Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 14 Jan 2022 10:18:46 -0500 Subject: [PATCH 33/47] addrman no lock in ctor --- src/addrman.h | 48 +++++++++++++++++++++++---------------- zcutil/build-mac-dtest.sh | 2 +- zcutil/build-mac.sh | 2 +- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/addrman.h b/src/addrman.h index 28e07a82b13..93c3692a5da 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -258,6 +258,33 @@ friend class CAddrManTest; //! Wraps GetRandInt to allow tests to override RandomInt and make it deterministic. virtual int RandomInt(int nMax); + /*** + * @brief Clears the internal collections and fills them again + * @note the mutex should be held before this method is called + * @note the constructor calls this directly with no lock + */ + void Clear_() + { + std::vector().swap(vRandom); + nKey = GetRandHash(); + for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) { + for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) { + vvNew[bucket][entry] = -1; + } + } + for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; bucket++) { + for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) { + vvTried[bucket][entry] = -1; + } + } + + nIdCount = 0; + nTried = 0; + nNew = 0; + mapInfo.clear(); + mapAddr.clear(); + } + #ifdef DEBUG_ADDRMAN //! Perform consistency check. Returns an error code or zero. int Check_(); @@ -502,29 +529,12 @@ friend class CAddrManTest; void Clear() { LOCK(cs); - std::vector().swap(vRandom); - nKey = GetRandHash(); - for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) { - for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) { - vvNew[bucket][entry] = -1; - } - } - for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; bucket++) { - for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) { - vvTried[bucket][entry] = -1; - } - } - - nIdCount = 0; - nTried = 0; - nNew = 0; - mapInfo.clear(); - mapAddr.clear(); + Clear_(); } CAddrMan() { - Clear(); + Clear_(); } ~CAddrMan() diff --git a/zcutil/build-mac-dtest.sh b/zcutil/build-mac-dtest.sh index 8104c720009..031e2761094 100755 --- a/zcutil/build-mac-dtest.sh +++ b/zcutil/build-mac-dtest.sh @@ -52,7 +52,7 @@ cd $WD ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64 -DTESTMODE" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ +CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ ./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" make "$@" V=1 NO_GTEST=1 STATIC=1 diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index aa030b8a019..03ad6915407 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -45,7 +45,7 @@ make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 ./autogen.sh CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ -CXXFLAGS='-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup' \ +CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ ./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" make "$@" V=1 NO_GTEST=1 STATIC=1 From cb8c132365f53e20db15b4b7aa263e364c0e109d Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 14 Jan 2022 11:45:45 -0500 Subject: [PATCH 34/47] enable-debug script param --- depends/hosts/darwin.mk | 4 ++-- depends/hosts/linux.mk | 2 +- depends/hosts/mingw32.mk | 2 +- zcutil/build-mac-dtest.sh | 33 +++++++++++++++++++-------------- zcutil/build-mac.sh | 24 ++++++++++++++++++------ zcutil/build.sh | 28 ++++++++++++++++++++-------- 6 files changed, 61 insertions(+), 32 deletions(-) diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index 7be744aebc0..9af5b86e5dd 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -8,10 +8,10 @@ darwin_CXX=g++-8 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysro darwin_CFLAGS=-pipe darwin_CXXFLAGS=$(darwin_CFLAGS) -darwin_release_CFLAGS=-O1 +darwin_release_CFLAGS=-g -O3 darwin_release_CXXFLAGS=$(darwin_release_CFLAGS) -darwin_debug_CFLAGS=-O1 +darwin_debug_CFLAGS=-g -O0 darwin_debug_CXXFLAGS=$(darwin_debug_CFLAGS) darwin_native_toolchain=native_cctools diff --git a/depends/hosts/linux.mk b/depends/hosts/linux.mk index 08a30684d13..c378257596d 100644 --- a/depends/hosts/linux.mk +++ b/depends/hosts/linux.mk @@ -1,7 +1,7 @@ linux_CFLAGS=-pipe linux_CXXFLAGS=$(linux_CFLAGS) -linux_release_CFLAGS=-O3 +linux_release_CFLAGS=-g -O3 linux_release_CXXFLAGS=$(linux_release_CFLAGS) linux_debug_CFLAGS=-g -O0 diff --git a/depends/hosts/mingw32.mk b/depends/hosts/mingw32.mk index 2fe6ff51854..f64f52c1d4a 100644 --- a/depends/hosts/mingw32.mk +++ b/depends/hosts/mingw32.mk @@ -3,7 +3,7 @@ mingw32_CXX=x86_64-w64-mingw32-g++-posix mingw32_CFLAGS=-pipe -std=c11 mingw32_CXXFLAGS=-pipe -std=c++11 -mingw32_release_CFLAGS=-O3 +mingw32_release_CFLAGS=-g -O3 mingw32_release_CXXFLAGS=$(mingw32_CXXFLAGS) $(mingw32_release_CFLAGS) mingw32_debug_CFLAGS=-g -O0 diff --git a/zcutil/build-mac-dtest.sh b/zcutil/build-mac-dtest.sh index 031e2761094..06171305bdd 100755 --- a/zcutil/build-mac-dtest.sh +++ b/zcutil/build-mac-dtest.sh @@ -18,11 +18,13 @@ Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov ] [ MAKEARGS... ] - Build Zcash and most of its transitive dependencies from - source. MAKEARGS are applied to both dependencies and Zcash itself. If - --enable-lcov is passed, Zcash is configured to add coverage +$0 [ --enable-lcov ] [ --enable-debug ] [ MAKEARGS... ] + Build Komodo and most of its transitive dependencies from + source. MAKEARGS are applied to both dependencies and Komodo itself. + If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. + If --enable-debug is passed, Komodo is built with debugging information. It + must be passed after the previous arguments, if present. EOF exit 0 fi @@ -37,22 +39,25 @@ then shift fi +# If --enable-debug is the next argument, enable debugging +DEBUGGING_ARG='' +if [ "x${1:-}" = 'x--enable-debug' ] +then + DEBUG=1 + export DEBUG + DEBUGGING_ARG='--enable-debug' + shift +fi + TRIPLET=`./depends/config.guess` PREFIX="$(pwd)/depends/$TRIPLET" make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 -#BUILD CCLIB - -WD=$PWD -cd src/cc -echo $PWD -./makecustom -cd $WD - ./autogen.sh + CPPFLAGS="-I$PREFIX/include -arch x86_64 -DTESTMODE" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ -./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" +./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$DEBUGGING_ARG" -make "$@" V=1 NO_GTEST=1 STATIC=1 +make "$@" NO_GTEST=1 STATIC=1 diff --git a/zcutil/build-mac.sh b/zcutil/build-mac.sh index 03ad6915407..77a5e764ecf 100755 --- a/zcutil/build-mac.sh +++ b/zcutil/build-mac.sh @@ -18,11 +18,13 @@ Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov ] [ MAKEARGS... ] - Build Zcash and most of its transitive dependencies from - source. MAKEARGS are applied to both dependencies and Zcash itself. If - --enable-lcov is passed, Zcash is configured to add coverage +$0 [ --enable-lcov ] [ --enable-debug ] [ MAKEARGS... ] + Build Komodo and most of its transitive dependencies from + source. MAKEARGS are applied to both dependencies and Komodo itself. + If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. + If --enable-debug is passed, Komodo is built with debugging information. It + must be passed after the previous arguments, if present. EOF exit 0 fi @@ -37,6 +39,16 @@ then shift fi +# If --enable-debug is the next argument, enable debugging +DEBUGGING_ARG='' +if [ "x${1:-}" = 'x--enable-debug' ] +then + DEBUG=1 + export DEBUG + DEBUGGING_ARG='--enable-debug' + shift +fi + TRIPLET=`./depends/config.guess` PREFIX="$(pwd)/depends/$TRIPLET" @@ -46,6 +58,6 @@ make "$@" -C ./depends/ V=1 NO_QT=1 NO_PROTON=1 CPPFLAGS="-I$PREFIX/include -arch x86_64" LDFLAGS="-L$PREFIX/lib -arch x86_64 -Wl,-no_pie" \ CXXFLAGS="-arch x86_64 -I/usr/local/Cellar/gcc\@8/8.3.0/include/c++/8.3.0/ -I$PREFIX/include -fwrapv -fno-strict-aliasing -Wno-builtin-declaration-mismatch -Werror -Wno-error=attributes -g -Wl,-undefined -Wl,dynamic_lookup" \ -./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" +./configure --prefix="${PREFIX}" --with-gui=no "$HARDENING_ARG" "$LCOV_ARG" "$DEBUGGING_ARG" -make "$@" V=1 NO_GTEST=1 STATIC=1 +make "$@" NO_GTEST=1 STATIC=1 diff --git a/zcutil/build.sh b/zcutil/build.sh index a017d07b50b..55f6b952ac1 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -44,17 +44,19 @@ then Usage: $0 --help Show this help message and exit. -$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [ MAKEARGS... ] - Build Zcash and most of its transitive dependencies from - source. MAKEARGS are applied to both dependencies and Zcash itself. - If --enable-lcov is passed, Zcash is configured to add coverage +$0 [ --enable-lcov || --disable-tests ] [ --disable-mining ] [ --enable-proton ] [ --disable-libs ] [ --enable-debug ] [ MAKEARGS... ] + Build Komodo and most of its transitive dependencies from + source. MAKEARGS are applied to both dependencies and Komodo itself. + If --enable-lcov is passed, Komodo is configured to add coverage instrumentation, thus enabling "make cov" to work. - If --disable-tests is passed instead, the Zcash tests are not built. - If --disable-mining is passed, Zcash is configured to not build any mining + If --disable-tests is passed instead, the Komodo tests are not built. + If --disable-mining is passed, Komodo is configured to not build any mining code. It must be passed after the test arguments, if present. - If --enable-proton is passed, Zcash is configured to build the Apache Qpid Proton + If --enable-proton is passed, Komodo is configured to build the Apache Qpid Proton library required for AMQP support. This library is not built by default. It must be passed after the test/mining arguments, if present. + If --enable-debug is passed, Komodo is built with debugging information. It + must be passed after the previous arguments, if present. EOF exit 0 fi @@ -90,6 +92,16 @@ then shift fi +# If --enable-debug is the next argument, enable debugging +DEBUGGING_ARG='' +if [ "x${1:-}" = 'x--enable-debug' ] +then + DEBUG=1 + export DEBUG + DEBUGGING_ARG='--enable-debug' + shift +fi + if [[ -z "${VERBOSE-}" ]]; then VERBOSITY="--enable-silent-rules" else @@ -100,6 +112,6 @@ HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V ./autogen.sh -CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' +CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$DEBUGGING_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' "$MAKE" "$@" From 7ecad6a4aaf7858026e03b7af46ce16623188a57 Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 22 Feb 2022 14:44:50 -0500 Subject: [PATCH 35/47] switch from -O3 to -O2 --- depends/hosts/darwin.mk | 2 +- depends/hosts/linux.mk | 2 +- depends/hosts/mingw32.mk | 2 +- src/Makefile.am | 10 +++++----- zcutil/build.sh | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/depends/hosts/darwin.mk b/depends/hosts/darwin.mk index 9af5b86e5dd..43a4c88f2ab 100644 --- a/depends/hosts/darwin.mk +++ b/depends/hosts/darwin.mk @@ -8,7 +8,7 @@ darwin_CXX=g++-8 -target $(host) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysro darwin_CFLAGS=-pipe darwin_CXXFLAGS=$(darwin_CFLAGS) -darwin_release_CFLAGS=-g -O3 +darwin_release_CFLAGS=-g -O2 darwin_release_CXXFLAGS=$(darwin_release_CFLAGS) darwin_debug_CFLAGS=-g -O0 diff --git a/depends/hosts/linux.mk b/depends/hosts/linux.mk index c378257596d..857fe783079 100644 --- a/depends/hosts/linux.mk +++ b/depends/hosts/linux.mk @@ -1,7 +1,7 @@ linux_CFLAGS=-pipe linux_CXXFLAGS=$(linux_CFLAGS) -linux_release_CFLAGS=-g -O3 +linux_release_CFLAGS=-g -O2 linux_release_CXXFLAGS=$(linux_release_CFLAGS) linux_debug_CFLAGS=-g -O0 diff --git a/depends/hosts/mingw32.mk b/depends/hosts/mingw32.mk index f64f52c1d4a..857850b05b1 100644 --- a/depends/hosts/mingw32.mk +++ b/depends/hosts/mingw32.mk @@ -3,7 +3,7 @@ mingw32_CXX=x86_64-w64-mingw32-g++-posix mingw32_CFLAGS=-pipe -std=c11 mingw32_CXXFLAGS=-pipe -std=c++11 -mingw32_release_CFLAGS=-g -O3 +mingw32_release_CFLAGS=-g -O2 mingw32_release_CXXFLAGS=$(mingw32_CXXFLAGS) $(mingw32_release_CFLAGS) mingw32_debug_CFLAGS=-g -O0 diff --git a/src/Makefile.am b/src/Makefile.am index 7f2ff22119e..b833dbdbabd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,9 +56,6 @@ if BUILD_BITCOIN_LIBS LIBZCASH_CONSENSUS=libzcashconsensus.la endif -$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " - LIBSNARK_CXXFLAGS = $(AM_CXXFLAGS) $(PIC_FLAGS) -DBINARY_OUTPUT -DNO_PT_COMPRESSION=1 -fstack-protector-all LIBSNARK_CONFIG_FLAGS = CURVE=ALT_BN128 NO_PROCPS=1 NO_DOCS=1 STATIC=1 NO_SUPERCOP=1 FEATUREFLAGS=-DMONTGOMERY_OUTPUT NO_COPY_DEPINST=1 NO_COMPILE_LIBGTEST=1 LIBSNARK_OPTFLAGS = $(CPPFLAGS) -march=x86-64 @@ -69,14 +66,17 @@ if TARGET_DARWIN LIBSNARK_CONFIG_FLAGS += PLATFORM=darwin endif +$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*) + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="$(LIBSNARK_OPTFLAGS) " + $(LIBSNARK): $(wildcard snark/src/*) $(AM_V_at)CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" libsnark-tests: $(wildcard snark/src/*) - $(AM_V_at)CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="-O2 -march=x86-64" + $(AM_V_at)CC="$(CC)" CXX="$(CXX)" AR="$(AR)" CXXFLAGS="$(LIBSNARK_CXXFLAGS)" $(MAKE) $(AM_MAKEFLAGS) -C snark/ check DEPINST="$(LIBSNARK_DEPINST)" $(LIBSNARK_CONFIG_FLAGS) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" $(LIBUNIVALUE): $(wildcard univalue/lib/*) - $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=x86-64 -g " + $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="$(LIBSNARK_OPTFLAGS)" # libcjson build LIBCJSON=libcjson.a diff --git a/zcutil/build.sh b/zcutil/build.sh index 55f6b952ac1..7b6da0d701f 100755 --- a/zcutil/build.sh +++ b/zcutil/build.sh @@ -108,10 +108,10 @@ else VERBOSITY="--disable-silent-rules" fi -HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ V=1 +HOST="$HOST" BUILD="$BUILD" NO_PROTON="$PROTON_ARG" "$MAKE" "$@" -C ./depends/ ./autogen.sh -CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$DEBUGGING_ARG" "$CONFIGURE_FLAGS" CXXFLAGS='-g' +CONFIG_SITE="$PWD/depends/$HOST/share/config.site" ./configure "$HARDENING_ARG" "$LCOV_ARG" "$TEST_ARG" "$MINING_ARG" "$PROTON_ARG" "$DEBUGGING_ARG" "$CONFIGURE_FLAGS" "$MAKE" "$@" From 634c1b2552a28a4d0a488dda4cad821a08dcabbc Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 23 Feb 2022 09:53:15 -0500 Subject: [PATCH 36/47] clean komodo_state --- src/test-komodo/testutils.cpp | 16 +++++++++++++++- src/test-komodo/testutils.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index 9baff2339d3..35f50fc2cef 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -18,6 +18,7 @@ #include "primitives/transaction.h" #include "script/cc.h" #include "script/interpreter.h" +#include "komodo_extern_globals.h" #include "testutils.h" @@ -164,6 +165,7 @@ CTransaction getInputTx(CScript scriptPubKey) TestChain::TestChain() { + CleanGlobals(); previousNetwork = Params().NetworkIDString(); dataDir = GetTempPath() / strprintf("test_komodo_%li_%i", GetTime(), GetRand(100000)); if (ASSETCHAINS_SYMBOL[0]) @@ -179,7 +181,7 @@ TestChain::TestChain() TestChain::~TestChain() { - adjust_hwmheight(0); // hwmheight can get skewed if komodo_connectblock not called (which some tests do) + CleanGlobals(); boost::filesystem::remove_all(dataDir); if (previousNetwork == "main") SelectParams(CBaseChainParams::MAIN); @@ -190,6 +192,18 @@ TestChain::~TestChain() } +void TestChain::CleanGlobals() +{ + // hwmheight can get skewed if komodo_connectblock not called (which some tests do) + adjust_hwmheight(0); + for(int i = 0; i < 33; ++i) + { + komodo_state s = KOMODO_STATES[i]; + s.events.clear(); + // TODO: clean notarization points + } +} + /*** * Get the block index at the specified height * @param height the height (0 indicates current height) diff --git a/src/test-komodo/testutils.h b/src/test-komodo/testutils.h index c1a02a38053..811c5d0eebd 100644 --- a/src/test-komodo/testutils.h +++ b/src/test-komodo/testutils.h @@ -94,6 +94,7 @@ class TestChain std::vector> toBeNotified; boost::filesystem::path dataDir; std::string previousNetwork; + void CleanGlobals(); }; /*** From 7e09f1dd4447919ee388f0c731564d344766776a Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 10 May 2022 13:13:31 -0500 Subject: [PATCH 37/47] avoid comparing ptr to int --- src/komodo_bitcoind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/komodo_bitcoind.cpp b/src/komodo_bitcoind.cpp index 43f06c2200d..378cfa3f746 100644 --- a/src/komodo_bitcoind.cpp +++ b/src/komodo_bitcoind.cpp @@ -500,7 +500,7 @@ int32_t komodo_verifynotarization(char *symbol,char *dest,int32_t height,int32_t { if ( (json= cJSON_Parse(jsonstr)) != 0 ) { - if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) != 0 ) + if ( (txjson= jobj(json,(char *)"result")) != 0 && (vouts= jarray(&n,txjson,(char *)"vout")) != nullptr ) { vout = jitem(vouts,n-1); if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 ) From cf6af36eac41844fe33b26a4ca85048d2a94676a Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 16 May 2022 11:42:25 -0500 Subject: [PATCH 38/47] Fix locking cs_main in tests --- src/main.cpp | 9 +++++++++ src/test-komodo/test_block.cpp | 9 ++++----- src/test-komodo/test_mempool.cpp | 8 ++++++++ src/test-komodo/test_parse_notarisation.cpp | 7 ++++++- src/test-komodo/testutils.cpp | 8 ++++++++ src/test-komodo/testutils.h | 11 +++++++++++ 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5284bc3160d..81bbfe3bb42 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3397,6 +3397,15 @@ static int64_t nTimeTotal = 0; bool FindBlockPos(int32_t tmpflag,CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false); bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos); +/***** + * Only for testing, DO NOT USE + * @returns the cs_main mutex + */ +CCriticalSection& get_cs_main() +{ + return cs_main; +} + /***** * @brief Apply the effects of this block (with given index) on the UTXO set represented by coins * @param block the block to add diff --git a/src/test-komodo/test_block.cpp b/src/test-komodo/test_block.cpp index 8b342183f0c..f006d1e929a 100644 --- a/src/test-komodo/test_block.cpp +++ b/src/test-komodo/test_block.cpp @@ -29,7 +29,7 @@ TEST(block_tests, TestStopAt) CBlock block; CValidationState state; KOMODO_STOPAT = 1; - EXPECT_FALSE( ConnectBlock(block, state, chain.GetIndex(), *chain.GetCoinsViewCache(), false, true) ); + EXPECT_FALSE( chain.ConnectBlock(block, state, chain.GetIndex(), false, true) ); KOMODO_STOPAT = 0; // to not stop other tests } @@ -59,11 +59,10 @@ TEST(block_tests, TestConnectWithoutChecks) block.vtx.push_back(fundAlice); CValidationState state; // create a new CBlockIndex to forward to ConnectBlock - auto view = chain.GetCoinsViewCache(); auto index = chain.GetIndex(); CBlockIndex newIndex; newIndex.pprev = index; - EXPECT_TRUE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); + EXPECT_TRUE( chain.ConnectBlock(block, state, &newIndex, true, false) ); if (!state.IsValid() ) FAIL() << state.GetRejectReason(); } @@ -116,7 +115,7 @@ TEST(block_tests, TestSpendInSameBlock) auto index = chain.GetIndex(); CBlockIndex newIndex; newIndex.pprev = index; - EXPECT_TRUE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); + EXPECT_TRUE( chain.ConnectBlock(block, state, &newIndex, true, false) ); if (!state.IsValid() ) FAIL() << state.GetRejectReason(); } @@ -188,7 +187,7 @@ TEST(block_tests, TestDoubleSpendInSameBlock) auto index = chain.GetIndex(); CBlockIndex newIndex; newIndex.pprev = index; - EXPECT_FALSE( ConnectBlock(block, state, &newIndex, *chain.GetCoinsViewCache(), true, false) ); + EXPECT_FALSE( chain.ConnectBlock(block, state, &newIndex, true, false) ); EXPECT_EQ(state.GetRejectReason(), "bad-txns-inputs-missingorspent"); } diff --git a/src/test-komodo/test_mempool.cpp b/src/test-komodo/test_mempool.cpp index 02be26fd878..e92fc092170 100644 --- a/src/test-komodo/test_mempool.cpp +++ b/src/test-komodo/test_mempool.cpp @@ -147,6 +147,8 @@ TEST(Mempool, PriorityStatsDoNotCrash) { EXPECT_EQ(dPriority, MAX_PRIORITY); } +CCriticalSection& get_cs_main(); // in main.cpp + TEST(Mempool, TxInputLimit) { SelectParams(CBaseChainParams::REGTEST); @@ -164,6 +166,7 @@ TEST(Mempool, TxInputLimit) { // Check it fails as expected CValidationState state1; CTransaction tx1(mtx); + LOCK( get_cs_main() ); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "bad-txns-version-too-low"); @@ -227,6 +230,7 @@ TEST(Mempool, OverwinterNotActiveYet) { CValidationState state1; CTransaction tx1(mtx); + LOCK( get_cs_main() ); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "tx-overwinter-not-active"); @@ -251,6 +255,7 @@ TEST(Mempool, SproutV3TxFailsAsExpected) { CValidationState state1; CTransaction tx1(mtx); + LOCK( get_cs_main() ); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "version"); } @@ -272,6 +277,7 @@ TEST(Mempool, SproutV3TxWhenOverwinterActive) { CValidationState state1; CTransaction tx1(mtx); + LOCK( get_cs_main() ); EXPECT_FALSE(AcceptToMemoryPool(pool, state1, tx1, false, &missingInputs)); EXPECT_EQ(state1.GetRejectReason(), "tx-overwinter-flag-not-set"); @@ -293,6 +299,8 @@ TEST(Mempool, SproutNegativeVersionTxWhenOverwinterActive) { mtx.vjoinsplit.resize(0); // no joinsplits mtx.fOverwintered = false; + LOCK( get_cs_main() ); + // A Sprout transaction with version -3 is created using Sprout code (as found in zcashd <= 1.0.14). // First four bytes of transaction, parsed as an uint32_t, has the value: 0xfffffffd // This test simulates an Overwinter node receiving this transaction, but incorrectly deserializing the diff --git a/src/test-komodo/test_parse_notarisation.cpp b/src/test-komodo/test_parse_notarisation.cpp index 9eab052d2f0..5efcb4a8bd4 100644 --- a/src/test-komodo/test_parse_notarisation.cpp +++ b/src/test-komodo/test_parse_notarisation.cpp @@ -406,8 +406,13 @@ TEST(TestParseNotarisation, test_notarizeddata) EXPECT_EQ(txid, expected_txid); } -TEST(TestParseNotarisation, OldVsNew) +TEST(TestParseNotarisation, DISABLED_OldVsNew) { + /*** + * This test requires a binary file of notarization data + * as well as a long time to run. Re-enable this test to check + * the notarization checkpoints. + */ ASSETCHAINS_SYMBOL[0] = 0; char symbol[4] = { 0 }; char dest[4] = { 0 }; diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index eba55233d59..1b552d0b95a 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -38,6 +38,7 @@ extern int32_t USE_EXTERNAL_PUBKEY; extern std::string NOTARY_PUBKEY; void adjust_hwmheight(int32_t in); // in komodo.cpp +CCriticalSection& get_cs_main(); // in main.cpp void setupChain() { @@ -238,6 +239,13 @@ CBlock TestChain::generateBlock() return block; } +bool TestChain::ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + bool fJustCheck, bool fCheckPOW) +{ + LOCK( get_cs_main() ); + return ::ConnectBlock(block, state, pindex, *(this->GetCoinsViewCache()), fJustCheck, fCheckPOW); +} + CKey TestChain::getNotaryKey() { return notaryKey; } CValidationState TestChain::acceptTx(const CTransaction& tx) diff --git a/src/test-komodo/testutils.h b/src/test-komodo/testutils.h index 811c5d0eebd..65e42a112b2 100644 --- a/src/test-komodo/testutils.h +++ b/src/test-komodo/testutils.h @@ -90,6 +90,17 @@ class TestChain * @returns the wallet */ std::shared_ptr AddWallet(); + /**** + * @brief attempt to connect a block to the chain + * @param block the block to connect + * @param state where to hold the results + * @param pindex the new chain index + * @param justCheck whether or not to do all checks + * @param checkPOW true to check PoW + * @returns true on success + */ + bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, + bool fJustCheck = false,bool fCheckPOW = false); private: std::vector> toBeNotified; boost::filesystem::path dataDir; From 76bad69d570bc2cfd62969ced5e92c270f4f5eed Mon Sep 17 00:00:00 2001 From: John Jones Date: Fri, 20 May 2022 16:39:49 -0500 Subject: [PATCH 39/47] Make TestWallet derive from CWallet --- src/chainparams.cpp | 2 + src/chainparams.h | 5 + src/consensus/consensus.h | 2 - src/komodo_defs.h | 1 - src/komodo_globals.h | 4 +- src/komodo_utils.cpp | 7 +- src/main.cpp | 6 +- src/main.h | 3 +- src/metrics.cpp | 2 +- src/qt/transactiondesc.cpp | 6 +- src/rpc/mining.cpp | 37 ++ src/script/interpreter.cpp | 11 + src/test-komodo/test_block.cpp | 224 +++++------ src/test-komodo/test_coins.cpp | 4 +- src/test-komodo/testutils.cpp | 684 ++++++++++++++++++++++++++++----- src/test-komodo/testutils.h | 98 +++-- src/test/test_bitcoin.cpp | 6 +- src/txmempool.cpp | 5 +- src/wallet/db.cpp | 45 ++- src/wallet/db.h | 6 +- src/wallet/wallet.cpp | 49 ++- src/wallet/wallet.h | 3 +- src/wallet/walletdb.cpp | 26 +- src/zcbenchmarks.cpp | 2 +- 24 files changed, 885 insertions(+), 353 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 36c5afc02ff..4e0653c51dc 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -381,6 +381,8 @@ class CRegTestParams : public CChainParams { consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170006; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + originalCoinbaseMaturity = 1; + coinbaseMaturity = 1; pchMessageStart[0] = 0xaa; pchMessageStart[1] = 0x8e; diff --git a/src/chainparams.h b/src/chainparams.h index daa16af8c40..db94db5a75b 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -122,6 +122,9 @@ class CChainParams void SetNValue(uint64_t n) { nEquihashN = n; } void SetKValue(uint64_t k) { nEquihashK = k; } void SetMiningRequiresPeers(bool flag) { fMiningRequiresPeers = flag; } + uint32_t CoinbaseMaturity() const { return coinbaseMaturity; } + void SetCoinbaseMaturity(uint32_t in) const { coinbaseMaturity = in; } + void ResetCoinbaseMaturity() const { coinbaseMaturity = originalCoinbaseMaturity; } //void setnonce(uint32_t nonce) { memcpy(&genesis.nNonce,&nonce,sizeof(nonce)); } //void settimestamp(uint32_t timestamp) { genesis.nTime = timestamp; } @@ -156,6 +159,8 @@ class CChainParams bool fTestnetToBeDeprecatedFieldRPC = false; CCheckpointData checkpointData; std::vector vFoundersRewardAddress; + mutable uint32_t coinbaseMaturity = 100; + uint32_t originalCoinbaseMaturity = 100; }; /** diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index eba39b64422..32b340325ae 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -40,8 +40,6 @@ extern unsigned int MAX_BLOCK_SIGOPS; /** The maximum size of a transaction (network rule) */ static const unsigned int MAX_TX_SIZE_BEFORE_SAPLING = 100000; static const unsigned int MAX_TX_SIZE_AFTER_SAPLING = (2 * MAX_TX_SIZE_BEFORE_SAPLING); //MAX_BLOCK_SIZE; -/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ -extern int COINBASE_MATURITY; /** The minimum value which is invalid for expiry height, used by CTransaction and CMutableTransaction */ static constexpr uint32_t TX_EXPIRY_HEIGHT_THRESHOLD = 500000000; diff --git a/src/komodo_defs.h b/src/komodo_defs.h index e63a369ca0a..d250bb4abff 100644 --- a/src/komodo_defs.h +++ b/src/komodo_defs.h @@ -39,7 +39,6 @@ #define ASSETCHAINS_STAKED_BLOCK_FUTURE_MAX 57 #define ASSETCHAINS_STAKED_BLOCK_FUTURE_HALF 27 #define ASSETCHAINS_STAKED_MIN_POW_DIFF 536900000 // 537000000 537300000 -#define _COINBASE_MATURITY 100 #define _ASSETCHAINS_TIMELOCKOFF 0xffffffffffffffff // KMD Notary Seasons diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 7dd1be1cc43..92f59672e63 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -43,9 +43,7 @@ struct knotaries_entry *Pubkeys; struct komodo_state KOMODO_STATES[34]; -#define _COINBASE_MATURITY 100 -int COINBASE_MATURITY = _COINBASE_MATURITY;//100; -unsigned int WITNESS_CACHE_SIZE = _COINBASE_MATURITY+10; +unsigned int WITNESS_CACHE_SIZE = 100+10; // coinbase maturity plus 10 uint256 KOMODO_EARLYTXID; bool IS_KOMODO_NOTARY; diff --git a/src/komodo_utils.cpp b/src/komodo_utils.cpp index 8c70a7f7bf9..89bc93a34f8 100644 --- a/src/komodo_utils.cpp +++ b/src/komodo_utils.cpp @@ -1796,7 +1796,6 @@ void komodo_args(char *argv0) if ( ASSETCHAINS_SYMBOL[0] != 0 ) { int32_t komodo_baseid(char *origbase); - extern int COINBASE_MATURITY; if ( strcmp(ASSETCHAINS_SYMBOL,"KMD") == 0 ) { fprintf(stderr,"cant have assetchain named KMD\n"); @@ -1807,10 +1806,10 @@ void komodo_args(char *argv0) else komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT + 1); if (ASSETCHAINS_CBMATURITY != 0) - COINBASE_MATURITY = ASSETCHAINS_CBMATURITY; + Params().SetCoinbaseMaturity(ASSETCHAINS_CBMATURITY); else if (ASSETCHAINS_LASTERA == 0 || is_STAKED(ASSETCHAINS_SYMBOL) != 0) - COINBASE_MATURITY = 1; - if (COINBASE_MATURITY < 1) + Params().SetCoinbaseMaturity(1); + if (Params().CoinbaseMaturity() < 1) { fprintf(stderr,"ac_cbmaturity must be >0, shutting down\n"); StartShutdown(); diff --git a/src/main.cpp b/src/main.cpp index 81bbfe3bb42..ab49416445d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1874,7 +1874,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa if (pool.mapNextTx.count(outpoint)) { // Disable replacement feature for now - return false; + return state.Invalid(false, REJECT_INVALID, "mempool conflict"); } } BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) { @@ -2797,9 +2797,9 @@ namespace Consensus { } // Ensure that coinbases are matured, no DoS as retry may work later - if (nSpendHeight - coins->nHeight < COINBASE_MATURITY) { + if (nSpendHeight - coins->nHeight < ::Params().CoinbaseMaturity()) { return state.Invalid( - error("CheckInputs(): tried to spend coinbase at depth %d/%d", nSpendHeight - coins->nHeight, (int32_t)COINBASE_MATURITY), + error("CheckInputs(): tried to spend coinbase at depth %d/%d", nSpendHeight - coins->nHeight, (int32_t)::Params().CoinbaseMaturity()), REJECT_INVALID, "bad-txns-premature-spend-of-coinbase"); } diff --git a/src/main.h b/src/main.h index de9130d3751..e2635ed86ef 100644 --- a/src/main.h +++ b/src/main.h @@ -66,7 +66,6 @@ class PrecomputedTransactionData; struct CNodeStateStats; #define DEFAULT_MEMPOOL_EXPIRY 1 -#define _COINBASE_MATURITY 100 /** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 2000000;//MAX_BLOCK_SIZE; @@ -78,7 +77,7 @@ static const bool DEFAULT_ALERTS = true; /** Minimum alert priority for enabling safe mode. */ static const int ALERT_PRIORITY_SAFE_MODE = 4000; /** Maximum reorg length we will accept before we shut down and alert the user. */ -static unsigned int MAX_REORG_LENGTH = _COINBASE_MATURITY - 1; +static unsigned int MAX_REORG_LENGTH = 100 - 1; // based on COINBASE_MATURITY /** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ diff --git a/src/metrics.cpp b/src/metrics.cpp index 7ec6298b03e..ff1924c91da 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -365,7 +365,7 @@ int printMetrics(size_t cols, bool mining) subsidy -= subsidy/5; } - if ((std::max(0, COINBASE_MATURITY - (tipHeight - height)) > 0) || + if ((std::max( 0U, Params().CoinbaseMaturity() - (tipHeight - height)) > 0) || (tipHeight < komodo_block_unlocktime(height) && subsidy >= ASSETCHAINS_TIMELOCKGTE)) { immature += subsidy; } else { diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 32d92bbbe4f..11609dc881b 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -267,9 +267,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (wtx.IsCoinBase()) { extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; - if ( ASSETCHAINS_SYMBOL[0] == 0 ) - COINBASE_MATURITY = _COINBASE_MATURITY; - quint32 numBlocksToMaturity = COINBASE_MATURITY + 1; + //if ( ASSETCHAINS_SYMBOL[0] == 0 ) + //COINBASE_MATURITY = _COINBASE_MATURITY; + quint32 numBlockToMaturity = 100 + 1; // COINBASE_MATURITY + 1 strHTML += "
" + tr("Generated coins must mature %1 blocks and have any applicable time locks open before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.").arg(QString::number(numBlocksToMaturity)) + "
"; // we need to display any possible CLTV lock time } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 98a9746cce8..4a267de8044 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -247,6 +247,43 @@ bool CalcPoW(CBlock *pblock) return false; } +/**** + * @brief Generate 1 block + * @param wallet the wallet that should be used + * @returns the block created or nullptr if there was a problem + */ +std::shared_ptr generateBlock(CWallet* wallet, CValidationState* validationState) +{ + CReserveKey reservekey(wallet); + int nHeight; + + { // Don't keep cs_main locked + LOCK(cs_main); + nHeight = chainActive.Height(); + } + + std::unique_ptr pblocktemplate(CreateNewBlockWithKey(reservekey,nHeight,KOMODO_MAXGPUCOUNT)); + if (pblocktemplate == nullptr) + return nullptr; + + CBlock *pblock = &pblocktemplate->block; + { + unsigned int nExtraNonce = 0; + LOCK(cs_main); + IncrementExtraNonce(pblock, chainActive.LastTip(), nExtraNonce); + } + + CalcPoW(pblock); // add PoW + CValidationState state; + if (!ProcessNewBlock(1,chainActive.LastTip()->nHeight+1,state, NULL, pblock, true, NULL)) + { + if (validationState != nullptr) + (*validationState) = state; + return nullptr; + } + return std::shared_ptr( new CBlock(*pblock) ); +} + //Value generate(const Array& params, bool fHelp) UniValue generate(const UniValue& params, bool fHelp, const CPubKey& mypk) { diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 64d98d78376..22a5f98d800 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1204,6 +1204,17 @@ SigVersion SignatureHashVersion(const CTransaction& txTo) } } +/***** + * Generate a signature hash + * @param scriptCode the scriptPubKey + * @param txTo the transaction we are trying to create + * @param nIn the index of the vIn that has the data to sign + * @param nHashType the hash type (i.e. SIGHASH_ALL) + * @param amount the amount (for hidden txs) + * @param consensusBranchId the branch id + * @param cache additional data + * @returns the signature + */ uint256 SignatureHash( const CScript& scriptCode, const CTransaction& txTo, diff --git a/src/test-komodo/test_block.cpp b/src/test-komodo/test_block.cpp index f006d1e929a..76dd5179c83 100644 --- a/src/test-komodo/test_block.cpp +++ b/src/test-komodo/test_block.cpp @@ -2,12 +2,14 @@ #include "testutils.h" #include "komodo_extern_globals.h" #include "consensus/validation.h" +#include "coincontrol.h" #include "miner.h" +#include #include -TEST(block_tests, header_size_is_expected) { +TEST(test_block, header_size_is_expected) { // Header with an empty Equihash solution. CBlockHeader header; CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -18,13 +20,13 @@ TEST(block_tests, header_size_is_expected) { EXPECT_EQ(ss.size(), stream_size); } -TEST(block_tests, TestStopAt) +TEST(test_block, TestStopAt) { TestChain chain; - auto notary = chain.AddWallet(chain.getNotaryKey()); - CBlock lastBlock = chain.generateBlock(); // genesis block + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block ASSERT_GT( chain.GetIndex()->nHeight, 0 ); - lastBlock = chain.generateBlock(); // now we should be above 1 + lastBlock = chain.generateBlock(notary); // now we should be above 1 ASSERT_GT( chain.GetIndex()->nHeight, 1); CBlock block; CValidationState state; @@ -33,16 +35,16 @@ TEST(block_tests, TestStopAt) KOMODO_STOPAT = 0; // to not stop other tests } -TEST(block_tests, TestConnectWithoutChecks) +TEST(test_block, TestConnectWithoutChecks) { TestChain chain; - auto notary = chain.AddWallet(chain.getNotaryKey()); - auto alice = chain.AddWallet(); - CBlock lastBlock = chain.generateBlock(); // genesis block + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + auto alice = std::make_shared("alice"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block ASSERT_GT( chain.GetIndex()->nHeight, 0 ); // Add some transaction to a block int32_t newHeight = chain.GetIndex()->nHeight + 1; - CTransaction fundAlice = notary->CreateSpendTransaction(alice, 100000); + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000); // construct the block CBlock block; // first a coinbase tx @@ -56,7 +58,7 @@ TEST(block_tests, TestConnectWithoutChecks) txNew.nExpiryHeight = 0; block.vtx.push_back(CTransaction(txNew)); // then the actual tx - block.vtx.push_back(fundAlice); + block.vtx.push_back(fundAlice.transaction); CValidationState state; // create a new CBlockIndex to forward to ConnectBlock auto index = chain.GetIndex(); @@ -67,147 +69,96 @@ TEST(block_tests, TestConnectWithoutChecks) FAIL() << state.GetRejectReason(); } -TEST(block_tests, TestSpendInSameBlock) +TEST(test_block, TestSpendInSameBlock) { + //setConsoleDebugging(true); TestChain chain; - auto notary = chain.AddWallet(chain.getNotaryKey()); - auto alice = chain.AddWallet(); - auto bob = chain.AddWallet(); - CBlock lastBlock = chain.generateBlock(); // genesis block + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + notary->SetBroadcastTransactions(true); + auto alice = std::make_shared("alice"); + alice->SetBroadcastTransactions(true); + auto bob = std::make_shared("bob"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block ASSERT_GT( chain.GetIndex()->nHeight, 0 ); + // delay just a second to help with locktime + std::this_thread::sleep_for(std::chrono::seconds(1)); // Start to build a block int32_t newHeight = chain.GetIndex()->nHeight + 1; - CTransaction fundAlice = notary->CreateSpendTransaction(alice, 100000); + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000, 0, true); // now have Alice move some funds to Bob in the same block - CMutableTransaction aliceToBobMutable; - CTxIn aliceIn; - aliceIn.prevout.hash = fundAlice.GetHash(); - aliceIn.prevout.n = 0; - aliceToBobMutable.vin.push_back(aliceIn); - CTxOut bobOut; - bobOut.scriptPubKey = GetScriptForDestination(bob->GetPubKey()); - bobOut.nValue = 10000; - aliceToBobMutable.vout.push_back(bobOut); - CTxOut aliceRemainder; - aliceRemainder.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceRemainder.nValue = fundAlice.vout[0].nValue - 10000; - aliceToBobMutable.vout.push_back(aliceRemainder); - uint256 hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); - aliceToBobMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); - CTransaction aliceToBobTx(aliceToBobMutable); - // construct the block - CBlock block; - // first a coinbase tx - auto consensusParams = Params().GetConsensus(); - CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); - txNew.vin.resize(1); - txNew.vin[0].prevout.SetNull(); - txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; - txNew.vout.resize(1); - txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); - txNew.nExpiryHeight = 0; - block.vtx.push_back(CTransaction(txNew)); - // then the actual txs - block.vtx.push_back(fundAlice); - block.vtx.push_back(aliceToBobTx); - CValidationState state; - // create a new CBlockIndex to forward to ConnectBlock - auto index = chain.GetIndex(); - CBlockIndex newIndex; - newIndex.pprev = index; - EXPECT_TRUE( chain.ConnectBlock(block, state, &newIndex, true, false) ); - if (!state.IsValid() ) - FAIL() << state.GetRejectReason(); + CCoinControl useThisTransaction; + COutPoint tx(fundAlice.transaction.GetHash(), 1); + useThisTransaction.Select(tx); + TransactionInProcess aliceToBob = alice->CreateSpendTransaction(bob, 50000, 5000, useThisTransaction); + EXPECT_TRUE( alice->CommitTransaction(aliceToBob.transaction, aliceToBob.reserveKey) ); + std::this_thread::sleep_for(std::chrono::seconds(1)); + // see if everything worked + lastBlock = chain.generateBlock(notary); + EXPECT_TRUE( lastBlock != nullptr); + // balances should be correct + EXPECT_EQ( bob->GetBalance() + bob->GetUnconfirmedBalance() + bob->GetImmatureBalance(), CAmount(50000)); + EXPECT_EQ( notary->GetBalance(), CAmount(10000000299905000)); + EXPECT_EQ( alice->GetBalance() + alice->GetUnconfirmedBalance() + alice->GetImmatureBalance(), CAmount(45000)); } -TEST(block_tests, TestDoubleSpendInSameBlock) +TEST(test_block, TestDoubleSpendInSameBlock) { TestChain chain; - auto notary = chain.AddWallet(chain.getNotaryKey()); - auto alice = chain.AddWallet(); - auto bob = chain.AddWallet(); - auto charlie = chain.AddWallet(); - CBlock lastBlock = chain.generateBlock(); // genesis block + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + notary->SetBroadcastTransactions(true); + auto alice = std::make_shared("alice"); + alice->SetBroadcastTransactions(true); + auto bob = std::make_shared("bob"); + auto charlie = std::make_shared("charlie"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block ASSERT_GT( chain.GetIndex()->nHeight, 0 ); // Start to build a block int32_t newHeight = chain.GetIndex()->nHeight + 1; - CTransaction fundAlice = notary->CreateSpendTransaction(alice, 100000); + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000, 0, true); + EXPECT_EQ(mempool.size(), 1); // now have Alice move some funds to Bob in the same block - CMutableTransaction aliceToBobMutable; - CTxIn aliceIn; - aliceIn.prevout.hash = fundAlice.GetHash(); - aliceIn.prevout.n = 0; - aliceToBobMutable.vin.push_back(aliceIn); - CTxOut bobOut; - bobOut.scriptPubKey = GetScriptForDestination(bob->GetPubKey()); - bobOut.nValue = 10000; - aliceToBobMutable.vout.push_back(bobOut); - CTxOut aliceRemainder; - aliceRemainder.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceRemainder.nValue = fundAlice.vout[0].nValue - 10000; - aliceToBobMutable.vout.push_back(aliceRemainder); - uint256 hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToBobMutable, 0, SIGHASH_ALL, 0, 0); - aliceToBobMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); - CTransaction aliceToBobTx(aliceToBobMutable); + { + CCoinControl useThisTransaction; + COutPoint tx(fundAlice.transaction.GetHash(), 1); + useThisTransaction.Select(tx); + TransactionInProcess aliceToBob = alice->CreateSpendTransaction(bob, 10000, 5000, useThisTransaction); + EXPECT_TRUE(alice->CommitTransaction(aliceToBob.transaction, aliceToBob.reserveKey)); + } // alice attempts to double spend the vout and send something to charlie - CMutableTransaction aliceToCharlieMutable; - CTxIn aliceIn2; - aliceIn2.prevout.hash = fundAlice.GetHash(); - aliceIn2.prevout.n = 0; - aliceToCharlieMutable.vin.push_back(aliceIn2); - CTxOut charlieOut; - charlieOut.scriptPubKey = GetScriptForDestination(charlie->GetPubKey()); - charlieOut.nValue = 10000; - aliceToCharlieMutable.vout.push_back(charlieOut); - CTxOut aliceRemainder2; - aliceRemainder2.scriptPubKey = GetScriptForDestination(alice->GetPubKey()); - aliceRemainder2.nValue = fundAlice.vout[0].nValue - 10000; - aliceToCharlieMutable.vout.push_back(aliceRemainder2); - hash = SignatureHash(fundAlice.vout[0].scriptPubKey, aliceToCharlieMutable, 0, SIGHASH_ALL, 0, 0); - aliceToCharlieMutable.vin[0].scriptSig << alice->Sign(hash, SIGHASH_ALL); - CTransaction aliceToCharlieTx(aliceToCharlieMutable); - // construct the block - CBlock block; - // first a coinbase tx - auto consensusParams = Params().GetConsensus(); - CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, newHeight); - txNew.vin.resize(1); - txNew.vin[0].prevout.SetNull(); - txNew.vin[0].scriptSig = (CScript() << newHeight << CScriptNum(1)) + COINBASE_FLAGS; - txNew.vout.resize(1); - txNew.vout[0].nValue = GetBlockSubsidy(newHeight,consensusParams); - txNew.nExpiryHeight = 0; - block.vtx.push_back(CTransaction(txNew)); - // then the actual txs - block.vtx.push_back(fundAlice); - block.vtx.push_back(aliceToBobTx); - block.vtx.push_back(aliceToCharlieTx); - CValidationState state; - // create a new CBlockIndex to forward to ConnectBlock - auto index = chain.GetIndex(); - CBlockIndex newIndex; - newIndex.pprev = index; - EXPECT_FALSE( chain.ConnectBlock(block, state, &newIndex, true, false) ); - EXPECT_EQ(state.GetRejectReason(), "bad-txns-inputs-missingorspent"); + { + CCoinControl useThisTransaction; + COutPoint tx(fundAlice.transaction.GetHash(), 1); + useThisTransaction.Select(tx); + TransactionInProcess aliceToCharlie = alice->CreateSpendTransaction(charlie, 10000, 5000, useThisTransaction); + CValidationState state; + EXPECT_FALSE(alice->CommitTransaction(aliceToCharlie.transaction, aliceToCharlie.reserveKey, state)); + EXPECT_EQ(state.GetRejectReason(), "mempool conflict"); + } + /* + EXPECT_EQ(mempool.size(), 3); + CValidationState validationState; + std::shared_ptr block = chain.generateBlock(notary, &validationState); + EXPECT_EQ( block, nullptr ); + EXPECT_EQ( validationState.GetRejectReason(), "bad-txns-inputs-missingorspent"); + */ } bool CalcPoW(CBlock *pblock); -TEST(block_tests, TestProcessBlock) +TEST(test_block, TestProcessBlock) { TestChain chain; EXPECT_EQ(chain.GetIndex()->nHeight, 0); - auto notary = chain.AddWallet(chain.getNotaryKey()); - auto alice = chain.AddWallet(); - auto bob = chain.AddWallet(); - auto charlie = chain.AddWallet(); - CBlock lastBlock = chain.generateBlock(); // gives notary everything + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + auto alice = std::make_shared("alice"); + auto bob = std::make_shared("bob"); + auto charlie = std::make_shared("charlie"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // gives notary everything EXPECT_EQ(chain.GetIndex()->nHeight, 1); chain.IncrementChainTime(); - auto notaryPrevOut = notary->GetAvailable(100000); // add a transaction to the mempool - CTransaction fundAlice = notary->CreateSpendTransaction(alice, 100000); - EXPECT_TRUE( chain.acceptTx(fundAlice).IsValid() ); + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000); + EXPECT_TRUE( chain.acceptTx(fundAlice.transaction).IsValid() ); // construct the block CBlock block; int32_t newHeight = chain.GetIndex()->nHeight + 1; @@ -234,7 +185,7 @@ TEST(block_tests, TestProcessBlock) // finish constructing the block block.nBits = GetNextWorkRequired( chain.GetIndex(), &block, Params().GetConsensus()); block.nTime = GetTime(); - block.hashPrevBlock = lastBlock.GetHash(); + block.hashPrevBlock = lastBlock->GetHash(); block.hashMerkleRoot = block.BuildMerkleTree(); // Add the PoW EXPECT_TRUE(CalcPoW(&block)); @@ -246,18 +197,17 @@ TEST(block_tests, TestProcessBlock) EXPECT_EQ(mempool.size(), 1); } -TEST(block_tests, TestProcessBadBlock) +TEST(test_block, TestProcessBadBlock) { TestChain chain; - auto notary = chain.AddWallet(chain.getNotaryKey()); - auto alice = chain.AddWallet(); - auto bob = chain.AddWallet(); - auto charlie = chain.AddWallet(); - CBlock lastBlock = chain.generateBlock(); // genesis block - auto notaryPrevOut = notary->GetAvailable(100000); + auto notary = std::make_shared(chain.getNotaryKey(), "notary"); + auto alice = std::make_shared("alice"); + auto bob = std::make_shared("bob"); + auto charlie = std::make_shared("charlie"); + std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block // add a transaction to the mempool - CTransaction fundAlice = notary->CreateSpendTransaction(alice, 100000); - EXPECT_TRUE( chain.acceptTx(fundAlice).IsValid() ); + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000); + EXPECT_TRUE( chain.acceptTx(fundAlice.transaction).IsValid() ); // construct the block CBlock block; int32_t newHeight = chain.GetIndex()->nHeight + 1; diff --git a/src/test-komodo/test_coins.cpp b/src/test-komodo/test_coins.cpp index 5ec26b2d31e..ef14be5833b 100644 --- a/src/test-komodo/test_coins.cpp +++ b/src/test-komodo/test_coins.cpp @@ -887,7 +887,7 @@ TEST(TestCoins, coins_coinbase_spends) { CTransaction tx2(mtx2); - EXPECT_TRUE(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); + EXPECT_TRUE(Consensus::CheckTxInputs(tx2, state, cache, 100+ Params().CoinbaseMaturity(), Params().GetConsensus())); } mtx2.vout.resize(1); @@ -896,7 +896,7 @@ TEST(TestCoins, coins_coinbase_spends) { CTransaction tx2(mtx2); - EXPECT_FALSE(Consensus::CheckTxInputs(tx2, state, cache, 100+COINBASE_MATURITY, Params().GetConsensus())); + EXPECT_FALSE(Consensus::CheckTxInputs(tx2, state, cache, 100+Params().CoinbaseMaturity(), Params().GetConsensus())); EXPECT_TRUE(state.GetRejectReason() == "bad-txns-coinbase-spend-has-transparent-outputs"); } } diff --git a/src/test-komodo/testutils.cpp b/src/test-komodo/testutils.cpp index 1b552d0b95a..9119adbf19e 100644 --- a/src/test-komodo/testutils.cpp +++ b/src/test-komodo/testutils.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "core_io.h" #include "key.h" @@ -19,15 +20,15 @@ #include "script/cc.h" #include "script/interpreter.h" #include "komodo_extern_globals.h" - +#include "utilmoneystr.h" #include "testutils.h" - +#include "coincontrol.h" +#include "cc/CCinclude.h" std::string notaryPubkey = "0205a8ad0c1dbc515f149af377981aab58b836af008d4d7ab21bd76faf80550b47"; std::string notarySecret = "UxFWWxsf1d7w7K5TvAWSkeX4H95XQKwdwGv49DXwWUTzPTTjHBbU"; CKey notaryKey; - /* * We need to have control of clock, * otherwise block production can fail. @@ -39,6 +40,44 @@ extern std::string NOTARY_PUBKEY; void adjust_hwmheight(int32_t in); // in komodo.cpp CCriticalSection& get_cs_main(); // in main.cpp +std::shared_ptr generateBlock(CWallet* wallet, CValidationState* state = nullptr); // in mining.cpp + +void displayTransaction(const CTransaction& tx) +{ + std::cout << "Transaction Hash: " << tx.GetHash().ToString(); + for(size_t i = 0; i < tx.vin.size(); ++i) + { + std::cout << "\nvIn " << i + << " prevout hash : " << tx.vin[i].prevout.hash.ToString() + << " n: " << tx.vin[i].prevout.n; + } + for(size_t i = 0; i < tx.vout.size(); ++i) + { + std::cout << "\nvOut " << i + << " nValue: " << tx.vout[i].nValue + << " scriptPubKey: " << tx.vout[i].scriptPubKey.ToString() + << " interest: " << tx.vout[i].interest; + } + std::cout << "\n"; +} + +void displayBlock(const CBlock& blk) +{ + std::cout << "Block Hash: " << blk.GetHash().ToString() + << "\nPrev Hash: " << blk.hashPrevBlock.ToString() + << "\n"; + for(size_t i = 0; i < blk.vtx.size(); ++i) + { + std::cout << i << " "; + displayTransaction(blk.vtx[i]); + } + std::cout << "\n"; +} + +void setConsoleDebugging(bool enable) +{ + fPrintToConsole = enable; +} void setupChain() { @@ -48,7 +87,6 @@ void setupChain() NOTARY_PUBKEY = notaryPubkey; USE_EXTERNAL_PUBKEY = 1; mapArgs["-mineraddress"] = "bogus"; - COINBASE_MATURITY = 1; // Global mock time nMockTime = GetTime(); @@ -175,6 +213,7 @@ TestChain::TestChain() mapArgs["-datadir"] = dataDir.string(); setupChain(); + USE_EXTERNAL_PUBKEY = 0; // we want control of who mines the block CBitcoinSecret vchSecret; vchSecret.SetString(notarySecret); // this returns false due to network prefix mismatch but works anyway notaryKey = vchSecret.GetKey(); @@ -183,6 +222,8 @@ TestChain::TestChain() TestChain::~TestChain() { CleanGlobals(); + // cruel and crude, but cleans up any wallet dbs so subsequent tests run. + bitdb = std::shared_ptr(new CDBEnv{}); boost::filesystem::remove_all(dataDir); if (previousNetwork == "main") SelectParams(CBaseChainParams::MAIN); @@ -193,6 +234,8 @@ TestChain::~TestChain() } +boost::filesystem::path TestChain::GetDataDir() { return dataDir; } + void TestChain::CleanGlobals() { // hwmheight can get skewed if komodo_connectblock not called (which some tests do) @@ -228,14 +271,17 @@ CCoinsViewCache *TestChain::GetCoinsViewCache() return pcoinsTip; } -CBlock TestChain::generateBlock() +std::shared_ptr TestChain::generateBlock(std::shared_ptr wallet, CValidationState* state) { - CBlock block; - ::generateBlock(&block); - for(auto wallet : toBeNotified) + std::shared_ptr block; + if (wallet == nullptr) { - wallet->BlockNotification(block); + CBlock blk; + ::generateBlock(&blk); + block = std::shared_ptr(new CBlock(blk) ); } + else + block = ::generateBlock(wallet.get(), state); return block; } @@ -257,36 +303,42 @@ CValidationState TestChain::acceptTx(const CTransaction& tx) return retVal; } -std::shared_ptr TestChain::AddWallet(const CKey& in) -{ - std::shared_ptr retVal = std::make_shared(this, in); - toBeNotified.push_back(retVal); - return retVal; -} - -std::shared_ptr TestChain::AddWallet() +/****** + * @brief A wallet for testing + * @param chain the chain + * @param name a name for the wallet + */ +TestWallet::TestWallet(const std::string& name) + : CWallet( name + ".dat") { - std::shared_ptr retVal = std::make_shared(this); - toBeNotified.push_back(retVal); - return retVal; + key.MakeNewKey(true); + LOCK(cs_wallet); + bool firstRunRet; + DBErrors err = LoadWallet(firstRunRet); + AddKey(key); + RegisterValidationInterface(this); } - -/*** - * A simplistic (dumb) wallet for helping with testing - * - It does not keep track of spent transactions - * - Blocks containing vOuts that apply are added to the front of a vector +/****** + * @brief A wallet for testing + * @param chain the chain + * @param in a key that already exists + * @param name a name for the wallet */ - -TestWallet::TestWallet(TestChain* chain) : chain(chain) +TestWallet::TestWallet(const CKey& in, const std::string& name) + : CWallet( name + ".dat"), key(in) { - key.MakeNewKey(true); - destScript = GetScriptForDestination(key.GetPubKey()); + LOCK( cs_wallet ); + bool firstRunRet; + DBErrors err = LoadWallet(firstRunRet); + AddKey(key); + RegisterValidationInterface(this); } -TestWallet::TestWallet(TestChain* chain, const CKey& in) : chain(chain), key(in) +TestWallet::~TestWallet() { - destScript = GetScriptForDestination(key.GetPubKey()); + UnregisterValidationInterface(this); + // TODO: remove file } /*** @@ -304,7 +356,7 @@ CKey TestWallet::GetPrivKey() const { return key; } * @param hash the hash to sign * @param hashType SIGHASH_ALL or something similar * @returns the bytes to add to ScriptSig - */ +*/ std::vector TestWallet::Sign(uint256 hash, unsigned char hashType) { std::vector retVal; @@ -318,7 +370,7 @@ std::vector TestWallet::Sign(uint256 hash, unsigned char hashType * @param cc the cryptocondition * @param hash the hash to sign * @returns the bytes to add to ScriptSig - */ +*/ std::vector TestWallet::Sign(CC* cc, uint256 hash) { int out = cc_signTreeSecp256k1Msg32(cc, key.begin(), hash.begin()); @@ -326,85 +378,525 @@ std::vector TestWallet::Sign(CC* cc, uint256 hash) } /*** - * Notifies this wallet of a new block + * Transfer to another user + * @param to who to transfer to + * @param amount the amount + * @returns the results */ -void TestWallet::BlockNotification(const CBlock& block) +CTransaction TestWallet::Transfer(std::shared_ptr to, CAmount amount, CAmount fee) +{ + TransactionInProcess tip = CreateSpendTransaction(to, amount, fee); + if (!CWallet::CommitTransaction( tip.transaction, tip.reserveKey)) + throw std::logic_error("Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here."); + return tip.transaction; +} + +/************* + * @brief Create a transaction, do not place in mempool + * @note throws std::logic_error if there was a problem + * @param to who to send to + * @param amount the amount to send + * @param fee the fee + * @returns the transaction +*/ +TransactionInProcess TestWallet::CreateSpendTransaction(std::shared_ptr to, + CAmount amount, CAmount fee, bool commit) { - // TODO: remove spent txs from availableTransactions - // see if this block has any outs for me - for( auto tx : block.vtx ) + CAmount curBalance = this->GetBalance(); + CAmount curImatureBalance = this->GetImmatureBalance(); + CAmount curUnconfirmedBalance = this->GetUnconfirmedBalance(); + + // Check amount + if (amount <= 0) + throw std::logic_error("Invalid amount"); + + if (amount > curBalance) + throw std::logic_error("Insufficient funds"); + + // Build recipient vector + std::vector vecSend; + bool fSubtractFeeFromAmount = false; + CRecipient recipient = {GetScriptForDestination(to->GetPubKey()), amount, fSubtractFeeFromAmount}; + vecSend.push_back(recipient); + // other items needed for transaction creation call + CAmount nFeeRequired; + std::string strError; + int nChangePosRet = -1; + TransactionInProcess retVal(this); + if (!CWallet::CreateTransaction(vecSend, retVal.transaction, retVal.reserveKey, nFeeRequired, + nChangePosRet, strError)) { - for(uint32_t i = 0; i < tx.vout.size(); ++i) - { - if (tx.vout[i].scriptPubKey == destScript) - { - availableTransactions.insert(availableTransactions.begin(), std::pair(tx, i)); - break; // skip to next tx - } - } + if (!fSubtractFeeFromAmount && amount + nFeeRequired > GetBalance()) + strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", + FormatMoney(nFeeRequired)); + throw std::logic_error(strError); } + + if (commit && !CommitTransaction(retVal.transaction, retVal.reserveKey)) + { + std::logic_error("Unable to commit transaction"); + } + + return retVal; } -/*** - * Get a transaction that has funds - * NOTE: If no single transaction matches, throws - * @param needed how much is needed - * @returns a pair of CTransaction and the n value of the vout - */ -std::pair TestWallet::GetAvailable(CAmount needed) +/************* + * @brief Create a transaction, do not place in mempool + * @note throws std::logic_error if there was a problem + * @param to who to send to + * @param amount the amount to send + * @param fee the fee + * @param txToSpend the specific transaction to spend (ok if not transmitted yet) + * @returns the transaction +*/ +TransactionInProcess TestWallet::CreateSpendTransaction(std::shared_ptr to, + CAmount amount, CAmount fee, CCoinControl& coinControl) { - for(auto txp : availableTransactions) + // verify the passed-in transaction has enough funds + std::vector availableTxs; + coinControl.ListSelected(availableTxs); + CTransaction tx; + uint256 hashBlock; + if (!myGetTransaction(availableTxs[0].hash, tx, hashBlock)) + throw std::logic_error("Requested tx not found"); + + CAmount curBalance = tx.vout[availableTxs[0].n].nValue; + + // Check amount + if (amount <= 0) + throw std::logic_error("Invalid amount"); + + if (amount > curBalance) + throw std::logic_error("Insufficient funds"); + + // Build recipient vector + std::vector vecSend; + bool fSubtractFeeFromAmount = false; + CRecipient recipient = {GetScriptForDestination(to->GetPubKey()), amount, fSubtractFeeFromAmount}; + vecSend.push_back(recipient); + // other items needed for transaction creation call + CAmount nFeeRequired; + std::string strError; + int nChangePosRet = -1; + TransactionInProcess retVal(this); + if (!CreateTransaction(vecSend, retVal.transaction, retVal.reserveKey, strError, &coinControl)) { - CTransaction tx = txp.first; - uint32_t n = txp.second; - if (tx.vout[n].nValue >= needed) - return txp; + if (!fSubtractFeeFromAmount && amount + nFeeRequired > curBalance) + strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", + FormatMoney(nFeeRequired)); + throw std::logic_error(strError); } - throw std::logic_error("No Funds"); + + return retVal; } -/*** - * Add a transaction to the list of available vouts - * @param tx the transaction - * @param n the n value of the vout +/**** + * @brief create a transaction spending a vout that is not yet in the wallet + * @param vecSend the recipients + * @param wtxNew the resultant tx + * @param reserveKey the key used + * @param strFailReason the reason for any failure + * @param outputControl the tx to spend + * @returns true on success */ -void TestWallet::AddOut(CTransaction tx, uint32_t n) +bool TestWallet::CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, + CReserveKey& reservekey, std::string& strFailReason, CCoinControl* coinControl) { - availableTransactions.insert(availableTransactions.begin(), std::pair(tx, n)); + bool sign = true; + int nChangePosRet = 0; + uint64_t interest2 = 0; + CAmount nValue = 0; + unsigned int nSubtractFeeFromAmount = 0; + BOOST_FOREACH (const CRecipient& recipient, vecSend) + { + if (nValue < 0 || recipient.nAmount < 0) + { + strFailReason = _("Transaction amounts must be positive"); + return false; + } + nValue += recipient.nAmount; + + if (recipient.fSubtractFeeFromAmount) + nSubtractFeeFromAmount++; + } + if (vecSend.empty() || nValue < 0) + { + strFailReason = _("Transaction amounts must be positive"); + return false; + } + + wtxNew.fTimeReceivedIsTxTime = true; + wtxNew.BindWallet(this); + int nextBlockHeight = chainActive.Height() + 1; + CMutableTransaction txNew = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nextBlockHeight); + + if (IS_MODE_EXCHANGEWALLET && ASSETCHAINS_SYMBOL[0] == 0) + txNew.nLockTime = 0; + else + { + if ( !komodo_hardfork_active((uint32_t)chainActive.LastTip()->nTime) ) + txNew.nLockTime = (uint32_t)chainActive.LastTip()->nTime + 1; // set to a time close to now + else + txNew.nLockTime = (uint32_t)chainActive.Tip()->GetMedianTimePast(); + } + + // Activates after Overwinter network upgrade + if (NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + if (txNew.nExpiryHeight >= TX_EXPIRY_HEIGHT_THRESHOLD){ + strFailReason = _("nExpiryHeight must be less than TX_EXPIRY_HEIGHT_THRESHOLD."); + return false; + } + } + + unsigned int max_tx_size = MAX_TX_SIZE_AFTER_SAPLING; + if (!NetworkUpgradeActive(nextBlockHeight, Params().GetConsensus(), Consensus::UPGRADE_SAPLING)) { + max_tx_size = MAX_TX_SIZE_BEFORE_SAPLING; + } +/* + // Discourage fee sniping. + // + // However because of a off-by-one-error in previous versions we need to + // neuter it by setting nLockTime to at least one less than nBestHeight. + // Secondly currently propagation of transactions created for block heights + // corresponding to blocks that were just mined may be iffy - transactions + // aren't re-accepted into the mempool - we additionally neuter the code by + // going ten blocks back. Doesn't yet do anything for sniping, but does act + // to shake out wallet bugs like not showing nLockTime'd transactions at + // all. + txNew.nLockTime = std::max(0, chainActive.Height() - 10); + + // Secondly occasionally randomly pick a nLockTime even further back, so + // that transactions that are delayed after signing for whatever reason, + // e.g. high-latency mix networks and some CoinJoin implementations, have + // better privacy. + if (GetRandInt(10) == 0) + txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100)); + + assert(txNew.nLockTime <= (unsigned int)chainActive.Height()); + assert(txNew.nLockTime < LOCKTIME_THRESHOLD);*/ + + { + LOCK2(cs_main, cs_wallet); + { + CAmount nFeeRet = 0; + while (true) + { + txNew.vin.clear(); + txNew.vout.clear(); + wtxNew.fFromMe = true; + nChangePosRet = -1; + bool fFirst = true; + + CAmount nTotalValue = nValue; + if (nSubtractFeeFromAmount == 0) + nTotalValue += nFeeRet; + double dPriority = 0; + // vouts to the payees + BOOST_FOREACH (const CRecipient& recipient, vecSend) + { + CTxOut txout(recipient.nAmount, recipient.scriptPubKey); + + if (recipient.fSubtractFeeFromAmount) + { + txout.nValue -= nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient + + if (fFirst) // first receiver pays the remainder not divisible by output count + { + fFirst = false; + txout.nValue -= nFeeRet % nSubtractFeeFromAmount; + } + } + + if (txout.IsDust(::minRelayTxFee)) + { + if (recipient.fSubtractFeeFromAmount && nFeeRet > 0) + { + if (txout.nValue < 0) + strFailReason = _("The transaction amount is too small to pay the fee"); + else + strFailReason = _("The transaction amount is too small to send after the fee has been deducted"); + } + else + strFailReason = _("Transaction amount too small"); + return false; + } + txNew.vout.push_back(txout); + } + + // Choose coins to use + std::vector > setCoins; + CAmount nValueIn = 0; + interest2 = 0; + std::vector ctrlVec; + coinControl->ListSelected(ctrlVec); + for(const auto& p : ctrlVec) + { + CTransaction tx; + uint256 hashBlock; + if (myGetTransaction(p.hash, tx, hashBlock)) + { + setCoins.push_back(std::pair(tx, p.n)); + } + } + for(const auto& pcoin : setCoins) + { + CAmount nCredit = pcoin.first.vout[pcoin.second].nValue; + nValueIn += nCredit; + //The coin age after the next block (depth+1) is used instead of the current, + //reflecting an assumption the user would accept a bit more delay for + //a chance at a free transaction. + //But mempool inputs might still be in the mempool, so their age stays 0 + if ( !IS_MODE_EXCHANGEWALLET && ASSETCHAINS_SYMBOL[0] == 0 ) + { + interest2 += pcoin.first.vout[pcoin.second].interest; + } + int age = 0; + if (age != 0) + age += 1; + dPriority += (double)nCredit * age; + } + if ( ASSETCHAINS_SYMBOL[0] == 0 && DONATION_PUBKEY.size() == 66 && interest2 > 5000 ) + { + CScript scriptDonation = CScript() << ParseHex(DONATION_PUBKEY) << OP_CHECKSIG; + CTxOut newTxOut(interest2,scriptDonation); + int32_t nDonationPosRet = txNew.vout.size() - 1; // dont change first or last + std::vector::iterator position = txNew.vout.begin()+nDonationPosRet; + txNew.vout.insert(position, newTxOut); + interest2 = 0; + } + CAmount nChange = (nValueIn - nValue); + if (nSubtractFeeFromAmount == 0) + nChange -= nFeeRet; + + if (nChange > 0) + { + // Fill a vout to ourself + // TODO: pass in scriptChange instead of reservekey so + // change transaction isn't always pay-to-bitcoin-address + CScript scriptChange; + + // coin control: send change to custom address + if (coinControl && !boost::get(&coinControl->destChange)) + scriptChange = GetScriptForDestination(coinControl->destChange); + + // no coin control: send change to newly generated address + else + { + // Note: We use a new key here to keep it from being obvious which side is the change. + // The drawback is that by not reusing a previous key, the change may be lost if a + // backup is restored, if the backup doesn't have the new private key for the change. + // If we reused the old key, it would be possible to add code to look for and + // rediscover unknown transactions that were written with keys of ours to recover + // post-backup change. + + // Reserve a new key pair from key pool + CPubKey vchPubKey; + bool ret; + ret = reservekey.GetReservedKey(vchPubKey); + assert(ret); // should never fail, as we just unlocked + scriptChange = GetScriptForDestination(vchPubKey.GetID()); + } + + CTxOut newTxOut(nChange, scriptChange); + + // We do not move dust-change to fees, because the sender would end up paying more than requested. + // This would be against the purpose of the all-inclusive feature. + // So instead we raise the change and deduct from the recipient. + if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(::minRelayTxFee)) + { + CAmount nDust = newTxOut.GetDustThreshold(::minRelayTxFee) - newTxOut.nValue; + newTxOut.nValue += nDust; // raise change until no more dust + for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient + { + if (vecSend[i].fSubtractFeeFromAmount) + { + txNew.vout[i].nValue -= nDust; + if (txNew.vout[i].IsDust(::minRelayTxFee)) + { + strFailReason = _("The transaction amount is too small to send after the fee has been deducted"); + return false; + } + break; + } + } + } + + // Never create dust outputs; if we would, just + // add the dust to the fee. + if (newTxOut.IsDust(::minRelayTxFee)) + { + nFeeRet += nChange; + reservekey.ReturnKey(); + } + else + { + nChangePosRet = txNew.vout.size() - 1; // dont change first or last + std::vector::iterator position = txNew.vout.begin()+nChangePosRet; + txNew.vout.insert(position, newTxOut); + } + } else reservekey.ReturnKey(); + + // Fill vin + // + // Note how the sequence number is set to max()-1 so that the + // nLockTime set above actually works. + for(const auto& coin : setCoins) + txNew.vin.push_back(CTxIn(coin.first.GetHash(),coin.second,CScript(), + std::numeric_limits::max()-1)); + + // Check mempooltxinputlimit to avoid creating a transaction which the local mempool rejects + size_t limit = (size_t)GetArg("-mempooltxinputlimit", 0); + { + LOCK(cs_main); + if (NetworkUpgradeActive(chainActive.Height() + 1, Params().GetConsensus(), Consensus::UPGRADE_OVERWINTER)) { + limit = 0; + } + } + if (limit > 0) { + size_t n = txNew.vin.size(); + if (n > limit) { + strFailReason = _(strprintf("Too many transparent inputs %zu > limit %zu", n, limit).c_str()); + return false; + } + } + + // Grab the current consensus branch ID + auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); + + // Sign + int nIn = 0; + CTransaction txNewConst(txNew); + for(const auto& coin : setCoins) + { + bool signSuccess; + const CScript& scriptPubKey = coin.first.vout[coin.second].scriptPubKey; + SignatureData sigdata; + if (sign) + signSuccess = ProduceSignature(TransactionSignatureCreator( + this, &txNewConst, nIn, coin.first.vout[coin.second].nValue, SIGHASH_ALL), + scriptPubKey, sigdata, consensusBranchId); + else + signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId); + + if (!signSuccess) + { + strFailReason = _("Signing transaction failed"); + return false; + } else { + UpdateTransaction(txNew, nIn, sigdata); + } + + nIn++; + } + + unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION); + + // Remove scriptSigs if we used dummy signatures for fee calculation + if (!sign) { + BOOST_FOREACH (CTxIn& vin, txNew.vin) + vin.scriptSig = CScript(); + } + + // Embed the constructed transaction data in wtxNew. + *static_cast(&wtxNew) = CTransaction(txNew); + + // Limit size + if (nBytes >= max_tx_size) + { + strFailReason = _("Transaction too large"); + return false; + } + + dPriority = wtxNew.ComputePriority(dPriority, nBytes); + + // Can we complete this as a free transaction? + if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE) + { + // Not enough fee: enough priority? + double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget); + // Not enough mempool history to estimate: use hard-coded AllowFree. + if (dPriorityNeeded <= 0 && AllowFree(dPriority)) + break; + + // Small enough, and priority high enough, to send for free + if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded) + break; + } + + CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool); + if ( nFeeNeeded < 5000 ) + nFeeNeeded = 5000; + + // If we made it here and we aren't even able to meet the relay fee on the next pass, give up + // because we must be at the maximum allowed fee. + if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes)) + { + strFailReason = _("Transaction too large for fee policy"); + return false; + } + + if (nFeeRet >= nFeeNeeded) + break; // Done, enough fee included. + + // Include more fee and try again. + nFeeRet = nFeeNeeded; + continue; + } + } + } + + return true; } -/*** - * Transfer to another user - * @param to who to transfer to - * @param amount the amount - * @returns the results +/** + * Call after CreateTransaction unless you want to abort */ -CValidationState TestWallet::Transfer(std::shared_ptr to, CAmount amount, CAmount fee) +bool TestWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CValidationState& state) { - CTransaction fundTo(CreateSpendTransaction(to, amount, fee)); - return chain->acceptTx(fundTo); -} + { + LOCK2(cs_main, cs_wallet); + LogPrintf("CommitTransaction:\n%s", wtxNew.ToString()); + { + // This is only to keep the database open to defeat the auto-flush for the + // duration of this scope. This is the only place where this optimization + // maybe makes sense; please don't do it anywhere else. + CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r+") : NULL; -CTransaction TestWallet::CreateSpendTransaction(std::shared_ptr to, CAmount amount, CAmount fee) -{ - std::pair available = GetAvailable(amount + fee); - CMutableTransaction tx; - CTxIn incoming; - incoming.prevout.hash = available.first.GetHash(); - incoming.prevout.n = available.second; - tx.vin.push_back(incoming); - CTxOut out1; - out1.scriptPubKey = GetScriptForDestination(to->GetPubKey()); - out1.nValue = amount; - tx.vout.push_back(out1); - // give the rest back to wallet owner - CTxOut out2; - out2.scriptPubKey = GetScriptForDestination(key.GetPubKey()); - out2.nValue = available.first.vout[available.second].nValue - amount - fee; - tx.vout.push_back(out2); - - uint256 hash = SignatureHash(available.first.vout[available.second].scriptPubKey, tx, 0, SIGHASH_ALL, 0, 0); - tx.vin[0].scriptSig << Sign(hash, SIGHASH_ALL); - - return CTransaction(tx); + // Take key pair from key pool so it won't be used again + reservekey.KeepKey(); + + // Add tx to wallet, because if it has change it's also ours, + // otherwise just for transaction history. + AddToWallet(wtxNew, false, pwalletdb); + + // Notify that old coins are spent + std::set setCoins; + BOOST_FOREACH(const CTxIn& txin, wtxNew.vin) + { + CWalletTx &coin = mapWallet[txin.prevout.hash]; + coin.BindWallet(this); + NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED); + } + + if (fFileBacked) + delete pwalletdb; + } + + // Track how many getdata requests our transaction gets + mapRequestCount[wtxNew.GetHash()] = 0; + + if (fBroadcastTransactions) + { + // Broadcast + if (!::AcceptToMemoryPool(mempool, state, wtxNew, false, nullptr)) + { + fprintf(stderr,"commit failed\n"); + // This must not fail. The transaction has already been signed and recorded. + LogPrintf("CommitTransaction(): Error: Transaction not valid\n"); + return false; + } + wtxNew.RelayWalletTransaction(); + } + } + return true; } diff --git a/src/test-komodo/testutils.h b/src/test-komodo/testutils.h index 65e42a112b2..149366b2cdc 100644 --- a/src/test-komodo/testutils.h +++ b/src/test-komodo/testutils.h @@ -1,6 +1,8 @@ #pragma once #include "main.h" +#include "wallet/wallet.h" +#include "consensus/validation.h" #define VCH(a,b) std::vector(a, a + b) @@ -14,6 +16,18 @@ extern std::string notaryPubkey; extern std::string notarySecret; extern CKey notaryKey; +/*** + * @brief Look inside a transaction + * @param tx the transaction to look at + */ +void displayTransaction(const CTransaction& tx); +/**** + * @brief Look inside a block + * @param blk the block to look at + */ +void displayBlock(const CBlock& blk); + +void setConsoleDebugging(bool enable); void setupChain(); /*** @@ -33,6 +47,13 @@ CTransaction getInputTx(CScript scriptPubKey); CMutableTransaction spendTx(const CTransaction &txIn, int nOut=0); std::vector getSig(const CMutableTransaction mtx, CScript inputPubKey, int nIn=0); +class TransactionInProcess +{ +public: + TransactionInProcess(CWallet* wallet) : reserveKey(wallet) {} + CWalletTx transaction; + CReserveKey reserveKey; +}; class TestWallet; @@ -62,7 +83,8 @@ class TestChain * Generate a block * @returns the block generated */ - CBlock generateBlock(); + std::shared_ptr generateBlock(std::shared_ptr wallet, + CValidationState* validationState = nullptr); /**** * @brief set the chain time to something reasonable * @note must be called after generateBlock if you @@ -79,17 +101,6 @@ class TestChain * @returns the results */ CValidationState acceptTx(const CTransaction &tx); - /*** - * Creates a wallet with a specific key - * @param key the key - * @returns the wallet - */ - std::shared_ptr AddWallet(const CKey &key); - /**** - * Create a wallet - * @returns the wallet - */ - std::shared_ptr AddWallet(); /**** * @brief attempt to connect a block to the chain * @param block the block to connect @@ -101,23 +112,23 @@ class TestChain */ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, bool fJustCheck = false,bool fCheckPOW = false); + + boost::filesystem::path GetDataDir(); private: - std::vector> toBeNotified; boost::filesystem::path dataDir; std::string previousNetwork; void CleanGlobals(); }; /*** - * A simplistic (dumb) wallet for helping with testing - * - It does not keep track of spent transactions - * - Blocks containing vOuts that apply are added to the front of a vector + * An easy-to-use wallet for testing Komodo */ -class TestWallet +class TestWallet : public CWallet { public: - TestWallet(TestChain* chain); - TestWallet(TestChain* chain, const CKey& in); + TestWallet(const std::string& name); + TestWallet(const CKey& in, const std::string& name); + ~TestWallet(); /*** * @returns the public key */ @@ -140,23 +151,6 @@ class TestWallet * @returns the bytes to add to ScriptSig */ std::vector Sign(CC* cc, uint256 hash); - /*** - * Notifies this wallet of a new block - */ - void BlockNotification(const CBlock& block); - /*** - * Get a transaction that has funds - * NOTE: If no single transaction matches, throws - * @param needed how much is needed - * @returns a pair of CTransaction and the n value of the vout - */ - std::pair GetAvailable(CAmount needed); - /*** - * Add a transaction to the list of available vouts - * @param tx the transaction - * @param n the n value of the vout - */ - void AddOut(CTransaction tx, uint32_t n); /***** * @brief create a transaction with 1 recipient (signed) * @param to who to send funds to @@ -164,17 +158,39 @@ class TestWallet * @param fee * @returns the transaction */ - CTransaction CreateSpendTransaction(std::shared_ptr to, CAmount amount, CAmount fee = 0); + TransactionInProcess CreateSpendTransaction(std::shared_ptr to, CAmount amount, + CAmount fee = 0, bool commit = true); + /************* + * @brief Create a transaction, do not place in mempool + * @note throws std::logic_error if there was a problem + * @param to who to send to + * @param amount the amount to send + * @param fee the fee + * @param txToSpend the specific transaction to spend (ok if not transmitted yet) + * @returns the transaction + */ + TransactionInProcess CreateSpendTransaction(std::shared_ptr to, + CAmount amount, CAmount fee, CCoinControl& coinControl); + /**** + * @brief create a transaction spending a vout that is not yet in the wallet + * @param vecSend the recipients + * @param wtxNew the resultant tx + * @param reserveKey the key used + * @param strFailReason the reason for any failure + * @param outputControl the tx to spend + * @returns true on success + */ + bool CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, + CReserveKey& reservekey, std::string& strFailReason, CCoinControl* coinControl); + using CWallet::CommitTransaction; + bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CValidationState& state); /*** * Transfer to another user (sends to mempool) * @param to who to transfer to * @param amount the amount * @returns the results */ - CValidationState Transfer(std::shared_ptr to, CAmount amount, CAmount fee = 0); + CTransaction Transfer(std::shared_ptr to, CAmount amount, CAmount fee = 0); private: - TestChain *chain; CKey key; - std::vector> availableTransactions; - CScript destScript; }; diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index 522f0d8f293..27b3917e027 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -91,7 +91,7 @@ TestingSetup::TestingSetup() // instead of unit tests, but for now we need these here. RegisterAllCoreRPCCommands(tableRPC); #ifdef ENABLE_WALLET - bitdb.MakeMock(); + bitdb->MakeMock(); RegisterWalletRPCCommands(tableRPC); #endif ClearDatadirCache(); @@ -129,8 +129,8 @@ TestingSetup::~TestingSetup() delete pcoinsdbview; delete pblocktree; #ifdef ENABLE_WALLET - bitdb.Flush(true); - bitdb.Reset(); + bitdb->Flush(true); + bitdb->Reset(); #endif boost::filesystem::remove_all(pathTemp); } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 2ff9dd051ff..24fd01101c1 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -31,7 +31,6 @@ #include "utilmoneystr.h" #include "validationinterface.h" #include "version.h" -#define _COINBASE_MATURITY 100 using namespace std; @@ -399,7 +398,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem // Remove transactions spending a coinbase which are now immature extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; if ( ASSETCHAINS_SYMBOL[0] == 0 ) - COINBASE_MATURITY = _COINBASE_MATURITY; + Params().ResetCoinbaseMaturity(); // Remove transactions spending a coinbase which are now immature and no-longer-final transactions LOCK(cs); list transactionsToRemove; @@ -414,7 +413,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem continue; const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash); if (nCheckFrequency != 0) assert(coins); - if (!coins || (coins->IsCoinBase() && (((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY) && + if (!coins || (coins->IsCoinBase() && (((signed long)nMemPoolHeight) - coins->nHeight < Params().CoinbaseMaturity()) && ((signed long)nMemPoolHeight < komodo_block_unlocktime(coins->nHeight) && coins->IsAvailable(0) && coins->vout[0].nValue >= ASSETCHAINS_TIMELOCKGTE))) { transactionsToRemove.push_back(tx); diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index dd0880b756a..f1ca0f51197 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -46,7 +46,10 @@ unsigned int nWalletDBUpdated; // CDB // -CDBEnv bitdb; +// A singleton for all wallets in this process +// Making this a static variable causes problems with testing, so +// switching to a shared_ptr +std::shared_ptr bitdb(new CDBEnv()); void CDBEnv::EnvShutdown() { @@ -254,17 +257,17 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose nFlags |= DB_CREATE; { - LOCK(bitdb.cs_db); - if (!bitdb.Open(GetDataDir())) + LOCK(bitdb->cs_db); + if (!bitdb->Open(GetDataDir())) throw runtime_error("CDB: Failed to open database environment."); strFile = strFilename; - ++bitdb.mapFileUseCount[strFile]; - pdb = bitdb.mapDb[strFile]; + ++bitdb->mapFileUseCount[strFile]; + pdb = bitdb->mapDb[strFile]; if (pdb == NULL) { - pdb = new Db(bitdb.dbenv, 0); + pdb = new Db(bitdb->dbenv, 0); - bool fMockDb = bitdb.IsMock(); + bool fMockDb = bitdb->IsMock(); if (fMockDb) { DbMpoolFile* mpf = pdb->get_mpf(); ret = mpf->set_flags(DB_MPOOL_NOFILE, 1); @@ -282,7 +285,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose if (ret != 0) { delete pdb; pdb = NULL; - --bitdb.mapFileUseCount[strFile]; + --bitdb->mapFileUseCount[strFile]; strFile = ""; throw runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFile)); } @@ -294,7 +297,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose fReadOnly = fTmp; } - bitdb.mapDb[strFile] = pdb; + bitdb->mapDb[strFile] = pdb; } } } @@ -309,7 +312,7 @@ void CDB::Flush() if (fReadOnly) nMinutes = 1; - bitdb.dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0); + bitdb->dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0); } void CDB::Close() @@ -325,8 +328,8 @@ void CDB::Close() Flush(); { - LOCK(bitdb.cs_db); - --bitdb.mapFileUseCount[strFile]; + LOCK(bitdb->cs_db); + --bitdb->mapFileUseCount[strFile]; } } @@ -357,19 +360,19 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) { while (true) { { - LOCK(bitdb.cs_db); - if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0) { + LOCK(bitdb->cs_db); + if (!bitdb->mapFileUseCount.count(strFile) || bitdb->mapFileUseCount[strFile] == 0) { // Flush log data to the dat file - bitdb.CloseDb(strFile); - bitdb.CheckpointLSN(strFile); - bitdb.mapFileUseCount.erase(strFile); + bitdb->CloseDb(strFile); + bitdb->CheckpointLSN(strFile); + bitdb->mapFileUseCount.erase(strFile); bool fSuccess = true; LogPrintf("CDB::Rewrite: Rewriting %s...\n", strFile); string strFileRes = strFile + ".rewrite"; { // surround usage of db with extra {} CDB db(strFile.c_str(), "r"); - Db* pdbCopy = new Db(bitdb.dbenv, 0); + Db* pdbCopy = new Db(bitdb->dbenv, 0); int ret = pdbCopy->open(NULL, // Txn pointer strFileRes.c_str(), // Filename @@ -412,17 +415,17 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip) } if (fSuccess) { db.Close(); - bitdb.CloseDb(strFile); + bitdb->CloseDb(strFile); if (pdbCopy->close(0)) fSuccess = false; delete pdbCopy; } } if (fSuccess) { - Db dbA(bitdb.dbenv, 0); + Db dbA(bitdb->dbenv, 0); if (dbA.remove(strFile.c_str(), NULL, 0)) fSuccess = false; - Db dbB(bitdb.dbenv, 0); + Db dbB(bitdb->dbenv, 0); if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) fSuccess = false; } diff --git a/src/wallet/db.h b/src/wallet/db.h index 8ad246de434..dd9d50a56f5 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -60,7 +60,7 @@ class CDBEnv public: mutable CCriticalSection cs_db; - DbEnv *dbenv; + DbEnv *dbenv = nullptr; std::map mapFileUseCount; std::map mapDb; @@ -109,7 +109,7 @@ class CDBEnv } }; -extern CDBEnv bitdb; +extern std::shared_ptr bitdb; /** RAII class that provides access to a Berkeley database */ @@ -292,7 +292,7 @@ class CDB { if (!pdb || activeTxn) return false; - DbTxn* ptxn = bitdb.TxnBegin(); + DbTxn* ptxn = bitdb->TxnBegin(); if (!ptxn) return false; activeTxn = ptxn; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e69e67c231a..07654acbbdc 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -771,12 +771,12 @@ set CWallet::GetConflicts(const uint256& txid) const void CWallet::Flush(bool shutdown) { - bitdb.Flush(shutdown); + bitdb->Flush(shutdown); } bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString) { - if (!bitdb.Open(GetDataDir())) + if (!bitdb->Open(GetDataDir())) { // try moving the database env out of the way boost::filesystem::path pathDatabase = GetDataDir() / "database"; @@ -789,7 +789,7 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er } // try again - if (!bitdb.Open(GetDataDir())) { + if (!bitdb->Open(GetDataDir())) { // if it still fails, it probably means we can't even create the database env string msg = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()); errorString += msg; @@ -800,13 +800,13 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er if (GetBoolArg("-salvagewallet", false)) { // Recover readable keypairs: - if (!CWalletDB::Recover(bitdb, walletFile, true)) + if (!CWalletDB::Recover(*bitdb, walletFile, true)) return false; } if (boost::filesystem::exists(GetDataDir() / walletFile)) { - CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover); + CDBEnv::VerifyResult r = bitdb->Verify(walletFile, CWalletDB::Recover); if (r == CDBEnv::RECOVER_OK) { warningString += strprintf(_("Warning: wallet.dat corrupt, data salvaged!" @@ -1179,7 +1179,7 @@ bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t n assert((nWitnessCacheSize - 1) >= nd->witnesses.size()); } } - assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0 || WITNESS_CACHE_SIZE != _COINBASE_MATURITY+10); + assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0 || WITNESS_CACHE_SIZE != Params().CoinbaseMaturity()+10); return true; } @@ -1193,7 +1193,7 @@ void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex) if (!::DecrementNoteWitnesses(wtxItem.second.mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize)) needsRescan = true; } - if ( WITNESS_CACHE_SIZE == _COINBASE_MATURITY+10 ) + if ( WITNESS_CACHE_SIZE == Params().CoinbaseMaturity()+10 ) { nWitnessCacheSize -= 1; // TODO: If nWitnessCache is zero, we need to regenerate the caches (#1302) @@ -3517,7 +3517,9 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int return true; } -bool CWallet::SelectCoins(const CAmount& nTargetValue, set >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl* coinControl) const +bool CWallet::SelectCoins(const CAmount& nTargetValue, set >& setCoinsRet, + CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, + const CCoinControl* coinControl) const { // Output parameter fOnlyCoinbaseCoinsRet is set to true when the only available coins are coinbase utxos. uint64_t tmp; int32_t retval; @@ -3614,7 +3616,16 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set vecSend; @@ -3658,8 +3669,20 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC return true; } -bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, - int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign) +/***** + * @brief create a transaction + * @param vecSend who to send to + * @param wtxNew wallet transaction + * @param reservekey + * @param nFeeRet + * @param nChangePosRet + * @param strFailReason + * @param coinControl + * @param sign true to sign inputs + */ +bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, + CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, + bool sign) { uint64_t interest2 = 0; CAmount nValue = 0; unsigned int nSubtractFeeFromAmount = 0; BOOST_FOREACH (const CRecipient& recipient, vecSend) @@ -4876,14 +4899,14 @@ int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const int CMerkleTx::GetBlocksToMaturity() const { if ( ASSETCHAINS_SYMBOL[0] == 0 ) - COINBASE_MATURITY = _COINBASE_MATURITY; + Params().ResetCoinbaseMaturity(); if (!IsCoinBase()) return 0; int32_t depth = GetDepthInMainChain(); int32_t ut = UnlockTime(0); int32_t toMaturity = (ut - chainActive.Height()) < 0 ? 0 : ut - chainActive.Height(); //printf("depth.%i, unlockTime.%i, toMaturity.%i\n", depth, ut, toMaturity); - ut = (COINBASE_MATURITY - depth) < 0 ? 0 : COINBASE_MATURITY - depth; + ut = (Params().CoinbaseMaturity() - depth) < 0 ? 0 : Params().CoinbaseMaturity() - depth; return(ut < toMaturity ? toMaturity : ut); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b1e5b66b82a..49e935ba06f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -747,6 +747,8 @@ class CAccountingEntry */ class CWallet : public CCryptoKeyStore, public CValidationInterface { +protected: + bool fBroadcastTransactions; private: bool SelectCoins(const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl *coinControl = NULL) const; @@ -760,7 +762,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface int64_t nNextResend; int64_t nLastResend; - bool fBroadcastTransactions; template using TxSpendMap = std::multimap; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index da1f07871c7..f3962a6a696 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1139,13 +1139,13 @@ void ThreadFlushWalletDB(const string& strFile) if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2) { - TRY_LOCK(bitdb.cs_db,lockDb); + TRY_LOCK(bitdb->cs_db,lockDb); if (lockDb) { // Don't do this if any databases are in use int nRefCount = 0; - map::iterator mi = bitdb.mapFileUseCount.begin(); - while (mi != bitdb.mapFileUseCount.end()) + map::iterator mi = bitdb->mapFileUseCount.begin(); + while (mi != bitdb->mapFileUseCount.end()) { nRefCount += (*mi).second; mi++; @@ -1154,18 +1154,18 @@ void ThreadFlushWalletDB(const string& strFile) if (nRefCount == 0) { boost::this_thread::interruption_point(); - map::iterator mi = bitdb.mapFileUseCount.find(strFile); - if (mi != bitdb.mapFileUseCount.end()) + map::iterator mi = bitdb->mapFileUseCount.find(strFile); + if (mi != bitdb->mapFileUseCount.end()) { LogPrint("db", "Flushing wallet.dat\n"); nLastFlushed = nWalletDBUpdated; int64_t nStart = GetTimeMillis(); // Flush wallet.dat so it's self contained - bitdb.CloseDb(strFile); - bitdb.CheckpointLSN(strFile); + bitdb->CloseDb(strFile); + bitdb->CheckpointLSN(strFile); - bitdb.mapFileUseCount.erase(mi++); + bitdb->mapFileUseCount.erase(mi++); LogPrint("db", "Flushed wallet.dat %dms\n", GetTimeMillis() - nStart); } } @@ -1181,13 +1181,13 @@ bool BackupWallet(const CWallet& wallet, const string& strDest) while (true) { { - LOCK(bitdb.cs_db); - if (!bitdb.mapFileUseCount.count(wallet.strWalletFile) || bitdb.mapFileUseCount[wallet.strWalletFile] == 0) + LOCK(bitdb->cs_db); + if (!bitdb->mapFileUseCount.count(wallet.strWalletFile) || bitdb->mapFileUseCount[wallet.strWalletFile] == 0) { // Flush log data to the dat file - bitdb.CloseDb(wallet.strWalletFile); - bitdb.CheckpointLSN(wallet.strWalletFile); - bitdb.mapFileUseCount.erase(wallet.strWalletFile); + bitdb->CloseDb(wallet.strWalletFile); + bitdb->CheckpointLSN(wallet.strWalletFile); + bitdb->mapFileUseCount.erase(wallet.strWalletFile); // Copy wallet.dat boost::filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile; diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 0a272c8a1d8..702686b21e1 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -53,7 +53,7 @@ void pre_wallet_load() UnregisterValidationInterface(pwalletMain); delete pwalletMain; pwalletMain = NULL; - bitdb.Reset(); + bitdb->Reset(); RegisterNodeSignals(GetNodeSignals()); LogPrintf("%s: done\n", __func__); } From bcc5248dd9e9c9221f0aa520c32867a64a36e44d Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 13 Jun 2022 13:00:32 -0500 Subject: [PATCH 40/47] correctly serialize komodostate records --- src/komodo.cpp | 50 ++++++++++++++++- src/komodo_structs.cpp | 6 +- src/test-komodo/test_events.cpp | 98 +++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 3 deletions(-) diff --git a/src/komodo.cpp b/src/komodo.cpp index 6c556fc478c..a18bf52650b 100644 --- a/src/komodo.cpp +++ b/src/komodo.cpp @@ -184,7 +184,55 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long size_t write_event(std::shared_ptr evt, FILE *fp) { std::stringstream ss; - ss << evt; + if (evt == nullptr) + return 0; + switch (evt->type) + { + case(komodo::komodo_event_type::EVENT_PUBKEYS): + { + komodo::event_pubkeys* tmp = dynamic_cast(evt.get()); + ss << *tmp; + break; + } + case(komodo::komodo_event_type::EVENT_NOTARIZED): + { + komodo::event_notarized* tmp = dynamic_cast(evt.get()); + ss << *tmp; + break; + } + case(komodo::komodo_event_type::EVENT_U): + { + komodo::event_u* tmp = dynamic_cast(evt.get()); + ss << *tmp; + break; + } + case(komodo::komodo_event_type::EVENT_KMDHEIGHT): + { + komodo::event_kmdheight* tmp = dynamic_cast(evt.get()); + ss << *tmp; + break; + } + case(komodo::komodo_event_type::EVENT_OPRETURN): + { + komodo::event_opreturn* tmp = dynamic_cast(evt.get()); + ss << *tmp; + break; + } + case(komodo::komodo_event_type::EVENT_PRICEFEED): + { + komodo::event_pricefeed* tmp = dynamic_cast(evt.get()); + ss << *tmp; + break; + } + case(komodo::komodo_event_type::EVENT_REWIND): + { + komodo::event_rewind* tmp = dynamic_cast(evt.get()); + ss << *tmp; + break; + } + default: + fprintf(stderr, "Invalid event type: %d\n", (int)evt->type); + } std::string buf = ss.str(); return fwrite(buf.c_str(), buf.size(), 1, fp); } diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index 0e80667a309..e00565077e3 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -174,7 +174,8 @@ std::ostream& operator<<(std::ostream& os, const event_rewind& in) event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_t height, const char* _dest, bool includeMoM) : event(EVENT_NOTARIZED, height), MoMdepth(0) { - strncpy(this->dest, _dest, sizeof(this->dest)-1); + if (_dest != nullptr) + strncpy(this->dest, _dest, sizeof(this->dest)-1); this->dest[sizeof(this->dest)-1] = 0; MoM.SetNull(); mem_read(this->notarizedheight, data, pos, data_len); @@ -190,7 +191,8 @@ event_notarized::event_notarized(uint8_t *data, long &pos, long data_len, int32_ event_notarized::event_notarized(FILE* fp, int32_t height, const char* _dest, bool includeMoM) : event(EVENT_NOTARIZED, height), MoMdepth(0) { - strncpy(this->dest, _dest, sizeof(this->dest)-1); + if (_dest != nullptr) + strncpy(this->dest, _dest, sizeof(this->dest)-1); this->dest[sizeof(this->dest)-1] = 0; MoM.SetNull(); if ( fread(¬arizedheight,1,sizeof(notarizedheight),fp) != sizeof(notarizedheight) ) diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp index f2ae8ad5c16..3e4895ba66e 100644 --- a/src/test-komodo/test_events.cpp +++ b/src/test-komodo/test_events.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -8,6 +9,7 @@ int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest); struct komodo_state *komodo_stateptrget(char *base); extern int32_t KOMODO_EXTERNAL_NOTARIES; +size_t write_event(std::shared_ptr evt, FILE *fp); namespace TestEvents { @@ -19,6 +21,17 @@ void write_p_record(std::FILE* fp) memset(&data[39], 2, 33); // 2nd key is all 2s std::fwrite(data, sizeof(data), 1, fp); } + +void write_p_record_new(std::FILE* fp) +{ + std::shared_ptr evt = std::make_shared(); + evt->height = 1; + evt->num = 2; + memset(&evt->pubkeys[0], 1, 33); + memset(&evt->pubkeys[1], 2, 33); + write_event(evt, fp); +} + void write_n_record(std::FILE* fp) { // a notarized record has @@ -147,6 +160,33 @@ bool compare_serialization(const std::string& filename, std::shared_ptr in) return retval; } +bool compare_files(const std::string& file1, const std::string& file2) +{ + std::ifstream f1(file1, std::ifstream::binary|std::ifstream::ate); + std::ifstream f2(file2, std::ifstream::binary|std::ifstream::ate); + + if (f1.fail() || f2.fail()) { + return false; //file problem + } + + if (f1.tellg() != f2.tellg()) { + return false; //size mismatch + } + + //seek back to beginning and use std::equal to compare contents + f1.seekg(0, std::ifstream::beg); + f2.seekg(0, std::ifstream::beg); + return std::equal(std::istreambuf_iterator(f1.rdbuf()), + std::istreambuf_iterator(), + std::istreambuf_iterator(f2.rdbuf())); +} + +void clear_state(const char* symbol) +{ + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + state->events.clear(); +} /**** * The main purpose of this test is to verify that * state files created continue to be readable despite logic @@ -159,6 +199,8 @@ TEST(TestEvents, komodo_faststateinit_test) strcpy(ASSETCHAINS_SYMBOL, symbol); KOMODO_EXTERNAL_NOTARIES = 1; + clear_state(symbol); + boost::filesystem::path temp = boost::filesystem::unique_path(); boost::filesystem::create_directories(temp); try @@ -549,6 +591,8 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) ASSETCHAINS_SYMBOL[0] = 0; KOMODO_EXTERNAL_NOTARIES = 0; + clear_state(symbol); + boost::filesystem::path temp = boost::filesystem::unique_path(); boost::filesystem::create_directories(temp); try @@ -761,4 +805,58 @@ TEST(TestEvents, komodo_faststateinit_test_kmd) boost::filesystem::remove_all(temp); } +TEST(test_events, write_test) +{ + char symbol[] = "TST"; + strcpy(ASSETCHAINS_SYMBOL, symbol); + KOMODO_EXTERNAL_NOTARIES = 1; + + clear_state(symbol); + + boost::filesystem::path temp = boost::filesystem::unique_path(); + boost::filesystem::create_directories(temp); + + const std::string full_filename = (temp / "kstate.tmp").string(); + const std::string full_filename2 = (temp / "kstate2.tmp").string(); + try + { + { + // old way + std::FILE* fp = std::fopen(full_filename.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_p_record(fp); + std::fclose(fp); + // verify files still exists + EXPECT_TRUE(boost::filesystem::exists(full_filename)); + // attempt to read the file + komodo_state* state = komodo_stateptrget((char*)symbol); + EXPECT_NE(state, nullptr); + char* dest = nullptr; + int32_t result = komodo_faststateinit( state, full_filename.c_str(), symbol, dest); + // compare results + EXPECT_EQ(result, 1); + // check that the new way is the same + EXPECT_EQ(state->events.size(), 1); + std::shared_ptr ev = std::dynamic_pointer_cast( state->events.front() ); + EXPECT_EQ(ev->height, 1); + EXPECT_EQ(ev->type, komodo::komodo_event_type::EVENT_PUBKEYS); + } + { + // new way + std::FILE* fp = std::fopen(full_filename2.c_str(), "wb+"); + EXPECT_NE(fp, nullptr); + write_p_record_new(fp); + std::fclose(fp); + EXPECT_TRUE(boost::filesystem::exists(full_filename2)); + // the two files should be binarily equal + EXPECT_TRUE( compare_files(full_filename, full_filename2) ); + } + } + catch(...) + { + FAIL() << "Exception thrown"; + } + boost::filesystem::remove_all(temp); +} + } // namespace TestEvents \ No newline at end of file From e22e9aabac5065367269a72dd36a9b8d7c7ed41f Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 14 Jun 2022 06:44:30 -0500 Subject: [PATCH 41/47] refactor to reduce casting --- src/komodo.cpp | 136 ++++++++++--------------------- src/komodo_events.cpp | 62 ++++++-------- src/komodo_events.h | 12 ++- src/komodo_structs.cpp | 36 ++++---- src/komodo_structs.h | 21 ++++- src/test-komodo/test_events.cpp | 140 +++++++++++++++++++------------- 6 files changed, 196 insertions(+), 211 deletions(-) diff --git a/src/komodo.cpp b/src/komodo.cpp index a18bf52650b..d396ed67790 100644 --- a/src/komodo.cpp +++ b/src/komodo.cpp @@ -57,7 +57,7 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char throw komodo::parse_error("Unable to read height from file"); if ( func == 'P' ) { - std::shared_ptr pk = std::make_shared(fp, ht); + komodo::event_pubkeys pk(fp, ht); if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) { komodo_eventadd_pubkeys(sp, symbol, ht, pk); @@ -65,23 +65,23 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char } else if ( func == 'N' || func == 'M' ) { - std::shared_ptr evt = std::make_shared(fp, ht, dest, func == 'M'); + komodo::event_notarized evt(fp, ht, dest, func == 'M'); komodo_eventadd_notarized(sp, symbol, ht, evt); } else if ( func == 'U' ) // deprecated { - std::shared_ptr evt = std::make_shared(fp, ht); + komodo::event_u evt(fp, ht); } else if ( func == 'K' || func == 'T') { - std::shared_ptr evt = std::make_shared(fp, ht, func == 'T'); + komodo::event_kmdheight evt(fp, ht, func == 'T'); komodo_eventadd_kmdheight(sp, symbol, ht, evt); } else if ( func == 'R' ) { - std::shared_ptr evt = std::make_shared(fp, ht); + komodo::event_opreturn evt(fp, ht); // check for oversized opret - if ( evt->opret.size() < 16384*4 ) + if ( evt.opret.size() < 16384*4 ) komodo_eventadd_opreturn(sp, symbol, ht, evt); } else if ( func == 'D' ) @@ -90,7 +90,7 @@ int32_t komodo_parsestatefile(struct komodo_state *sp,FILE *fp,char *symbol,char } else if ( func == 'V' ) { - std::shared_ptr evt = std::make_shared(fp, ht); + komodo::event_pricefeed evt(fp, ht); komodo_eventadd_pricefeed(sp, symbol, ht, evt); } } // retrieved the func @@ -125,7 +125,7 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long throw komodo::parse_error("Unable to parse height from file data"); if ( func == 'P' ) { - std::shared_ptr pk = std::make_shared(filedata, fpos, datalen, ht); + komodo::event_pubkeys pk(filedata, fpos, datalen, ht); if ( (KOMODO_EXTERNAL_NOTARIES && matched ) || (strcmp(symbol,"KMD") == 0 && !KOMODO_EXTERNAL_NOTARIES) ) { komodo_eventadd_pubkeys(sp, symbol, ht, pk); @@ -133,25 +133,21 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( func == 'N' || func == 'M' ) { - std::shared_ptr ntz = - std::make_shared(filedata, fpos, datalen, ht, dest, func == 'M'); + komodo::event_notarized ntz(filedata, fpos, datalen, ht, dest, func == 'M'); komodo_eventadd_notarized(sp, symbol, ht, ntz); } else if ( func == 'U' ) // deprecated { - std::shared_ptr u = - std::make_shared(filedata, fpos, datalen, ht); + komodo::event_u u(filedata, fpos, datalen, ht); } else if ( func == 'K' || func == 'T' ) { - std::shared_ptr kmd_ht = - std::make_shared(filedata, fpos, datalen, ht, func == 'T'); + komodo::event_kmdheight kmd_ht(filedata, fpos, datalen, ht, func == 'T'); komodo_eventadd_kmdheight(sp, symbol, ht, kmd_ht); } else if ( func == 'R' ) { - std::shared_ptr opret = - std::make_shared(filedata, fpos, datalen, ht); + komodo::event_opreturn opret(filedata, fpos, datalen, ht); komodo_eventadd_opreturn(sp, symbol, ht, opret); } else if ( func == 'D' ) @@ -160,8 +156,7 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long } else if ( func == 'V' ) { - std::shared_ptr pf = - std::make_shared(filedata, fpos, datalen, ht); + komodo::event_pricefeed pf(filedata, fpos, datalen, ht); komodo_eventadd_pricefeed(sp, symbol, ht, pf); } *fposp = fpos; @@ -181,58 +176,11 @@ int32_t komodo_parsestatefiledata(struct komodo_state *sp,uint8_t *filedata,long * @param fp the file * @returns the number of bytes written */ -size_t write_event(std::shared_ptr evt, FILE *fp) +template +size_t write_event(T& evt, FILE *fp) { std::stringstream ss; - if (evt == nullptr) - return 0; - switch (evt->type) - { - case(komodo::komodo_event_type::EVENT_PUBKEYS): - { - komodo::event_pubkeys* tmp = dynamic_cast(evt.get()); - ss << *tmp; - break; - } - case(komodo::komodo_event_type::EVENT_NOTARIZED): - { - komodo::event_notarized* tmp = dynamic_cast(evt.get()); - ss << *tmp; - break; - } - case(komodo::komodo_event_type::EVENT_U): - { - komodo::event_u* tmp = dynamic_cast(evt.get()); - ss << *tmp; - break; - } - case(komodo::komodo_event_type::EVENT_KMDHEIGHT): - { - komodo::event_kmdheight* tmp = dynamic_cast(evt.get()); - ss << *tmp; - break; - } - case(komodo::komodo_event_type::EVENT_OPRETURN): - { - komodo::event_opreturn* tmp = dynamic_cast(evt.get()); - ss << *tmp; - break; - } - case(komodo::komodo_event_type::EVENT_PRICEFEED): - { - komodo::event_pricefeed* tmp = dynamic_cast(evt.get()); - ss << *tmp; - break; - } - case(komodo::komodo_event_type::EVENT_REWIND): - { - komodo::event_rewind* tmp = dynamic_cast(evt.get()); - ss << *tmp; - break; - } - default: - fprintf(stderr, "Invalid event type: %d\n", (int)evt->type); - } + ss << evt; std::string buf = ss.str(); return fwrite(buf.c_str(), buf.size(), 1, fp); } @@ -286,38 +234,38 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar { if ( KMDheight != 0 ) { - std::shared_ptr kmd_ht = std::make_shared(height); - kmd_ht->kheight = KMDheight; - kmd_ht->timestamp = KMDtimestamp; + komodo::event_kmdheight kmd_ht(height); + kmd_ht.kheight = KMDheight; + kmd_ht.timestamp = KMDtimestamp; write_event(kmd_ht, fp); komodo_eventadd_kmdheight(sp,symbol,height,kmd_ht); } else if ( opretbuf != 0 && opretlen > 0 ) { - std::shared_ptr evt = std::make_shared(height); - evt->txid = txhash; - evt->vout = vout; - evt->value = opretvalue; + komodo::event_opreturn evt(height); + evt.txid = txhash; + evt.vout = vout; + evt.value = opretvalue; for(uint16_t i = 0; i < opretlen; ++i) - evt->opret.push_back(opretbuf[i]); + evt.opret.push_back(opretbuf[i]); write_event(evt, fp); komodo_eventadd_opreturn(sp,symbol,height,evt); } else if ( notarypubs != 0 && numnotaries > 0 ) { - std::shared_ptr pk = std::make_shared(height); - pk->num = numnotaries; - memcpy(pk->pubkeys, notarypubs, 33 * 64); + komodo::event_pubkeys pk(height); + pk.num = numnotaries; + memcpy(pk.pubkeys, notarypubs, 33 * 64); write_event(pk, fp); komodo_eventadd_pubkeys(sp,symbol,height,pk); } else if ( voutmask != 0 && numvouts > 0 ) { - std::shared_ptr evt = std::make_shared(height); - evt->n = numvouts; - evt->nid = notaryid; - memcpy(evt->mask, &voutmask, sizeof(voutmask)); - memcpy(evt->hash, &txhash, sizeof(txhash)); + komodo::event_u evt(height); + evt.n = numvouts; + evt.nid = notaryid; + memcpy(evt.mask, &voutmask, sizeof(voutmask)); + memcpy(evt.hash, &txhash, sizeof(txhash)); write_event(evt, fp); } else if ( pvals != 0 && numpvals > 0 ) @@ -328,10 +276,10 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar nonz++; if ( nonz >= 32 ) { - std::shared_ptr evt = std::make_shared(height); - evt->num = numpvals; - for( uint8_t i = 0; i < evt->num; ++i) - evt->prices[i] = pvals[i]; + komodo::event_pricefeed evt(height); + evt.num = numpvals; + for( uint8_t i = 0; i < evt.num; ++i) + evt.prices[i] = pvals[i]; write_event(evt, fp); komodo_eventadd_pricefeed(sp,symbol,height,evt); } @@ -340,12 +288,12 @@ void komodo_stateupdate(int32_t height,uint8_t notarypubs[][33],uint8_t numnotar { if ( sp != nullptr ) { - std::shared_ptr evt = std::make_shared(height, dest); - evt->blockhash = sp->LastNotarizedHash(); - evt->desttxid = sp->LastNotarizedDestTxId(); - evt->notarizedheight = sp->LastNotarizedHeight(); - evt->MoM = sp->LastNotarizedMoM(); - evt->MoMdepth = sp->LastNotarizedMoMDepth(); + komodo::event_notarized evt(height, dest); + evt.blockhash = sp->LastNotarizedHash(); + evt.desttxid = sp->LastNotarizedDestTxId(); + evt.notarizedheight = sp->LastNotarizedHeight(); + evt.MoM = sp->LastNotarizedMoM(); + evt.MoMdepth = sp->LastNotarizedMoMDepth(); write_event(evt, fp); komodo_eventadd_notarized(sp,symbol,height,evt); } diff --git a/src/komodo_events.cpp b/src/komodo_events.cpp index e9c4b68aff1..97175643d7a 100644 --- a/src/komodo_events.cpp +++ b/src/komodo_events.cpp @@ -26,24 +26,24 @@ * @param height * @param ntz the event */ -void komodo_eventadd_notarized( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr ntz) +void komodo_eventadd_notarized( komodo_state *sp, char *symbol, int32_t height, komodo::event_notarized& ntz) { char *coin = (ASSETCHAINS_SYMBOL[0] == 0) ? (char *)"KMD" : ASSETCHAINS_SYMBOL; if ( IS_KOMODO_NOTARY - && komodo_verifynotarization(symbol,ntz->dest,height,ntz->notarizedheight,ntz->blockhash, ntz->desttxid) < 0 ) + && komodo_verifynotarization(symbol,ntz.dest,height,ntz.notarizedheight,ntz.blockhash, ntz.desttxid) < 0 ) { static uint32_t counter; if ( counter++ < 100 ) printf("[%s] error validating notarization ht.%d notarized_height.%d, if on a pruned %s node this can be ignored\n", - ASSETCHAINS_SYMBOL,height,ntz->notarizedheight, ntz->dest); + ASSETCHAINS_SYMBOL,height,ntz.notarizedheight, ntz.dest); } else if ( strcmp(symbol,coin) == 0 ) { if ( sp != nullptr ) { sp->add_event(symbol, height, ntz); - komodo_notarized_update(sp,height, ntz->notarizedheight, ntz->blockhash, ntz->desttxid, ntz->MoM, ntz->MoMdepth); + komodo_notarized_update(sp,height, ntz.notarizedheight, ntz.blockhash, ntz.desttxid, ntz.MoM, ntz.MoMdepth); } } } @@ -55,12 +55,12 @@ void komodo_eventadd_notarized( komodo_state *sp, char *symbol, int32_t height, * @param height * @param pk the event */ -void komodo_eventadd_pubkeys(komodo_state *sp, char *symbol, int32_t height, std::shared_ptr pk) +void komodo_eventadd_pubkeys(komodo_state *sp, char *symbol, int32_t height, komodo::event_pubkeys& pk) { if (sp != nullptr) { sp->add_event(symbol, height, pk); - komodo_notarysinit(height, pk->pubkeys, pk->num); + komodo_notarysinit(height, pk.pubkeys, pk.num); } } @@ -71,12 +71,12 @@ void komodo_eventadd_pubkeys(komodo_state *sp, char *symbol, int32_t height, std * @param height * @param pf the event */ -void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr pf) +void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, komodo::event_pricefeed& pf) { if (sp != nullptr) { sp->add_event(symbol, height, pf); - komodo_pvals(height,pf->prices, pf->num); + komodo_pvals(height,pf.prices, pf.num); } } @@ -87,12 +87,12 @@ void komodo_eventadd_pricefeed( komodo_state *sp, char *symbol, int32_t height, * @param height * @param opret the event */ -void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, std::shared_ptr opret) +void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, komodo::event_opreturn& opret) { if ( sp != nullptr && ASSETCHAINS_SYMBOL[0] != 0) { sp->add_event(symbol, height, opret); - komodo_opreturn(height, opret->value, opret->opret.data(), opret->opret.size(), opret->txid, opret->vout, symbol); + komodo_opreturn(height, opret.value, opret.opret.data(), opret.opret.size(), opret.txid, opret.vout, symbol); } } @@ -102,28 +102,19 @@ void komodo_eventadd_opreturn( komodo_state *sp, char *symbol, int32_t height, s * @param sp the state object * @param ev the event to undo */ -void komodo_event_undo(komodo_state *sp, std::shared_ptr ev) +template +void komodo_event_undo(komodo_state *sp, T& ev) { - switch ( ev->type ) - { - case KOMODO_EVENT_RATIFY: - printf("rewind of ratify, needs to be coded.%d\n",ev->height); - break; - case KOMODO_EVENT_NOTARIZED: - break; - case KOMODO_EVENT_KMDHEIGHT: - if ( ev->height <= sp->SAVEDHEIGHT ) - sp->SAVEDHEIGHT = ev->height; - break; - case KOMODO_EVENT_PRICEFEED: - // backtrack prices; - break; - case KOMODO_EVENT_OPRETURN: - // backtrack opreturns - break; - } } +template<> +void komodo_event_undo(komodo_state* sp, komodo::event_kmdheight& ev) +{ + if ( ev.height <= sp->SAVEDHEIGHT ) + sp->SAVEDHEIGHT = ev.height; +} + + void komodo_event_rewind(komodo_state *sp, char *symbol, int32_t height) { @@ -138,9 +129,9 @@ void komodo_event_rewind(komodo_state *sp, char *symbol, int32_t height) while ( sp->events.size() > 0) { auto ev = sp->events.back(); - if (ev-> height < height) + if (ev->height < height) break; - komodo_event_undo(sp, ev); + komodo_event_undo(sp, *ev); sp->events.pop_back(); } } @@ -167,19 +158,20 @@ void komodo_setkmdheight(struct komodo_state *sp,int32_t kmdheight,uint32_t time * @param height * @param kmdht the event */ -void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height, std::shared_ptr kmdht) +void komodo_eventadd_kmdheight(struct komodo_state *sp,char *symbol,int32_t height, + komodo::event_kmdheight& kmdht) { if (sp != nullptr) { - if ( kmdht->kheight > 0 ) // height is advancing + if ( kmdht.kheight > 0 ) // height is advancing { sp->add_event(symbol, height, kmdht); - komodo_setkmdheight(sp, kmdht->kheight, kmdht->timestamp); + komodo_setkmdheight(sp, kmdht.kheight, kmdht.timestamp); } else // rewinding { - std::shared_ptr e = std::make_shared(height); + komodo::event_rewind e(height); sp->add_event(symbol, height, e); komodo_event_rewind(sp,symbol,height); } diff --git a/src/komodo_events.h b/src/komodo_events.h index 31cd2407dfc..3098e1b31f2 100644 --- a/src/komodo_events.h +++ b/src/komodo_events.h @@ -16,17 +16,15 @@ #include "komodo_defs.h" #include "komodo_structs.h" -void komodo_eventadd_notarized(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr ntz); +void komodo_eventadd_notarized(komodo_state *sp,char *symbol,int32_t height, komodo::event_notarized& ntz); -void komodo_eventadd_pubkeys(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pk); +void komodo_eventadd_pubkeys(komodo_state *sp,char *symbol,int32_t height, komodo::event_pubkeys& pk); -void komodo_eventadd_pricefeed(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr pf); +void komodo_eventadd_pricefeed(komodo_state *sp,char *symbol,int32_t height, komodo::event_pricefeed& pf); -void komodo_eventadd_opreturn(komodo_state *sp,char *symbol,int32_t height, std::shared_ptr opret); +void komodo_eventadd_opreturn(komodo_state *sp,char *symbol,int32_t height, komodo::event_opreturn& opret); -void komodo_eventadd_kmdheight(komodo_state *sp,char *symbol,int32_t height,std::shared_ptr kmd_ht); - -void komodo_event_undo(komodo_state *sp, std::shared_ptr ep); +void komodo_eventadd_kmdheight(komodo_state *sp,char *symbol,int32_t height, komodo::event_kmdheight& kmd_ht); void komodo_event_rewind(komodo_state *sp,char *symbol,int32_t height); diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index e00565077e3..860027b1f38 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -14,24 +14,6 @@ ******************************************************************************/ #include "komodo_structs.h" #include "mem_read.h" -#include - -extern std::mutex komodo_mutex; - -/*** - * komodo_state - */ - -bool komodo_state::add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in) -{ - if (ASSETCHAINS_SYMBOL[0] != 0) - { - std::lock_guard lock(komodo_mutex); - events.push_back( in ); - return true; - } - return false; -} namespace komodo { @@ -150,6 +132,24 @@ event_pubkeys::event_pubkeys(FILE* fp, int32_t height) : event(EVENT_PUBKEYS, he throw parse_error("Illegal number of keys: " + std::to_string(num)); } +/* +event_pubkeys::event_pubkeys(const event_pubkeys& orig) : event(EVENT_PUBKEYS, orig.height) +{ + this->num = orig.num; + memcpy(this->pubkeys, orig.pubkeys, sizeof(uint8_t) * 64 * 33); +} + +event_pubkeys& event_pubkeys::operator=(const event_pubkeys& orig) +{ + if (this == &orig) + return *this; + + this->num = orig.num; + memcpy(this->pubkeys, orig.pubkeys, sizeof(uint8_t) * 64 * 33); + return *this; +} +*/ + std::ostream& operator<<(std::ostream& os, const event_pubkeys& in) { const event& e = dynamic_cast(in); diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 6f4f0135186..252bf1f55c4 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -45,6 +45,9 @@ #define KOMODO_ASSETCHAIN_MAXLEN 65 #include "bits256.h" +#include + +extern std::mutex komodo_mutex; // structs prior to refactor struct komodo_kv { UT_hash_handle hh; bits256 pubkey; uint8_t *key,*value; int32_t height; uint32_t flags; uint16_t keylen,valuesize; }; @@ -117,6 +120,8 @@ struct event_notarized : public event } event_notarized(uint8_t* data, long &pos, long data_len, int32_t height, const char* _dest, bool includeMoM = false); event_notarized(FILE* fp, int32_t ht, const char* _dest, bool includeMoM = false); + //event_notarized(const event_notarized& orig); + //event_notarized& operator=(const event_notarized& orig); uint256 blockhash; uint256 desttxid; uint256 MoM; @@ -147,6 +152,8 @@ struct event_pubkeys : public event */ event_pubkeys(uint8_t* data, long &pos, long data_len, int32_t height); event_pubkeys(FILE* fp, int32_t height); + //event_pubkeys(const event_pubkeys& orig); + //event_pubkeys& operator=(const event_pubkeys& orig); uint8_t num = 0; uint8_t pubkeys[64][33]; }; @@ -291,7 +298,19 @@ class komodo_state uint64_t shorted; std::list> events; uint32_t RTbufs[64][3]; uint64_t RTmask; - bool add_event(const std::string& symbol, const uint32_t height, std::shared_ptr in); + template + bool add_event(const std::string& symbol, const uint32_t height, T& in) + { + if (ASSETCHAINS_SYMBOL[0] != 0) + { + std::shared_ptr ptr = std::make_shared( in ); + std::lock_guard lock(komodo_mutex); + events.push_back( ptr ); + return true; + } + return false; + } + protected: /*** * @brief clear the checkpoints collection diff --git a/src/test-komodo/test_events.cpp b/src/test-komodo/test_events.cpp index 3e4895ba66e..e281c4ce6c6 100644 --- a/src/test-komodo/test_events.cpp +++ b/src/test-komodo/test_events.cpp @@ -9,9 +9,10 @@ int32_t komodo_faststateinit(struct komodo_state *sp,const char *fname,char *symbol,char *dest); struct komodo_state *komodo_stateptrget(char *base); extern int32_t KOMODO_EXTERNAL_NOTARIES; -size_t write_event(std::shared_ptr evt, FILE *fp); +template +size_t write_event(T& evt, FILE *fp); -namespace TestEvents { +namespace test_events { void write_p_record(std::FILE* fp) { @@ -24,11 +25,11 @@ void write_p_record(std::FILE* fp) void write_p_record_new(std::FILE* fp) { - std::shared_ptr evt = std::make_shared(); - evt->height = 1; - evt->num = 2; - memset(&evt->pubkeys[0], 1, 33); - memset(&evt->pubkeys[1], 2, 33); + komodo::event_pubkeys evt; + evt.height = 1; + evt.num = 2; + memset(&evt.pubkeys[0], 1, 33); + memset(&evt.pubkeys[1], 2, 33); write_event(evt, fp); } @@ -127,14 +128,14 @@ void write_b_record(std::FILE* fp) std::fwrite(data, sizeof(data), 1, fp); } template -bool compare_serialization(const std::string& filename, std::shared_ptr in) +bool compare_serialization(const std::string& filename, const T& in) { // read contents of file std::ifstream s(filename, std::ios::binary); std::vector file_contents((std::istreambuf_iterator(s)), std::istreambuf_iterator()); // get contents of in std::stringstream ss; - ss << *(in.get()); + ss << in; std::vector in_contents( (std::istreambuf_iterator(ss)), std::istreambuf_iterator()); bool retval = file_contents == in_contents; if (!retval) @@ -193,7 +194,7 @@ void clear_state(const char* symbol) * changes. Files need to be readable. The record format should * not change without hardfork protection */ -TEST(TestEvents, komodo_faststateinit_test) +TEST(test_events, komodo_faststateinit_test) { char symbol[] = "TST"; strcpy(ASSETCHAINS_SYMBOL, symbol); @@ -235,9 +236,10 @@ TEST(TestEvents, komodo_faststateinit_test) */ // check that the new way is the same EXPECT_EQ(state->events.size(), 1); - std::shared_ptr ev2 = std::dynamic_pointer_cast(state->events.front()); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PUBKEYS); + komodo::event_pubkeys& ev2 = + static_cast( *state->events.front() ); + EXPECT_EQ(ev2.height, 1); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_PUBKEYS); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -266,9 +268,10 @@ TEST(TestEvents, komodo_faststateinit_test) */ // check that the new way is the same EXPECT_EQ(state->events.size(), 2); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(++state->events.begin()) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + komodo::event_notarized& ev2 = + static_cast( *(*(++state->events.begin())) ); + EXPECT_EQ(ev2.height, 1); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_NOTARIZED); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -299,9 +302,9 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(state->events.size(), 3); auto itr = state->events.begin(); std::advance(itr, 2); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_NOTARIZED); + komodo::event_notarized& ev2 = static_cast( *(*(itr)) ); + EXPECT_EQ(ev2.height, 1); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_NOTARIZED); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -330,12 +333,12 @@ TEST(TestEvents, komodo_faststateinit_test) auto itr = state->events.begin(); // this does not get added to state, so we need to serialize the object just // to verify serialization works as expected - std::shared_ptr ev2 = std::make_shared(); - ev2->height = 1; - ev2->n = 'N'; - ev2->nid = 'I'; - memset(ev2->mask, 1, 8); - memset(ev2->hash, 2, 32); + komodo::event_u ev2; + ev2.height = 1; + ev2.n = 'N'; + ev2.nid = 'I'; + memset(ev2.mask, 1, 8); + memset(ev2.hash, 2, 32); EXPECT_TRUE(compare_serialization(full_filename, ev2)); } // record type K (KMD height) @@ -365,9 +368,9 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(state->events.size(), 4); auto itr = state->events.begin(); std::advance(itr, 3); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + komodo::event_kmdheight& ev2 = static_cast( *(*(itr)) ); + EXPECT_EQ(ev2.height, 1); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_KMDHEIGHT); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -398,9 +401,9 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(state->events.size(), 5); auto itr = state->events.begin(); std::advance(itr, 4); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + komodo::event_kmdheight& ev2 = static_cast( *(*(itr)) ); + EXPECT_EQ(ev2.height, 1); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_KMDHEIGHT); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -431,9 +434,9 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(state->events.size(), 6); auto itr = state->events.begin(); std::advance(itr, 5); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_OPRETURN); + komodo::event_opreturn& ev2 = static_cast( *(*(itr)) ); + EXPECT_EQ(ev2.height, 1); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_OPRETURN); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -464,9 +467,9 @@ TEST(TestEvents, komodo_faststateinit_test) EXPECT_EQ(state->events.size(), 7); auto itr = state->events.begin(); std::advance(itr, 6); - std::shared_ptr ev2 = std::dynamic_pointer_cast( *(itr) ); - EXPECT_EQ(ev2->height, 1); - EXPECT_EQ(ev2->type, komodo::komodo_event_type::EVENT_PRICEFEED); + komodo::event_pricefeed& ev2 = static_cast( *(*(itr)) ); + EXPECT_EQ(ev2.height, 1); + EXPECT_EQ(ev2.type, komodo::komodo_event_type::EVENT_PRICEFEED); // the serialized version should match the input EXPECT_TRUE(compare_serialization(full_filename, ev2)); } @@ -540,38 +543,38 @@ TEST(TestEvents, komodo_faststateinit_test) auto itr = state->events.begin(); std::advance(itr, 7); { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PUBKEYS); + EXPECT_EQ( (**itr).height, 1); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_PUBKEYS); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + EXPECT_EQ( (**itr).height, 1); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_NOTARIZED); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_NOTARIZED); + EXPECT_EQ( (**itr).height, 1); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_NOTARIZED); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + EXPECT_EQ( (**itr).height, 1); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_KMDHEIGHT); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_KMDHEIGHT); + EXPECT_EQ( (**itr).height, 1); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_KMDHEIGHT); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_OPRETURN); + EXPECT_EQ( (**itr).height, 1); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_OPRETURN); itr++; } { - EXPECT_EQ( (*itr)->height, 1); - EXPECT_EQ( (*itr)->type, komodo::komodo_event_type::EVENT_PRICEFEED); + EXPECT_EQ( (**itr).height, 1); + EXPECT_EQ( (**itr).type, komodo::komodo_event_type::EVENT_PRICEFEED); itr++; } } @@ -583,7 +586,7 @@ TEST(TestEvents, komodo_faststateinit_test) boost::filesystem::remove_all(temp); } -TEST(TestEvents, komodo_faststateinit_test_kmd) +TEST(test_events, komodo_faststateinit_test_kmd) { // Nothing should be added to events if this is the komodo chain @@ -837,9 +840,9 @@ TEST(test_events, write_test) EXPECT_EQ(result, 1); // check that the new way is the same EXPECT_EQ(state->events.size(), 1); - std::shared_ptr ev = std::dynamic_pointer_cast( state->events.front() ); - EXPECT_EQ(ev->height, 1); - EXPECT_EQ(ev->type, komodo::komodo_event_type::EVENT_PUBKEYS); + komodo::event_pubkeys& ev = static_cast( *state->events.front() ); + EXPECT_EQ(ev.height, 1); + EXPECT_EQ(ev.type, komodo::komodo_event_type::EVENT_PUBKEYS); } { // new way @@ -859,4 +862,29 @@ TEST(test_events, write_test) boost::filesystem::remove_all(temp); } -} // namespace TestEvents \ No newline at end of file +TEST(test_events, event_copy) +{ + // make an object + komodo::event_pubkeys pk1(1); + pk1.num = 2; + memset(pk1.pubkeys[0], 1, 33); + memset(pk1.pubkeys[1], 2, 33); + // make a copy + std::vector> events; + events.push_back( std::make_shared(pk1) ); + komodo::event_pubkeys& pk2 = static_cast(*events.front()); + // are they equal? + EXPECT_EQ(pk1.height, pk2.height); + EXPECT_EQ(pk1.num, pk2.num); + for(uint8_t i = 0; i < pk1.num; ++i) + { + for(uint8_t j = 0; j < 33; ++j) + { + if (pk1.pubkeys[i][j] != pk2.pubkeys[i][j]) + FAIL() << "Error at " << (int)i << " " << (int)j; + } + } + +} + +} // namespace test_events \ No newline at end of file From 876e824b7ca2e4fe8ba87b0423d898f692ce4b5f Mon Sep 17 00:00:00 2001 From: John Jones Date: Tue, 14 Jun 2022 07:42:05 -0500 Subject: [PATCH 42/47] remove dynamic cast from events --- src/komodo_structs.cpp | 45 +++++++++++++----------------------------- src/komodo_structs.h | 4 ---- 2 files changed, 14 insertions(+), 35 deletions(-) diff --git a/src/komodo_structs.cpp b/src/komodo_structs.cpp index 860027b1f38..3a68639f8ad 100644 --- a/src/komodo_structs.cpp +++ b/src/komodo_structs.cpp @@ -78,8 +78,8 @@ std::ostream& operator<<(std::ostream& os, const event& in) break; case(EVENT_NOTARIZED): { - event_notarized* tmp = dynamic_cast(const_cast(&in)); - if (tmp->MoMdepth == 0) + const event_notarized& tmp = static_cast(in); + if (tmp.MoMdepth == 0) os << "N"; else os << "M"; @@ -90,8 +90,8 @@ std::ostream& operator<<(std::ostream& os, const event& in) break; case(EVENT_KMDHEIGHT): { - event_kmdheight* tmp = dynamic_cast(const_cast(&in)); - if (tmp->timestamp == 0) + const event_kmdheight& tmp = static_cast(in); + if (tmp.timestamp == 0) os << "K"; else os << "T"; @@ -132,31 +132,14 @@ event_pubkeys::event_pubkeys(FILE* fp, int32_t height) : event(EVENT_PUBKEYS, he throw parse_error("Illegal number of keys: " + std::to_string(num)); } -/* -event_pubkeys::event_pubkeys(const event_pubkeys& orig) : event(EVENT_PUBKEYS, orig.height) -{ - this->num = orig.num; - memcpy(this->pubkeys, orig.pubkeys, sizeof(uint8_t) * 64 * 33); -} - -event_pubkeys& event_pubkeys::operator=(const event_pubkeys& orig) -{ - if (this == &orig) - return *this; - - this->num = orig.num; - memcpy(this->pubkeys, orig.pubkeys, sizeof(uint8_t) * 64 * 33); - return *this; -} -*/ - std::ostream& operator<<(std::ostream& os, const event_pubkeys& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e; os << in.num; - for(uint8_t i = 0; i < in.num-1; ++i) - os << in.pubkeys[i]; + for(uint8_t i = 0; i < in.num; ++i) + for(uint8_t j = 0; j < 33; ++j) + os << in.pubkeys[i][j]; return os; } @@ -166,7 +149,7 @@ event_rewind::event_rewind(uint8_t *data, long &pos, long data_len, int32_t heig } std::ostream& operator<<(std::ostream& os, const event_rewind& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e; return os; } @@ -212,7 +195,7 @@ event_notarized::event_notarized(FILE* fp, int32_t height, const char* _dest, bo std::ostream& operator<<(std::ostream& os, const event_notarized& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e; os << serializable(in.notarizedheight); os << serializable(in.blockhash); @@ -247,7 +230,7 @@ event_u::event_u(FILE *fp, int32_t height) : event(EVENT_U, height) std::ostream& operator<<(std::ostream& os, const event_u& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e; os << in.n << in.nid; os.write((const char*)in.mask, 8); @@ -275,7 +258,7 @@ event_kmdheight::event_kmdheight(FILE *fp, int32_t height, bool includeTimestamp std::ostream& operator<<(std::ostream& os, const event_kmdheight& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e << serializable(in.kheight); if (in.timestamp > 0) os << serializable(in.timestamp); @@ -314,7 +297,7 @@ event_opreturn::event_opreturn(FILE* fp, int32_t height) : event(EVENT_OPRETURN, std::ostream& operator<<(std::ostream& os, const event_opreturn& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e << serializable(in.txid) << serializable(in.vout) @@ -344,7 +327,7 @@ event_pricefeed::event_pricefeed(FILE* fp, int32_t height) : event(EVENT_PRICEFE std::ostream& operator<<(std::ostream& os, const event_pricefeed& in) { - const event& e = dynamic_cast(in); + const event& e = static_cast(in); os << e << (uint8_t)in.num; os.write((const char*)in.prices, in.num * sizeof(uint32_t)); return os; diff --git a/src/komodo_structs.h b/src/komodo_structs.h index 252bf1f55c4..40c3bc15006 100644 --- a/src/komodo_structs.h +++ b/src/komodo_structs.h @@ -120,8 +120,6 @@ struct event_notarized : public event } event_notarized(uint8_t* data, long &pos, long data_len, int32_t height, const char* _dest, bool includeMoM = false); event_notarized(FILE* fp, int32_t ht, const char* _dest, bool includeMoM = false); - //event_notarized(const event_notarized& orig); - //event_notarized& operator=(const event_notarized& orig); uint256 blockhash; uint256 desttxid; uint256 MoM; @@ -152,8 +150,6 @@ struct event_pubkeys : public event */ event_pubkeys(uint8_t* data, long &pos, long data_len, int32_t height); event_pubkeys(FILE* fp, int32_t height); - //event_pubkeys(const event_pubkeys& orig); - //event_pubkeys& operator=(const event_pubkeys& orig); uint8_t num = 0; uint8_t pubkeys[64][33]; }; From 0d8e72d16ef3c8599c2cda6916221d4efc67ca99 Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 15 Jun 2022 08:35:38 -0500 Subject: [PATCH 43/47] komodo_disconnect no longer used --- src/komodo_bitcoind.cpp | 12 ------------ src/komodo_bitcoind.h | 2 -- src/main.cpp | 1 - 3 files changed, 15 deletions(-) diff --git a/src/komodo_bitcoind.cpp b/src/komodo_bitcoind.cpp index 378cfa3f746..e0b86defa8b 100644 --- a/src/komodo_bitcoind.cpp +++ b/src/komodo_bitcoind.cpp @@ -705,18 +705,6 @@ int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout) return(0); } -void komodo_disconnect(CBlockIndex *pindex,CBlock& block) -{ - char symbol[KOMODO_ASSETCHAIN_MAXLEN],dest[KOMODO_ASSETCHAIN_MAXLEN]; struct komodo_state *sp; - //fprintf(stderr,"disconnect ht.%d\n",pindex->nHeight); - komodo_init(pindex->nHeight); - if ( (sp= komodo_stateptr(symbol,dest)) != 0 ) - { - //sp->rewinding = pindex->nHeight; - //fprintf(stderr,"-%d ",pindex->nHeight); - } else printf("komodo_disconnect: ht.%d cant get komodo_state.(%s)\n",pindex->nHeight,ASSETCHAINS_SYMBOL); -} - int32_t komodo_is_notarytx(const CTransaction& tx) { uint8_t *ptr; static uint8_t crypto777[33]; diff --git a/src/komodo_bitcoind.h b/src/komodo_bitcoind.h index 29174c2b92c..8928a52eb33 100644 --- a/src/komodo_bitcoind.h +++ b/src/komodo_bitcoind.h @@ -129,8 +129,6 @@ uint256 komodo_calcmerkleroot(CBlock *pblock, uint256 prevBlockHash, int32_t nHe int32_t komodo_isPoS(CBlock *pblock, int32_t height,CTxDestination *addressout); -void komodo_disconnect(CBlockIndex *pindex,CBlock& block); - int32_t komodo_is_notarytx(const CTransaction& tx); int32_t komodo_block2height(CBlock *block); diff --git a/src/main.cpp b/src/main.cpp index ab49416445d..76a804ba761 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3149,7 +3149,6 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex *pfClean = false; bool fClean = true; - //komodo_disconnect(pindex,block); does nothing? CBlockUndo blockUndo; CDiskBlockPos pos = pindex->GetUndoPos(); if (pos.IsNull()) From 8db798bf3355f791134f7e32e52f00950bb7ee40 Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 15 Jun 2022 09:10:50 -0500 Subject: [PATCH 44/47] Set max witness cache in wallet --- src/komodo_globals.h | 1 - src/komodo_utils.cpp | 1 - src/komodo_utils.h | 2 -- src/wallet/gtest/test_wallet.cpp | 2 +- src/wallet/wallet.cpp | 20 ++++++++++---------- src/wallet/wallet.h | 15 ++++++--------- 6 files changed, 17 insertions(+), 24 deletions(-) diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 92f59672e63..48bdc5be594 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -43,7 +43,6 @@ struct knotaries_entry *Pubkeys; struct komodo_state KOMODO_STATES[34]; -unsigned int WITNESS_CACHE_SIZE = 100+10; // coinbase maturity plus 10 uint256 KOMODO_EARLYTXID; bool IS_KOMODO_NOTARY; diff --git a/src/komodo_utils.cpp b/src/komodo_utils.cpp index 89bc93a34f8..54c74ea827d 100644 --- a/src/komodo_utils.cpp +++ b/src/komodo_utils.cpp @@ -1308,7 +1308,6 @@ void komodo_args(char *argv0) } KOMODO_STOPAT = GetArg("-stopat",0); MAX_REORG_LENGTH = GetArg("-maxreorg",MAX_REORG_LENGTH); - WITNESS_CACHE_SIZE = MAX_REORG_LENGTH+10; ASSETCHAINS_CC = GetArg("-ac_cc",0); KOMODO_CCACTIVATE = GetArg("-ac_ccactivate",0); ASSETCHAINS_BLOCKTIME = GetArg("-ac_blocktime",60); diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 6ebae40852e..1ffce5a7f5c 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -378,8 +378,6 @@ uint64_t komodo_ac_block_subsidy(int nHeight); int8_t equihash_params_possible(uint64_t n, uint64_t k); -void komodo_args(char *argv0); - void komodo_nameset(char *symbol,char *dest,char *source); struct komodo_state *komodo_stateptrget(char *base); diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index 20c39da2b15..98c1e09c04c 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -1477,7 +1477,7 @@ TEST(WalletTests, CachedWitnessesCleanIndex) { wallet.AddSproutSpendingKey(sk); // Generate a chain - size_t numBlocks = WITNESS_CACHE_SIZE + 10; + size_t numBlocks = MAX_REORG_LENGTH + 10; blocks.resize(numBlocks); indices.resize(numBlocks); for (size_t i = 0; i < numBlocks; i++) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 07654acbbdc..949fba49229 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -977,7 +977,7 @@ void CWallet::ClearNoteWitnessCache() } template -void CopyPreviousWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize) +void CopyPreviousWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, int64_t maxWitnessCacheSize) { for (auto& item : noteDataMap) { auto* nd = &(item.second); @@ -996,7 +996,7 @@ void CopyPreviousWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nW if (nd->witnesses.size() > 0) { nd->witnesses.push_front(nd->witnesses.front()); } - if (nd->witnesses.size() > WITNESS_CACHE_SIZE) { + if (nd->witnesses.size() > maxWitnessCacheSize) { nd->witnesses.pop_back(); } } @@ -1069,11 +1069,11 @@ void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, { LOCK(cs_wallet); for (std::pair& wtxItem : mapWallet) { - ::CopyPreviousWitnesses(wtxItem.second.mapSproutNoteData, pindex->nHeight, nWitnessCacheSize); - ::CopyPreviousWitnesses(wtxItem.second.mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize); + ::CopyPreviousWitnesses(wtxItem.second.mapSproutNoteData, pindex->nHeight, nWitnessCacheSize, maxWitnessCacheSize); + ::CopyPreviousWitnesses(wtxItem.second.mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize, maxWitnessCacheSize); } - if (nWitnessCacheSize < WITNESS_CACHE_SIZE) { + if (nWitnessCacheSize < maxWitnessCacheSize) { nWitnessCacheSize += 1; } @@ -1136,7 +1136,7 @@ void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, } template -bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize) +bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, int64_t maxWitnessCacheSize) { extern int32_t KOMODO_REWIND; @@ -1179,7 +1179,7 @@ bool DecrementNoteWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t n assert((nWitnessCacheSize - 1) >= nd->witnesses.size()); } } - assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0 || WITNESS_CACHE_SIZE != Params().CoinbaseMaturity()+10); + assert(KOMODO_REWIND != 0 || nWitnessCacheSize > 0 || maxWitnessCacheSize != Params().CoinbaseMaturity()+10); return true; } @@ -1188,12 +1188,12 @@ void CWallet::DecrementNoteWitnesses(const CBlockIndex* pindex) { LOCK(cs_wallet); for (std::pair& wtxItem : mapWallet) { - if (!::DecrementNoteWitnesses(wtxItem.second.mapSproutNoteData, pindex->nHeight, nWitnessCacheSize)) + if (!::DecrementNoteWitnesses(wtxItem.second.mapSproutNoteData, pindex->nHeight, nWitnessCacheSize, maxWitnessCacheSize)) needsRescan = true; - if (!::DecrementNoteWitnesses(wtxItem.second.mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize)) + if (!::DecrementNoteWitnesses(wtxItem.second.mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize, maxWitnessCacheSize)) needsRescan = true; } - if ( WITNESS_CACHE_SIZE == Params().CoinbaseMaturity()+10 ) + if ( maxWitnessCacheSize == Params().CoinbaseMaturity()+10 ) { nWitnessCacheSize -= 1; // TODO: If nWitnessCache is zero, we need to regenerate the caches (#1302) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 49e935ba06f..fa9dfac8c10 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -73,11 +73,6 @@ static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2; static const CAmount nHighTransactionMaxFeeWarning = 100 * nHighTransactionFeeWarning; //! Largest (in bytes) free transaction we're willing to create static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000; -//! Size of witness cache -// Should be large enough that we can expect not to reorg beyond our cache -// unless there is some exceptional network disruption. -extern unsigned int WITNESS_CACHE_SIZE; - //! Size of HD seed in bytes static const size_t HD_WALLET_SEED_LENGTH = 32; @@ -749,6 +744,10 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface { protected: bool fBroadcastTransactions; + //! Size of witness cache + // Should be large enough that we can expect not to reorg beyond our cache + // unless there is some exceptional network disruption. + int64_t maxWitnessCacheSize; private: bool SelectCoins(const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl *coinControl = NULL) const; @@ -888,15 +887,13 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface MasterKeyMap mapMasterKeys; unsigned int nMasterKeyMaxID; - CWallet() + CWallet(int64_t witnessCacheSize = MAX_REORG_LENGTH + 10) : maxWitnessCacheSize(witnessCacheSize) { SetNull(); } - CWallet(const std::string& strWalletFileIn) + CWallet(const std::string& strWalletFileIn, int64_t witnessCacheSize = MAX_REORG_LENGTH + 10) : CWallet(witnessCacheSize) { - SetNull(); - strWalletFile = strWalletFileIn; fFileBacked = true; } From 9ded975f662c2e4588bf65e93aac7cf5a759bb56 Mon Sep 17 00:00:00 2001 From: John Jones Date: Wed, 15 Jun 2022 16:09:30 -0500 Subject: [PATCH 45/47] fix miner fee in test --- src/test-komodo/test_block.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/test-komodo/test_block.cpp b/src/test-komodo/test_block.cpp index 76dd5179c83..9b68705ad06 100644 --- a/src/test-komodo/test_block.cpp +++ b/src/test-komodo/test_block.cpp @@ -78,13 +78,16 @@ TEST(test_block, TestSpendInSameBlock) auto alice = std::make_shared("alice"); alice->SetBroadcastTransactions(true); auto bob = std::make_shared("bob"); + auto miner = std::make_shared("miner"); std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block ASSERT_GT( chain.GetIndex()->nHeight, 0 ); + CAmount notaryBalance = notary->GetBalance(); // delay just a second to help with locktime std::this_thread::sleep_for(std::chrono::seconds(1)); // Start to build a block int32_t newHeight = chain.GetIndex()->nHeight + 1; - TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000, 0, true); + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000, 5000, true); + notaryBalance -= 105000; // transfer + fee // now have Alice move some funds to Bob in the same block CCoinControl useThisTransaction; COutPoint tx(fundAlice.transaction.GetHash(), 1); @@ -93,11 +96,11 @@ TEST(test_block, TestSpendInSameBlock) EXPECT_TRUE( alice->CommitTransaction(aliceToBob.transaction, aliceToBob.reserveKey) ); std::this_thread::sleep_for(std::chrono::seconds(1)); // see if everything worked - lastBlock = chain.generateBlock(notary); + lastBlock = chain.generateBlock(miner); EXPECT_TRUE( lastBlock != nullptr); // balances should be correct EXPECT_EQ( bob->GetBalance() + bob->GetUnconfirmedBalance() + bob->GetImmatureBalance(), CAmount(50000)); - EXPECT_EQ( notary->GetBalance(), CAmount(10000000299905000)); + EXPECT_EQ( notary->GetBalance(), notaryBalance); EXPECT_EQ( alice->GetBalance() + alice->GetUnconfirmedBalance() + alice->GetImmatureBalance(), CAmount(45000)); } @@ -111,10 +114,11 @@ TEST(test_block, TestDoubleSpendInSameBlock) auto bob = std::make_shared("bob"); auto charlie = std::make_shared("charlie"); std::shared_ptr lastBlock = chain.generateBlock(notary); // genesis block + CAmount notaryBalance = notary->GetBalance(); ASSERT_GT( chain.GetIndex()->nHeight, 0 ); // Start to build a block int32_t newHeight = chain.GetIndex()->nHeight + 1; - TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000, 0, true); + TransactionInProcess fundAlice = notary->CreateSpendTransaction(alice, 100000, 5000, true); EXPECT_EQ(mempool.size(), 1); // now have Alice move some funds to Bob in the same block { From fe25d9a0f26c41a2b2d6add3288a8b42cbe85c4d Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 27 Jun 2022 10:17:41 -0500 Subject: [PATCH 46/47] Get correct config file --- src/chainparamsbase.h | 4 + src/komodo_globals.h | 4 +- src/komodo_utils.cpp | 110 ++++++++++++-------- src/komodo_utils.h | 7 ++ src/test-komodo/test_parse_notarisation.cpp | 56 ++++++++++ src/util.cpp | 18 +++- src/util.h | 14 +++ 7 files changed, 162 insertions(+), 51 deletions(-) diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 94e3a42380d..dae6ff19d17 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -38,6 +38,10 @@ class CBaseChainParams MAX_NETWORK_TYPES }; + /*** + * @brief returns the subdirectory for the network + * @return the data subdirectory ( nothing, or "testnet3" or "regtest" ) + */ const std::string& DataDir() const { return strDataDir; } int RPCPort() const { return nRPCPort; } diff --git a/src/komodo_globals.h b/src/komodo_globals.h index 64c1deff133..432f4e7ede3 100644 --- a/src/komodo_globals.h +++ b/src/komodo_globals.h @@ -102,7 +102,9 @@ int32_t ASSETCHAINS_STAKED; uint64_t ASSETCHAINS_COMMISSION,ASSETCHAINS_SUPPLY = 10,ASSETCHAINS_FOUNDERS_REWARD; uint32_t KOMODO_INITDONE; -char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771, DEST_PORT; +char KMDUSERPASS[8192+512+1],BTCUSERPASS[8192]; +uint16_t KMD_PORT = 7771,BITCOIND_RPCPORT = 7771; +uint16_t DEST_PORT = 0; // port to communicate with LTC for notarization verification uint64_t PENDING_KOMODO_TX; extern int32_t KOMODO_LOADINGBLOCKS; // defined in pow.cpp, boolean, 1 if currently loading the block index, 0 if not unsigned int MAX_BLOCK_SIGOPS = 20000; diff --git a/src/komodo_utils.cpp b/src/komodo_utils.cpp index 54c74ea827d..6b5aaef7b15 100644 --- a/src/komodo_utils.cpp +++ b/src/komodo_utils.cpp @@ -867,37 +867,51 @@ void iguana_initQ(queue_t *Q,char *name) free(item); } +/** + * @brief Get the username, password, and port from a file + * @param[out] username the username found in the config file + * @param[out] password the password found in the config file + * @param[in] fp the file to be read + * @return the RPC port + */ uint16_t _komodo_userpass(char *username,char *password,FILE *fp) { - char *rpcuser,*rpcpassword,*str,line[8192]; uint16_t port = 0; - rpcuser = rpcpassword = 0; - username[0] = password[0] = 0; + uint16_t port = 0; + char *rpcuser = nullptr; + char *rpcpassword = nullptr; + char line[8192]; + + username[0] = 0; + password[0] = 0; + while ( fgets(line,sizeof(line),fp) != 0 ) { + char *str = nullptr; if ( line[0] == '#' ) continue; - //printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword")); - if ( (str= strstr(line,(char *)"rpcuser")) != 0 ) + if ( (str= strstr(line,(char *)"rpcuser")) != nullptr ) + { rpcuser = parse_conf_line(str,(char *)"rpcuser"); - else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 ) + } + else if ( (str= strstr(line,(char *)"rpcpassword")) != nullptr ) + { rpcpassword = parse_conf_line(str,(char *)"rpcpassword"); - else if ( (str= strstr(line,(char *)"rpcport")) != 0 ) + } + else if ( (str= strstr(line,(char *)"rpcport")) != nullptr ) { port = atoi(parse_conf_line(str,(char *)"rpcport")); - //fprintf(stderr,"rpcport.%u in file\n",port); } } - if ( rpcuser != 0 && rpcpassword != 0 ) + if ( rpcuser != nullptr && rpcpassword != nullptr ) { strcpy(username,rpcuser); strcpy(password,rpcpassword); } - //printf("rpcuser.(%s) rpcpassword.(%s) KMDUSERPASS.(%s) %u\n",rpcuser,rpcpassword,KMDUSERPASS,port); - if ( rpcuser != 0 ) + if ( rpcuser != nullptr ) free(rpcuser); - if ( rpcpassword != 0 ) + if ( rpcpassword != nullptr ) free(rpcpassword); - return(port); + return port; } void komodo_statefname(char *fname,char *symbol,char *str) @@ -1239,10 +1253,35 @@ int8_t equihash_params_possible(uint64_t n, uint64_t k) return(-1); } +/*** + * @brief get username, password, and port from a config file + * @param[in] path the path to the data directory + * @param[in] filename the filename of the config file (without directory) + * @param[out] userpass the username and password from the config file (colon separated) + * @param[out] port the RPC port found in the config file + */ +void get_userpass_and_port(const boost::filesystem::path& path, const std::string& filename, + std::string userpass, uint16_t& port) +{ + boost::filesystem::path datadir_path = path; + datadir_path /= filename; + FILE* fp = fopen(datadir_path.c_str(), "rb"); + if ( fp != nullptr ) + { + char username[512]; + char password[4096]; + port = _komodo_userpass(username,password,fp); + userpass = std::string(username) + ":" + std::string(password); + fclose(fp); + } + else + printf("couldnt open.(%s) will not validate dest notarizations\n", datadir_path.c_str()); +} + void komodo_args(char *argv0) { std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[32756],disablebits[32],*extraptr=0; - FILE *fp; uint64_t val; uint16_t port, dest_rpc_port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256], ccEnablesHeight[512] = {0}; CTransaction earlytx; uint256 hashBlock; + FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256], ccEnablesHeight[512] = {0}; CTransaction earlytx; uint256 hashBlock; std::string ntz_dest_path; ntz_dest_path = GetArg("-notary", ""); @@ -1851,41 +1890,20 @@ void komodo_args(char *argv0) } else { - char fname[512],username[512],password[4096]; int32_t iter; FILE *fp; - ASSETCHAINS_P2PPORT = 7770; - ASSETCHAINS_RPCPORT = 7771; - for (iter=0; iter<2; iter++) - { - strcpy(fname,GetDataDir().string().c_str()); -#ifdef _WIN32 - while ( fname[strlen(fname)-1] != '\\' ) - fname[strlen(fname)-1] = 0; - if ( iter == 0 ) - strcat(fname,"Komodo\\komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); -#else - while ( fname[strlen(fname)-1] != '/' ) - fname[strlen(fname)-1] = 0; + // -ac_name not passed, we are on the KMD chain + ASSETCHAINS_P2PPORT = 7770; // default port for P2P + ASSETCHAINS_RPCPORT = 7771; // default port for RPC #ifdef __APPLE__ - if ( iter == 0 ) - strcat(fname,"Komodo/Komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); + std::string filename = "Komodo.conf"; #else - if ( iter == 0 ) - strcat(fname,".komodo/komodo.conf"); - else strcat(fname,ntz_dest_path.c_str()); + std::string filename = "komodo.conf"; #endif -#endif - if ( (fp= fopen(fname,"rb")) != 0 ) - { - dest_rpc_port = _komodo_userpass(username,password,fp); - DEST_PORT = iter == 1 ? dest_rpc_port : 0; - sprintf(iter == 0 ? KMDUSERPASS : BTCUSERPASS,"%s:%s",username,password); - fclose(fp); - } else printf("couldnt open.(%s) will not validate dest notarizations\n",fname); - if ( !IS_KOMODO_NOTARY ) - break; - } + + auto datadir_path = GetDataDir(); + uint16_t ignore; + get_userpass_and_port(datadir_path, filename, KMDUSERPASS, ignore); + if (IS_KOMODO_NOTARY) + get_userpass_and_port(datadir_path, ntz_dest_path, BTCUSERPASS, DEST_PORT); } int32_t dpowconfs = KOMODO_DPOWCONFS; if ( ASSETCHAINS_SYMBOL[0] != 0 ) diff --git a/src/komodo_utils.h b/src/komodo_utils.h index 1ffce5a7f5c..afc7a962f06 100644 --- a/src/komodo_utils.h +++ b/src/komodo_utils.h @@ -356,6 +356,13 @@ int32_t queue_size(queue_t *queue); void iguana_initQ(queue_t *Q,char *name); +/** + * @brief Get the username, password, and port from a file + * @param[out] username the username found in the config file + * @param[out] password the password found in the config file + * @param[in] fp the file to be read + * @return the RPC port + */ uint16_t _komodo_userpass(char *username,char *password,FILE *fp); void komodo_statefname(char *fname,char *symbol,char *str); diff --git a/src/test-komodo/test_parse_notarisation.cpp b/src/test-komodo/test_parse_notarisation.cpp index 5efcb4a8bd4..792e7400987 100644 --- a/src/test-komodo/test_parse_notarisation.cpp +++ b/src/test-komodo/test_parse_notarisation.cpp @@ -7,6 +7,7 @@ #include "komodo_structs.h" #include "test_parse_notarisation.h" +#include #include komodo_state *komodo_stateptr(char *symbol,char *dest); @@ -15,6 +16,9 @@ void komodo_notarized_update(struct komodo_state *sp,int32_t nHeight,int32_t not const notarized_checkpoint *komodo_npptr(int32_t height); int32_t komodo_prevMoMheight(); int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); +// method in komodo_utils.cpp: +void get_userpass_and_port(const boost::filesystem::path& path, const std::string& filename, + std::string userpass, uint16_t& port); class komodo_state_accessor : public komodo_state { @@ -525,4 +529,56 @@ TEST(TestParseNotarisation, DISABLED_OldVsNew) // for l in `g 'parse notarisation' ~/.komodo/debug.log | pyline 'l.split()[8]'`; do hoek decodeTx '{"hex":"'`src/komodo-cli getrawtransaction "$l"`'"}' | jq '.outputs[1].script.op_return' | pyline 'import base64; print base64.b64decode(l).encode("hex")'; done +TEST(TestParseNotarisation, FilePaths) +{ + // helper for home directory + class MockHomeDirectory + { + public: + MockHomeDirectory() + { + data_path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + boost::filesystem::create_directories(data_path); + orig_home = getenv("HOME"); + setenv("HOME", data_path.c_str(), true); + + } + ~MockHomeDirectory() + { + boost::filesystem::remove_all(data_path); + setenv("HOME", orig_home.c_str(), true); + } + bool create_komodo_config() + { + std::string filename = (data_path /= "komodo.conf").string(); + std::ofstream komodo(filename); + komodo << "username:test1\n" + << "password=my_password\n" + << "rpcport=1234"; + return true; + } + boost::filesystem::path data_path; + std::string orig_home; + }; + { + // default + MockHomeDirectory home; + mapArgs["-datadir"] = ""; + mapArgs["-notary"] = ""; + home.create_komodo_config(); + std::string userpass; + std::string expected("test1:my_password"); + uint16_t port; + get_userpass_and_port(home.data_path, "komodo.conf", userpass, port); + EXPECT_EQ(userpass, expected); + EXPECT_EQ(port, 1234); + } + { + // with -datadir + } + { + // with -notary + } } + +} // namespace TestParseNotarisation diff --git a/src/util.cpp b/src/util.cpp index fa62ba1ff85..97fee9f45f3 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -529,8 +529,14 @@ void PrintExceptionContinue(const std::exception* pex, const char* pszThread) } extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN]; -//int64_t MAX_MONEY = 200000000 * 100000000LL; +/**** + * @brief get the OS-specific default data directory + * @note Windows: be "C:\Users\[username]\AppData\Roaming\Komodo" + * @note Mac: ~/Library/Application Support/Komodo + * @note Unix: ~/.komodo + * @returns the default path to the Komodo data directory + */ boost::filesystem::path GetDefaultDataDir() { namespace fs = boost::filesystem; @@ -649,7 +655,13 @@ const boost::filesystem::path GetExportDir() return path; } - +/**** + * @brief determine the data directory + * @note looks at the -datadir command-line parameter or OS-specific defaults + * @note creates the directory if it does not already exist + * @param fNetSpecific if true, adds network-specific subdirectory (i.e. "regtest" or "testnet3") + * @returns the full OS-specific data directory including Komodo (i.e. "~/.komodo") + */ const boost::filesystem::path &GetDataDir(bool fNetSpecific) { namespace fs = boost::filesystem; @@ -677,8 +689,6 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) path /= BaseParams().DataDir(); fs::create_directories(path); - //std::string assetpath = path + "/assets"; - //boost::filesystem::create_directory(assetpath); return path; } diff --git a/src/util.h b/src/util.h index 17bf19952b0..fb61df33e49 100644 --- a/src/util.h +++ b/src/util.h @@ -139,7 +139,21 @@ int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); bool TryCreateDirectory(const boost::filesystem::path& p); +/**** + * @brief get the OS-specific default data directory + * @note Windows: be "C:\Users\[username]\AppData\Roaming\Komodo" + * @note Mac: ~/Library/Application Support/Komodo + * @note Unix: ~/.komodo + * @returns the default path to the Komodo data directory + */ boost::filesystem::path GetDefaultDataDir(); +/**** + * @brief determine the data directory + * @note looks at the -datadir command-line parameter or OS-specific defaults + * @note creates the directory if it does not already exist + * @param fNetSpecific if true, adds network-specific subdirectory (i.e. "regtest" or "testnet3") + * @returns the full OS-specific data directory including Komodo (i.e. "~/.komodo") + */ const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); void ClearDatadirCache(); boost::filesystem::path GetConfigFile(); From d4624fd6238b122c0be4ddfd648b367e247cc12b Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 27 Jun 2022 15:08:37 -0500 Subject: [PATCH 47/47] add test --- src/komodo_utils.cpp | 111 +++++++++++--------- src/test-komodo/test_parse_notarisation.cpp | 91 ++++++++++++---- 2 files changed, 131 insertions(+), 71 deletions(-) diff --git a/src/komodo_utils.cpp b/src/komodo_utils.cpp index 6b5aaef7b15..a88b52389fc 100644 --- a/src/komodo_utils.cpp +++ b/src/komodo_utils.cpp @@ -1261,8 +1261,10 @@ int8_t equihash_params_possible(uint64_t n, uint64_t k) * @param[out] port the RPC port found in the config file */ void get_userpass_and_port(const boost::filesystem::path& path, const std::string& filename, - std::string userpass, uint16_t& port) + std::string& userpass, uint16_t& port) { + userpass = ""; + port = 0; boost::filesystem::path datadir_path = path; datadir_path /= filename; FILE* fp = fopen(datadir_path.c_str(), "rb"); @@ -1271,28 +1273,59 @@ void get_userpass_and_port(const boost::filesystem::path& path, const std::strin char username[512]; char password[4096]; port = _komodo_userpass(username,password,fp); - userpass = std::string(username) + ":" + std::string(password); + if ( username[0] != 0 && password[0] != 0 ) + userpass = std::string(username) + ":" + std::string(password); fclose(fp); } else printf("couldnt open.(%s) will not validate dest notarizations\n", datadir_path.c_str()); } +/**** + * @brief set ports and usernames/passwords from command line and/or config files + * @note modifies ASSETCHAINS_P2PPORT, ASSETCHAINS_RPCPORT, KMDUSERPASS, BTCUSERPASS, DESTPORT + * @note IS_KOMODO_NOTARY should already be set + * @param ltc_config_filename configuration file for ltc (via -notary command line parameter) + */ +void set_kmd_user_password_port(const std::string& ltc_config_filename) +{ + ASSETCHAINS_P2PPORT = 7770; // default port for P2P + ASSETCHAINS_RPCPORT = 7771; // default port for RPC +#ifdef __APPLE__ + std::string filename = "Komodo.conf"; +#else + std::string filename = "komodo.conf"; +#endif + + auto datadir_path = GetDataDir(); + uint16_t ignore; + std::string userpass; + get_userpass_and_port(datadir_path, filename, userpass, ignore); + if (!userpass.empty()) + strncpy(KMDUSERPASS, userpass.c_str(), 8705); + if (IS_KOMODO_NOTARY) + { + get_userpass_and_port(datadir_path, ltc_config_filename, userpass, DEST_PORT); + if (!userpass.empty()) + strncpy(BTCUSERPASS, userpass.c_str(), 8192); + } +} + void komodo_args(char *argv0) { - std::string name,addn,hexstr,symbol; char *dirname,fname[512],arg0str[64],magicstr[9]; uint8_t magic[4],extrabuf[32756],disablebits[32],*extraptr=0; - FILE *fp; uint64_t val; uint16_t port; int32_t i,nonz=0,baseid,len,n,extralen = 0; uint64_t ccenables[256], ccEnablesHeight[512] = {0}; CTransaction earlytx; uint256 hashBlock; + std::string name; // -ac_name + char *dirname; + uint8_t disablebits[32],*extraptr=0; + FILE *fp; + int32_t i,nonz=0,n; - std::string ntz_dest_path; - ntz_dest_path = GetArg("-notary", ""); + const std::string ntz_dest_path = GetArg("-notary", ""); IS_KOMODO_NOTARY = ntz_dest_path == "" ? 0 : 1; STAKED_NOTARY_ID = GetArg("-stakednotary", -1); KOMODO_NSPV = GetArg("-nSPV",0); - memset(ccenables,0,sizeof(ccenables)); memset(disablebits,0,sizeof(disablebits)); - memset(ccEnablesHeight,0,sizeof(ccEnablesHeight)); if ( GetBoolArg("-gen", false) != 0 ) { KOMODO_MININGTHREADS = GetArg("-genproclimit",-1); @@ -1333,7 +1366,7 @@ void komodo_args(char *argv0) name = GetArg("-ac_name",""); if ( argv0 != 0 ) { - len = (int32_t)strlen(argv0); + int32_t len = (int32_t)strlen(argv0); for (i=0; i 0 ) - { - for (i=first; i<=last; i++) - { - CLEARBIT(disablebits,i); - ASSETCHAINS_CCDISABLES[i] = 0; - } - }*/ } if ( ASSETCHAINS_BEAMPORT != 0 ) { @@ -1645,8 +1674,10 @@ void komodo_args(char *argv0) printf("ASSETCHAINS_FOUNDERS needs an ASSETCHAINS_OVERRIDE_PUBKEY or ASSETCHAINS_SCRIPTPUB\n"); } } + int32_t extralen = 0; if ( ASSETCHAINS_ENDSUBSIDY[0] != 0 || ASSETCHAINS_REWARD[0] != 0 || ASSETCHAINS_HALVING[0] != 0 || ASSETCHAINS_DECAY[0] != 0 || ASSETCHAINS_COMMISSION != 0 || ASSETCHAINS_PUBLIC != 0 || ASSETCHAINS_PRIVATE != 0 || ASSETCHAINS_TXPOW != 0 || ASSETCHAINS_FOUNDERS != 0 || ASSETCHAINS_SCRIPTPUB.size() > 1 || ASSETCHAINS_SELFIMPORT.size() > 0 || ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 || ASSETCHAINS_TIMELOCKGTE != _ASSETCHAINS_TIMELOCKOFF|| ASSETCHAINS_ALGO != ASSETCHAINS_EQUIHASH || ASSETCHAINS_LASTERA > 0 || ASSETCHAINS_BEAMPORT != 0 || ASSETCHAINS_CODAPORT != 0 || nonz > 0 || ASSETCHAINS_CCLIB.size() > 0 || ASSETCHAINS_FOUNDERS_REWARD != 0 || ASSETCHAINS_NOTARY_PAY[0] != 0 || ASSETCHAINS_BLOCKTIME != 60 || ASSETCHAINS_CBOPRET != 0 || Mineropret.size() != 0 || (ASSETCHAINS_NK[0] != 0 && ASSETCHAINS_NK[1] != 0) || KOMODO_SNAPSHOT_INTERVAL != 0 || ASSETCHAINS_EARLYTXIDCONTRACT != 0 || ASSETCHAINS_CBMATURITY != 0 || ASSETCHAINS_ADAPTIVEPOW != 0 ) { + uint8_t extrabuf[32756]; fprintf(stderr,"perc %.4f%% ac_pub=[%02x%02x%02x...] acsize.%d\n",dstr(ASSETCHAINS_COMMISSION)*100,ASSETCHAINS_OVERRIDE_PUBKEY33[0],ASSETCHAINS_OVERRIDE_PUBKEY33[1],ASSETCHAINS_OVERRIDE_PUBKEY33[2],(int32_t)ASSETCHAINS_SCRIPTPUB.size()); extraptr = extrabuf; memcpy(extraptr,ASSETCHAINS_OVERRIDE_PUBKEY33,33), extralen = 33; @@ -1689,7 +1720,7 @@ void komodo_args(char *argv0) extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(ASSETCHAINS_ALGO),(void *)&ASSETCHAINS_ALGO); } - val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; + uint64_t val = ASSETCHAINS_COMMISSION | (((int64_t)ASSETCHAINS_STAKED & 0xff) << 32) | (((uint64_t)ASSETCHAINS_CC & 0xffff) << 40) | ((ASSETCHAINS_PUBLIC != 0) << 7) | ((ASSETCHAINS_PRIVATE != 0) << 6) | ASSETCHAINS_TXPOW; extralen += iguana_rwnum(1,&extraptr[extralen],sizeof(val),(void *)&val); if ( ASSETCHAINS_FOUNDERS != 0 ) @@ -1708,7 +1739,6 @@ void komodo_args(char *argv0) { decode_hex(&extraptr[extralen],ASSETCHAINS_SCRIPTPUB.size()/2,(char *)ASSETCHAINS_SCRIPTPUB.c_str()); extralen += ASSETCHAINS_SCRIPTPUB.size()/2; - //extralen += iguana_rwnum(1,&extraptr[extralen],(int32_t)ASSETCHAINS_SCRIPTPUB.size(),(void *)ASSETCHAINS_SCRIPTPUB.c_str()); fprintf(stderr,"append ac_script %s\n",ASSETCHAINS_SCRIPTPUB.c_str()); } if ( ASSETCHAINS_SELFIMPORT.size() > 0 ) @@ -1752,7 +1782,7 @@ void komodo_args(char *argv0) { for (i=0; i 0 ) + const std::string addn = GetArg("-seednode",""); + if ( addn.size() > 0 ) ASSETCHAINS_SEED = 1; strncpy(ASSETCHAINS_SYMBOL,name.c_str(),sizeof(ASSETCHAINS_SYMBOL)-1); @@ -1802,9 +1831,9 @@ void komodo_args(char *argv0) MAX_MONEY = komodo_max_money(); - if ( (baseid = komodo_baseid(ASSETCHAINS_SYMBOL)) >= 0 && baseid < 32 ) + int32_t baseid = komodo_baseid(ASSETCHAINS_SYMBOL); + if ( baseid >= 0 && baseid < 32 ) { - //komodo_maxallowed(baseid); printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); } @@ -1813,7 +1842,6 @@ void komodo_args(char *argv0) if ( KOMODO_BIT63SET(MAX_MONEY) != 0 ) MAX_MONEY = KOMODO_MAXNVALUE; fprintf(stderr,"MAX_MONEY %llu %.8f\n",(long long)MAX_MONEY,(double)MAX_MONEY/SATOSHIDEN); - //printf("baseid.%d MAX_MONEY.%s %.8f\n",baseid,ASSETCHAINS_SYMBOL,(double)MAX_MONEY/SATOSHIDEN); uint16_t tmpport = komodo_port(ASSETCHAINS_SYMBOL,ASSETCHAINS_SUPPLY,&ASSETCHAINS_MAGIC,extraptr,extralen); if ( GetArg("-port",0) != 0 ) { @@ -1830,7 +1858,6 @@ void komodo_args(char *argv0) boost::this_thread::sleep(boost::posix_time::milliseconds(3000)); #endif } - //fprintf(stderr,"Got datadir.(%s)\n",dirname); if ( ASSETCHAINS_SYMBOL[0] != 0 ) { int32_t komodo_baseid(char *origbase); @@ -1839,7 +1866,8 @@ void komodo_args(char *argv0) fprintf(stderr,"cant have assetchain named KMD\n"); StartShutdown(); } - if ( (port= komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL)) != 0 ) + uint16_t port = komodo_userpass(ASSETCHAINS_USERPASS,ASSETCHAINS_SYMBOL); + if ( port != 0 ) ASSETCHAINS_RPCPORT = port; else komodo_configfile(ASSETCHAINS_SYMBOL,ASSETCHAINS_P2PPORT + 1); @@ -1852,17 +1880,18 @@ void komodo_args(char *argv0) fprintf(stderr,"ac_cbmaturity must be >0, shutting down\n"); StartShutdown(); } - //fprintf(stderr,"ASSETCHAINS_RPCPORT (%s) %u\n",ASSETCHAINS_SYMBOL,ASSETCHAINS_RPCPORT); } if ( ASSETCHAINS_RPCPORT == 0 ) ASSETCHAINS_RPCPORT = ASSETCHAINS_P2PPORT + 1; - //ASSETCHAINS_NOTARIES = GetArg("-ac_notaries",""); - //komodo_assetchain_pubkeys((char *)ASSETCHAINS_NOTARIES.c_str()); + + uint8_t magic[4]; iguana_rwnum(1,magic,sizeof(ASSETCHAINS_MAGIC),(void *)&ASSETCHAINS_MAGIC); + char magicstr[9]; for (i=0; i<4; i++) sprintf(&magicstr[i<<1],"%02x",magic[i]); magicstr[8] = 0; #ifndef FROM_CLI + char fname[512]; sprintf(fname,"%s_7776",ASSETCHAINS_SYMBOL); if ( (fp= fopen(fname,"wb")) != 0 ) { @@ -1871,7 +1900,6 @@ void komodo_args(char *argv0) notarypay = 1; fprintf(fp,iguanafmtstr,name.c_str(),name.c_str(),name.c_str(),name.c_str(),magicstr,ASSETCHAINS_P2PPORT,ASSETCHAINS_RPCPORT,"78.47.196.146",notarypay); fclose(fp); - //printf("created (%s)\n",fname); } else printf("error creating (%s)\n",fname); #endif if ( ASSETCHAINS_CC < 2 ) @@ -1891,25 +1919,12 @@ void komodo_args(char *argv0) else { // -ac_name not passed, we are on the KMD chain - ASSETCHAINS_P2PPORT = 7770; // default port for P2P - ASSETCHAINS_RPCPORT = 7771; // default port for RPC -#ifdef __APPLE__ - std::string filename = "Komodo.conf"; -#else - std::string filename = "komodo.conf"; -#endif - - auto datadir_path = GetDataDir(); - uint16_t ignore; - get_userpass_and_port(datadir_path, filename, KMDUSERPASS, ignore); - if (IS_KOMODO_NOTARY) - get_userpass_and_port(datadir_path, ntz_dest_path, BTCUSERPASS, DEST_PORT); + set_kmd_user_password_port(ntz_dest_path); } int32_t dpowconfs = KOMODO_DPOWCONFS; if ( ASSETCHAINS_SYMBOL[0] != 0 ) { BITCOIND_RPCPORT = GetArg("-rpcport", ASSETCHAINS_RPCPORT); - //fprintf(stderr,"(%s) port.%u chain params initialized\n",ASSETCHAINS_SYMBOL,BITCOIND_RPCPORT); if ( strcmp("PIRATE",ASSETCHAINS_SYMBOL) == 0 && ASSETCHAINS_HALVING[0] == 77777 ) { ASSETCHAINS_HALVING[0] *= 5; diff --git a/src/test-komodo/test_parse_notarisation.cpp b/src/test-komodo/test_parse_notarisation.cpp index 792e7400987..3d80c5d3f02 100644 --- a/src/test-komodo/test_parse_notarisation.cpp +++ b/src/test-komodo/test_parse_notarisation.cpp @@ -17,8 +17,10 @@ const notarized_checkpoint *komodo_npptr(int32_t height); int32_t komodo_prevMoMheight(); int32_t komodo_notarizeddata(int32_t nHeight,uint256 *notarized_hashp,uint256 *notarized_desttxidp); // method in komodo_utils.cpp: -void get_userpass_and_port(const boost::filesystem::path& path, const std::string& filename, - std::string userpass, uint16_t& port); +void set_kmd_user_password_port(const std::string& ltc_config_filename); +extern char KMDUSERPASS[8705]; +extern char BTCUSERPASS[8192]; +extern uint16_t DEST_PORT; class komodo_state_accessor : public komodo_state { @@ -532,29 +534,32 @@ TEST(TestParseNotarisation, DISABLED_OldVsNew) TEST(TestParseNotarisation, FilePaths) { // helper for home directory - class MockHomeDirectory + class MockDataDirectory { public: - MockHomeDirectory() + MockDataDirectory() { + ClearDatadirCache(); data_path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); - boost::filesystem::create_directories(data_path); + auto komodo_path = data_path / ".komodo" / "regtest"; + boost::filesystem::create_directories(komodo_path); orig_home = getenv("HOME"); setenv("HOME", data_path.c_str(), true); - } - ~MockHomeDirectory() + ~MockDataDirectory() { boost::filesystem::remove_all(data_path); setenv("HOME", orig_home.c_str(), true); + ClearDatadirCache(); } - bool create_komodo_config() + bool create_config(const std::string& filename, const std::string& user, + const std::string& pass, uint16_t port) { - std::string filename = (data_path /= "komodo.conf").string(); - std::ofstream komodo(filename); - komodo << "username:test1\n" - << "password=my_password\n" - << "rpcport=1234"; + std::string file = (data_path / ".komodo" / "regtest" / filename).string(); + std::ofstream komodo(file); + komodo << "rpcuser=" << user << "\n" + << "rpcpassword=" << pass << "\n" + << "rpcport=" << std::to_string(port) << "\n"; return true; } boost::filesystem::path data_path; @@ -562,22 +567,62 @@ TEST(TestParseNotarisation, FilePaths) }; { // default - MockHomeDirectory home; - mapArgs["-datadir"] = ""; - mapArgs["-notary"] = ""; - home.create_komodo_config(); - std::string userpass; - std::string expected("test1:my_password"); - uint16_t port; - get_userpass_and_port(home.data_path, "komodo.conf", userpass, port); - EXPECT_EQ(userpass, expected); - EXPECT_EQ(port, 1234); + MockDataDirectory home; + mapArgs.erase("-datadir"); + ASSETCHAINS_P2PPORT = 0; + ASSETCHAINS_RPCPORT = 0; + memset(KMDUSERPASS, 0, sizeof(KMDUSERPASS) ); + memset(BTCUSERPASS, 0, sizeof(BTCUSERPASS) ); + DEST_PORT=0; + IS_KOMODO_NOTARY = 0; + home.create_config("komodo.conf", "test1", "my_password", 1234); + home.create_config("ltc.conf", "test2", "ltc_password", 5678); + set_kmd_user_password_port("ltc.conf"); + EXPECT_EQ( std::string(KMDUSERPASS), std::string("test1:my_password") ); + EXPECT_EQ( std::string(BTCUSERPASS), std::string("")); + EXPECT_EQ(DEST_PORT, 0); + EXPECT_EQ(ASSETCHAINS_P2PPORT, 7770); + EXPECT_EQ(ASSETCHAINS_RPCPORT, 7771); } { // with -datadir + MockDataDirectory home; + mapArgs["-datadir"] = home.data_path.string() + "/.komodo"; + ASSETCHAINS_P2PPORT = 0; + ASSETCHAINS_RPCPORT = 0; + memset(KMDUSERPASS, 0, sizeof(KMDUSERPASS) ); + memset(BTCUSERPASS, 0, sizeof(BTCUSERPASS) ); + DEST_PORT=0; + IS_KOMODO_NOTARY = 0; + std::string expected_kmd("test1:my_password"); + home.create_config("komodo.conf", "test1", "my_password", 1234); + home.create_config("ltc.conf", "test2", "ltc_password", 5678); + set_kmd_user_password_port("ltc.conf"); + EXPECT_EQ( std::string(KMDUSERPASS), std::string("test1:my_password") ); + EXPECT_EQ( std::string(BTCUSERPASS), std::string("")); + EXPECT_EQ(DEST_PORT, 0); + EXPECT_EQ(ASSETCHAINS_P2PPORT, 7770); + EXPECT_EQ(ASSETCHAINS_RPCPORT, 7771); } { // with -notary + MockDataDirectory home; + mapArgs["-datadir"] = home.data_path.string() + "/.komodo"; + ASSETCHAINS_P2PPORT = 0; + ASSETCHAINS_RPCPORT = 0; + memset(KMDUSERPASS, 0, sizeof(KMDUSERPASS) ); + memset(BTCUSERPASS, 0, sizeof(BTCUSERPASS) ); + DEST_PORT=0; + IS_KOMODO_NOTARY = 1; + std::string expected_kmd("test1:my_password"); + home.create_config("komodo.conf", "test1", "my_password", 1234); + home.create_config("ltc.conf", "test2", "ltc_password", 5678); + set_kmd_user_password_port("ltc.conf"); + EXPECT_EQ(std::string(KMDUSERPASS), std::string("test1:my_password")); + EXPECT_EQ(std::string(BTCUSERPASS), std::string("test2:ltc_password")); + EXPECT_EQ(DEST_PORT, 5678); + EXPECT_EQ(ASSETCHAINS_P2PPORT, 7770); + EXPECT_EQ(ASSETCHAINS_RPCPORT, 7771); } }