Remove bad chain alert partition check

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.

(cherry picked from commit ab8be98fdb25b678a8cd7e89adf06d1b1f6bdd62)
This commit is contained in:
BtcDrak 2016-06-14 12:26:59 +01:00 committed by Larry Ruane
parent a960e896dd
commit fa8d2a45bb
4 changed files with 0 additions and 186 deletions

View File

@ -1718,12 +1718,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);

View File

@ -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;

View File

@ -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 */

View File

@ -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