|
|
@ -28,6 +28,7 @@ |
|
|
|
#include <boost/algorithm/string/replace.hpp> |
|
|
|
#include <boost/algorithm/string/replace.hpp> |
|
|
|
#include <boost/filesystem.hpp> |
|
|
|
#include <boost/filesystem.hpp> |
|
|
|
#include <boost/filesystem/fstream.hpp> |
|
|
|
#include <boost/filesystem/fstream.hpp> |
|
|
|
|
|
|
|
#include <boost/math/distributions/poisson.hpp> |
|
|
|
#include <boost/thread.hpp> |
|
|
|
#include <boost/thread.hpp> |
|
|
|
|
|
|
|
|
|
|
|
using namespace std; |
|
|
|
using namespace std; |
|
|
@ -1685,6 +1686,64 @@ void ThreadScriptCheck() { |
|
|
|
scriptcheckqueue.Thread(); |
|
|
|
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 nTimeVerify = 0; |
|
|
|
static int64_t nTimeConnect = 0; |
|
|
|
static int64_t nTimeConnect = 0; |
|
|
|
static int64_t nTimeIndex = 0; |
|
|
|
static int64_t nTimeIndex = 0; |
|
|
|