diff --git a/gridcoinresearch.pro b/gridcoinresearch.pro index 2077cd8db1..e177fe76eb 100755 --- a/gridcoinresearch.pro +++ b/gridcoinresearch.pro @@ -260,7 +260,8 @@ HEADERS += src/qt/bitcoingui.h \ src/boinc.h \ src/qt/diagnosticsdialog.h \ src/backup.h \ - src/appcache.h + src/appcache.h \ + src/tally.h SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ @@ -340,7 +341,8 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/boinc.cpp \ src/allocators.cpp \ src/backup.cpp \ - src/appcache.cpp + src/appcache.cpp \ + src/tally.cpp ## #RC_FILE = qaxserver.rc diff --git a/src/Makefile.include.objs b/src/Makefile.include.objs index dd643edb8f..681f744804 100755 --- a/src/Makefile.include.objs +++ b/src/Makefile.include.objs @@ -39,4 +39,5 @@ OBJS= \ obj/boinc.o \ obj/allocators.o \ obj/backup.o \ - obj/appcache.o + obj/appcache.o \ + obj/tally.o diff --git a/src/init.cpp b/src/init.cpp index 2b885b494a..13bebcd361 100755 --- a/src/init.cpp +++ b/src/init.cpp @@ -9,6 +9,8 @@ #include "init.h" #include "util.h" #include "ui_interface.h" +#include "tally.h" + #include #include #include @@ -24,7 +26,7 @@ bool LoadAdminMessages(bool bFullTableScan,std::string& out_errors); StructCPID GetStructCPID(); void BusyWaitForTally_retired(); -void TallyNetworkAverages_v9(); +void TallyNetworkAverages_v9(CBlockIndex* index); extern void ThreadAppInit2(void* parg); void LoadCPIDs(); @@ -1013,7 +1015,9 @@ bool AppInit2(ThreadHandlerPtr threads) uiInterface.InitMessage(_("Loading Network Averages...")); if (fDebug3) printf("Loading network averages"); - TallyNetworkAverages_v9(); + CBlockIndex* tallyHeight = FindTallyTrigger(pindexBest); + if(tallyHeight) + TallyNetworkAverages_v9(tallyHeight); if (!threads->createThread(StartNode, NULL, "Start Thread")) InitError(_("Error: could not start node")); diff --git a/src/main.cpp b/src/main.cpp index f538219991..fdd82342e5 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,6 +23,7 @@ #include "miner.h" #include "backup.h" #include "appcache.h" +#include "tally.h" #include #include @@ -52,7 +53,7 @@ extern bool AskForOutstandingBlocks(uint256 hashStart); extern bool CleanChain(); extern void ResetTimerMain(std::string timer_name); extern bool TallyResearchAverages_retired(bool Forcefully); -extern bool TallyNetworkAverages_v9(); +extern bool TallyNetworkAverages_v9(CBlockIndex* index); extern void IncrementCurrentNeuralNetworkSupermajority(std::string NeuralHash, std::string GRCAddress, double distance); bool VerifyCPIDSignature(std::string sCPID, std::string sBlockHash, std::string sSignature); extern MiningCPID GetInitializedMiningCPID(std::string name, std::map& vRef); @@ -3508,9 +3509,9 @@ bool DisconnectBlocksBatch(CTxDB& txdb, list& vResurrect, unsigned // Tally research averages. if(IsV9Enabled_Tally(nBestHeight)) { - assert(0==(pcommon->nHeight % TALLY_GRANULARITY)); + assert(IsTallyTrigger(pcommon)); if (fDebug) printf("DisconnectBlocksBatch: TallyNetworkAverages (v9P %%%d) height %d\n",TALLY_GRANULARITY,nBestHeight); - TallyNetworkAverages_v9(); + TallyNetworkAverages_v9(pindexBest); } else { @@ -3555,9 +3556,9 @@ bool ReorganizeChain(CTxDB& txdb, unsigned &cnt_dis, unsigned &cnt_con, CBlock & return error("ReorganizeChain: unable to find fork root"); } - if(pcommon!=pindexBest) while( (pcommon->nHeight % TALLY_GRANULARITY)!=0 ) + if(pcommon != pindexBest) { - pcommon = pcommon->pprev; + pcommon = FindTallyTrigger(pcommon); if(!pcommon) return error("ReorganizeChain: unable to find fork root with tally point"); } @@ -3689,10 +3690,10 @@ bool ReorganizeChain(CTxDB& txdb, unsigned &cnt_dis, unsigned &cnt_con, CBlock & { // quorum not needed // Tally research averages. - if ((nBestHeight % TALLY_GRANULARITY) == 0) + if(IsTallyTrigger(pindexBest)) { if (fDebug) printf("ReorganizeChain: TallyNetworkAverages (v9N %%%d) height %d\n",TALLY_GRANULARITY,nBestHeight); - TallyNetworkAverages_v9(); + TallyNetworkAverages_v9(pindexBest); } } else @@ -5763,13 +5764,13 @@ bool TallyNetworkAverages_retired(bool Forcefully) -bool TallyResearchAverages_v9() +bool TallyResearchAverages_v9(CBlockIndex* index) { - if(!IsV9Enabled_Tally(nBestHeight)) + if(!IsV9Enabled_Tally(index->nHeight)) return error("TallyResearchAverages_v9: called while V9 tally disabled\n"); //Iterate throught last 14 days, tally network averages - if (nBestHeight < 15) + if (index->nHeight < 15) { bNetAveragesLoaded = true; return true; @@ -5784,7 +5785,7 @@ bool TallyResearchAverages_v9() double NetworkInterest = 0; //Consensus Start/End block: - int nMaxConensusDepth = nBestHeight - CONSENSUS_LOOKBACK; + int nMaxConensusDepth = index->nHeight - CONSENSUS_LOOKBACK; int nMaxDepth = nMaxConensusDepth - (nMaxConensusDepth % TALLY_GRANULARITY); int nLookback = BLOCKS_PER_DAY * 14; //Daily block count * Lookback in days int nMinDepth = nMaxDepth - nLookback; @@ -5794,7 +5795,7 @@ bool TallyResearchAverages_v9() if(fDebug) printf("TallyResearchAverages: start %d end %d\n",nMaxDepth,nMinDepth); mvMagnitudesCopy.clear(); - CBlockIndex* pblockindex = pindexBest; + CBlockIndex* pblockindex = index; if (!pblockindex) { bNetAveragesLoaded = true; @@ -5880,11 +5881,9 @@ bool TallyResearchAverages_v9() return false; } - - -bool TallyNetworkAverages_v9() +bool TallyNetworkAverages_v9(CBlockIndex* index) { - if (IsResearchAgeEnabled(pindexBest->nHeight) && IsV9Enabled_Tally(pindexBest->nHeight)) + if (IsResearchAgeEnabled(index->nHeight) && IsV9Enabled_Tally(index->nHeight)) { if(!bTallyFinished_retired) { @@ -5894,7 +5893,7 @@ bool TallyNetworkAverages_v9() while(!bTallyFinished_retired) MilliSleep(10); } - return TallyResearchAverages_v9(); + return TallyResearchAverages_v9(index); } return false; diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 70d506e47b..80d02f7d44 100755 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -14,6 +14,7 @@ #include "util.h" #include "backup.h" #include "appcache.h" +#include "tally.h" #include #include @@ -23,7 +24,7 @@ #include -bool TallyResearchAverages_v9(); +bool TallyResearchAverages_v9(CBlockIndex* index); using namespace json_spirit; using namespace std; extern std::string YesNo(bool bin); @@ -2047,10 +2048,11 @@ Value execute(const Array& params, bool fHelp) } else if (sItem == "tally") { - bNetAveragesLoaded_retired = false; - TallyResearchAverages_v9(); - entry.push_back(Pair("Tally Network Averages",1)); - results.push_back(entry); + bNetAveragesLoaded_retired = false; + CBlockIndex* tallyIndex = FindTallyTrigger(pindexBest); + TallyResearchAverages_v9(tallyIndex); + entry.push_back(Pair("Tally Network Averages",1)); + results.push_back(entry); } else if (sItem == "encrypt") { diff --git a/src/tally.cpp b/src/tally.cpp new file mode 100644 index 0000000000..dcd3e7720b --- /dev/null +++ b/src/tally.cpp @@ -0,0 +1,20 @@ +#include "tally.h" +#include "main.h" + +#include + +CBlockIndex* FindTallyTrigger(CBlockIndex* block) +{ + // Scan backwards until we find one where accepting it would + // trigger a tally. + for(; + block && block->pprev && !IsTallyTrigger(block); + block = block->pprev); + + return block; +} + +bool IsTallyTrigger(const CBlockIndex *block) +{ + return block && block->nHeight % TALLY_GRANULARITY == 0; +} diff --git a/src/tally.h b/src/tally.h new file mode 100644 index 0000000000..9d131bd776 --- /dev/null +++ b/src/tally.h @@ -0,0 +1,25 @@ +#pragma once + +#include "fwd.h" + +//! +//! \brief Find previous tally trigger from block. +//! +//! Scans the chain back from \p block to find the block which should be used +//! as the starting point for a tally. \p block must not be NULL. +//! +//! \param block Block to start from. +//! \return Tally trigger point from \p block. +//! +CBlockIndex* FindTallyTrigger(CBlockIndex* block); + +//! +//! \brief Check if a block is a tally trigger. +//! +//! Checks the height of \p block to see if it matches the tally granularity. +//! If this returns \c false then no tally should be made on that block. +//! +//! \param block Block to check. +//! \return +//! +bool IsTallyTrigger(const CBlockIndex* block); diff --git a/src/test/tally_tests.cpp b/src/test/tally_tests.cpp new file mode 100644 index 0000000000..3a2a580a0f --- /dev/null +++ b/src/test/tally_tests.cpp @@ -0,0 +1,58 @@ +#include "tally.h" +#include "main.h" + +#include +#include +#include + +namespace +{ + typedef std::shared_ptr CBlockIndexPtr; + std::vector CreateChain() + { + std::vector blocks; + + // Create a chain of 100 blocks + for(int i=1; i<=100; ++i) + { + CBlockIndexPtr block = std::make_shared(); + block->nHeight = i; + + // Attach to chain + if(!blocks.empty()) + { + CBlockIndexPtr previous = blocks.back(); + previous->pnext = block.get(); + block->pprev = previous.get(); + } + + blocks.push_back(block); + } + + return blocks; + } +} + +BOOST_AUTO_TEST_SUITE(tally_tests) + +BOOST_AUTO_TEST_CASE(tally_FindTallyTriggerShouldUseTallyGranularity) +{ + BOOST_CHECK_EQUAL(TALLY_GRANULARITY, 10); + + auto chain = CreateChain(); + CBlockIndexPtr head = chain.back(); + + const CBlockIndex* block = FindTallyTrigger(head.get()->pprev); + BOOST_CHECK_EQUAL(block->nHeight, 90); +} + +BOOST_AUTO_TEST_CASE(tally_IsTallyTriggerShouldUseTallyGranularity) +{ + auto chain = CreateChain(); + CBlockIndexPtr head = chain.back(); + + BOOST_CHECK(IsTallyTrigger(head.get())); + BOOST_CHECK(IsTallyTrigger(head->pprev) == false); +} + +BOOST_AUTO_TEST_SUITE_END()