diff options
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp index d3956fafda..ac7d50ce65 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,6 +28,7 @@ #include <boost/algorithm/string/replace.hpp> #include <boost/filesystem.hpp> #include <boost/filesystem/fstream.hpp> +#include <boost/math/distributions/poisson.hpp> #include <boost/thread.hpp> using namespace std; @@ -1685,6 +1686,64 @@ void ThreadScriptCheck() { scriptcheckqueue.Thread(); } +// +// Called periodically asynchronously; alerts if it smells like +// we're being fed a bad chain (blocks being generated much +// too slowly or too quickly). +// +void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CChain& chain, int64_t nPowTargetSpacing) +{ + if (initialDownloadCheck()) return; + + static int64_t lastAlertTime = 0; + int64_t now = GetAdjustedTime(); + if (lastAlertTime > now-60*60*24) return; // Alert at most once per day + + const int SPAN_HOURS=4; + const int SPAN_SECONDS=SPAN_HOURS*60*60; + int BLOCKS_EXPECTED = SPAN_SECONDS / nPowTargetSpacing; + + boost::math::poisson_distribution<double> poisson(BLOCKS_EXPECTED); + + std::string strWarning; + int64_t startTime = GetAdjustedTime()-SPAN_SECONDS; + + LOCK(cs); + int h = chain.Height(); + while (h > 0 && chain[h]->GetBlockTime() >= startTime) + --h; + int nBlocks = chain.Height()-h; + + // How likely is it to find that many by chance? + double p = boost::math::pdf(poisson, nBlocks); + + LogPrint("partitioncheck", "%s : Found %d blocks in the last %d hours\n", __func__, nBlocks, SPAN_HOURS); + LogPrint("partitioncheck", "%s : likelihood: %g\n", __func__, p); + + // Aim for one false-positive about every fifty years of normal running: + const int FIFTY_YEARS = 50*365*24*60*60; + double alertThreshold = 1.0 / (FIFTY_YEARS / SPAN_SECONDS); + + if (p <= alertThreshold && nBlocks < BLOCKS_EXPECTED) + { + // Many fewer blocks than expected: alert! + strWarning = strprintf(_("WARNING: check your network connection, %d blocks received in the last %d hours (%d expected)"), + nBlocks, SPAN_HOURS, BLOCKS_EXPECTED); + } + else if (p <= alertThreshold && nBlocks > BLOCKS_EXPECTED) + { + // Many more blocks than expected: alert! + strWarning = strprintf(_("WARNING: abnormally high number of blocks generated, %d blocks received in the last %d hours (%d expected)"), + nBlocks, SPAN_HOURS, BLOCKS_EXPECTED); + } + if (!strWarning.empty()) + { + strMiscWarning = strWarning; + CAlert::Notify(strWarning, true); + lastAlertTime = now; + } +} + static int64_t nTimeVerify = 0; static int64_t nTimeConnect = 0; static int64_t nTimeIndex = 0; |