Auto merge of #4972 - LarryRuane:remove-PartitionCheck, r=str4d
Remove bad chain alert partition check (cherry picked from https://github.com/bitcoin/bitcoin/pull/8275 commit ab8be98fdb25b678a8cd7e89adf06d1b1f6bdd62), original commit message: As per meeting 2016-03-31 https://bitcoincore.org/en/meetings/2016/03/31/#bad-chain-alerts The partition checker was producing huge number of false-positives and was disabled in 0.12.1 on the understanding it would either be fixed in 0.13 or removed entirely from master if not.
This commit is contained in:
commit
e83ecc1dcb
|
@ -1724,12 +1724,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
|
|
||||||
StartNode(threadGroup, scheduler);
|
StartNode(threadGroup, scheduler);
|
||||||
|
|
||||||
// Monitor the chain every minute, and alert if we get blocks much quicker or slower than expected.
|
|
||||||
CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload,
|
|
||||||
boost::cref(chainparams.GetConsensus()),
|
|
||||||
boost::ref(cs_main), boost::cref(pindexBestHeader));
|
|
||||||
scheduler.scheduleEvery(f, 60);
|
|
||||||
|
|
||||||
#ifdef ENABLE_MINING
|
#ifdef ENABLE_MINING
|
||||||
// Generate coins in the background
|
// Generate coins in the background
|
||||||
GenerateBitcoins(GetBoolArg("-gen", DEFAULT_GENERATE), GetArg("-genproclimit", DEFAULT_GENERATE_THREADS), chainparams);
|
GenerateBitcoins(GetBoolArg("-gen", DEFAULT_GENERATE), GetArg("-genproclimit", DEFAULT_GENERATE_THREADS), chainparams);
|
||||||
|
|
78
src/main.cpp
78
src/main.cpp
|
@ -2646,84 +2646,6 @@ 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)(const Consensus::Params&),
|
|
||||||
const Consensus::Params& consensusParams,
|
|
||||||
CCriticalSection& cs,
|
|
||||||
const CBlockIndex *const &bestHeader)
|
|
||||||
{
|
|
||||||
if (bestHeader == NULL || initialDownloadCheck(consensusParams)) return;
|
|
||||||
|
|
||||||
static int64_t lastAlertTime = 0;
|
|
||||||
int64_t now = GetTime();
|
|
||||||
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;
|
|
||||||
|
|
||||||
LOCK(cs);
|
|
||||||
|
|
||||||
int BLOCKS_EXPECTED;
|
|
||||||
// TODO: This can be simplified when the Blossom activation height is set
|
|
||||||
int nBlossomBlocks = consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight == Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT ?
|
|
||||||
0 : std::max(0, bestHeader->nHeight - consensusParams.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight);
|
|
||||||
int blossomBlockTime = nBlossomBlocks * consensusParams.nPostBlossomPowTargetSpacing;
|
|
||||||
// If the span period includes Blossom activation, adjust the number of expected blocks.
|
|
||||||
if (blossomBlockTime < SPAN_SECONDS) {
|
|
||||||
// If there are 0 blossomBlocks the following is equivalent to
|
|
||||||
// BLOCKS_EXPECTED = SPAN_SECONDS / consensusParams.nPreBlossomPowTargetSpacing
|
|
||||||
BLOCKS_EXPECTED = nBlossomBlocks + (SPAN_SECONDS - blossomBlockTime) / consensusParams.nPreBlossomPowTargetSpacing;
|
|
||||||
} else {
|
|
||||||
BLOCKS_EXPECTED = SPAN_SECONDS / consensusParams.nPostBlossomPowTargetSpacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::math::poisson_distribution<double> poisson(BLOCKS_EXPECTED);
|
|
||||||
|
|
||||||
std::string strWarning;
|
|
||||||
int64_t startTime = GetTime() - SPAN_SECONDS;
|
|
||||||
|
|
||||||
const CBlockIndex* i = bestHeader;
|
|
||||||
int nBlocks = 0;
|
|
||||||
while (i->GetBlockTime() >= startTime) {
|
|
||||||
++nBlocks;
|
|
||||||
i = i->pprev;
|
|
||||||
if (i == NULL) return; // Ran out of chain, we must not be fully synced
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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())
|
|
||||||
{
|
|
||||||
SetMiscWarning(strWarning, GetTime());
|
|
||||||
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;
|
||||||
|
|
|
@ -255,12 +255,6 @@ bool ProcessMessages(const CChainParams& chainparams, CNode* pfrom);
|
||||||
bool SendMessages(const Consensus::Params& params, CNode* pto, bool fSendTrickle);
|
bool SendMessages(const Consensus::Params& params, CNode* pto, bool fSendTrickle);
|
||||||
/** Run an instance of the script checking thread */
|
/** Run an instance of the script checking thread */
|
||||||
void ThreadScriptCheck();
|
void ThreadScriptCheck();
|
||||||
/** Try to detect Partition (network isolation) attacks against us */
|
|
||||||
void PartitionCheck(
|
|
||||||
bool (*initialDownloadCheck)(const Consensus::Params&),
|
|
||||||
const Consensus::Params& params,
|
|
||||||
CCriticalSection& cs,
|
|
||||||
const CBlockIndex *const &bestHeader);
|
|
||||||
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
|
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
|
||||||
bool IsInitialBlockDownload(const Consensus::Params& params);
|
bool IsInitialBlockDownload(const Consensus::Params& params);
|
||||||
/** Format a string that describes several potential problems detected by the core */
|
/** Format a string that describes several potential problems detected by the core */
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "test/data/alertTests.raw.h"
|
#include "test/data/alertTests.raw.h"
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
#include "rpc/protocol.h"
|
#include "rpc/protocol.h"
|
||||||
#include "rpc/server.h"
|
#include "rpc/server.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
|
@ -409,101 +408,6 @@ BOOST_AUTO_TEST_CASE(AlertDisablesRPC)
|
||||||
mapAlerts.clear();
|
mapAlerts.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool falseFunc(const Consensus::Params&) { return false; }
|
|
||||||
|
|
||||||
void PartitionAlertTestImpl(const Consensus::Params& params, int startTime, int expectedTotal, int expectedSlow, int expectedFast)
|
|
||||||
{
|
|
||||||
// Test PartitionCheck
|
|
||||||
CCriticalSection csDummy;
|
|
||||||
CBlockIndex indexDummy[800];
|
|
||||||
|
|
||||||
// Generate fake blockchain timestamps relative to
|
|
||||||
// an arbitrary time:
|
|
||||||
int64_t start = startTime;
|
|
||||||
for (int i = 0; i < 800; i++)
|
|
||||||
{
|
|
||||||
indexDummy[i].phashBlock = NULL;
|
|
||||||
indexDummy[i].pprev = i ? &indexDummy[i-1] : NULL;
|
|
||||||
indexDummy[i].nHeight = i;
|
|
||||||
indexDummy[i].nTime = i ? indexDummy[i - 1].nTime + params.PoWTargetSpacing(i) : start;
|
|
||||||
// Other members don't matter, the partition check code doesn't
|
|
||||||
// use them
|
|
||||||
}
|
|
||||||
int64_t now = indexDummy[799].nTime + params.PoWTargetSpacing(800);
|
|
||||||
SetMockTime(now);
|
|
||||||
|
|
||||||
// Test 1: chain with blocks every nPowTargetSpacing seconds,
|
|
||||||
// as normal, no worries:
|
|
||||||
SetMiscWarning("", 0);
|
|
||||||
PartitionCheck(falseFunc, params, csDummy, &indexDummy[799]);
|
|
||||||
BOOST_CHECK_EQUAL("", GetMiscWarning().first);
|
|
||||||
|
|
||||||
// Test 2: go 3.5 hours without a block, expect a warning:
|
|
||||||
now += 3*60*60+30*60;
|
|
||||||
SetMockTime(now);
|
|
||||||
SetMiscWarning("", 0);
|
|
||||||
PartitionCheck(falseFunc, params, csDummy, &indexDummy[799]);
|
|
||||||
std::string expectedSlowErr = strprintf("WARNING: Check your network connection, %d blocks received in the last 4 hours (%d expected)", expectedSlow, expectedTotal);
|
|
||||||
auto warning = GetMiscWarning();
|
|
||||||
// advance 5 seconds so alert time will be in the past
|
|
||||||
SetMockTime(now + 5);
|
|
||||||
BOOST_CHECK_EQUAL(GetTime() - 5, warning.second);
|
|
||||||
BOOST_CHECK_EQUAL(expectedSlowErr, warning.first);
|
|
||||||
BOOST_TEST_MESSAGE(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", warning.second) + " - Got alert text: " + warning.first);
|
|
||||||
|
|
||||||
// Test 3: test the "partition alerts only go off once per day"
|
|
||||||
// code:
|
|
||||||
now += 60*10;
|
|
||||||
SetMockTime(now);
|
|
||||||
SetMiscWarning("", 0);
|
|
||||||
PartitionCheck(falseFunc, params, csDummy, &indexDummy[799]);
|
|
||||||
BOOST_CHECK_EQUAL("", GetMiscWarning().first);
|
|
||||||
|
|
||||||
// Test 4: get 2.5 times as many blocks as expected:
|
|
||||||
start = now + 60*60*24; // Pretend it is a day later
|
|
||||||
for (int i = 0; i < 800; i++) {
|
|
||||||
// Tweak chain timestamps:
|
|
||||||
indexDummy[i].nTime = i ? indexDummy[i - 1].nTime + params.PoWTargetSpacing(i) * 2/5 : start;
|
|
||||||
}
|
|
||||||
now = indexDummy[799].nTime + params.PoWTargetSpacing(0) * 2/5;
|
|
||||||
SetMockTime(now);
|
|
||||||
|
|
||||||
SetMiscWarning("", 0);
|
|
||||||
PartitionCheck(falseFunc, params, csDummy, &indexDummy[799]);
|
|
||||||
std::string expectedFastErr = strprintf("WARNING: Abnormally high number of blocks generated, %d blocks received in the last 4 hours (%d expected)", expectedFast, expectedTotal);
|
|
||||||
warning = GetMiscWarning();
|
|
||||||
// advance 5 seconds so alert time will be in the past
|
|
||||||
SetMockTime(now + 5);
|
|
||||||
BOOST_CHECK_EQUAL(GetTime() - 5, warning.second);
|
|
||||||
BOOST_CHECK_EQUAL(expectedFastErr, warning.first);
|
|
||||||
BOOST_TEST_MESSAGE(DateTimeStrFormat("%Y-%m-%d %H:%M:%S", warning.second) + " - Got alert text: " + warning.first);
|
|
||||||
SetMiscWarning("", 0);
|
|
||||||
|
|
||||||
SetMockTime(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(PartitionAlert)
|
|
||||||
{
|
|
||||||
CChainParams& params = Params(CBaseChainParams::MAIN);
|
|
||||||
PartitionAlertTestImpl(params.GetConsensus(), 1000000000, 96, 12, 240);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(PartitionAlertBlossomOnly)
|
|
||||||
{
|
|
||||||
PartitionAlertTestImpl(RegtestActivateBlossom(false).GetConsensus(), 1500000000, 96 * 2, 12 * 2, 240 * 2);
|
|
||||||
RegtestDeactivateBlossom();
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(PartitionAlertBlossomActivates)
|
|
||||||
{
|
|
||||||
// 48 pre blossom blocks, 96 blossom blocks will take 48 * 150s + 96 * 75s = 4hrs
|
|
||||||
// in the slow case, all of the blocks will be blossom blocks
|
|
||||||
// in the fast case, 96 blocks will be blossom => 96 * 75s * 2/5 = 2880s spent on blossom
|
|
||||||
// => (14400 - 2880) / (150 * 2/5) = 11520 / 60 = 192 pre blossom blocks
|
|
||||||
PartitionAlertTestImpl(RegtestActivateBlossom(false, 799 - 96).GetConsensus(), 2000000000, 144, 12 * 2, 192 + 96);
|
|
||||||
RegtestDeactivateBlossom();
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue