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.
This commit is contained in:
BtcDrak
2016-06-14 12:26:59 +01:00
committed by lateminer
parent 694c451c7e
commit 556187e3f8
5 changed files with 2 additions and 160 deletions

View File

@@ -39,7 +39,6 @@ BITCOIN_TESTS =\
test/arith_uint256_tests.cpp \
test/scriptnum10.h \
test/addrman_tests.cpp \
test/alert_tests.cpp \
test/allocator_tests.cpp \
test/base32_tests.cpp \
test/base64_tests.cpp \

View File

@@ -1450,19 +1450,6 @@ bool AppInit2(Config& config, boost::thread_group& threadGroup, CScheduler& sche
InitRespendFilter();
StartNode(threadGroup, scheduler);
// Monitor the chain, and alert if we get blocks much quicker or slower than expected
// The "bad chain alert" scheduler has been disabled because the current system gives far
// too many false positives, such that users are starting to ignore them.
// This code will be disabled for 0.12.1 while a fix is deliberated in #7568
// this was discussed in the IRC meeting on 2016-03-31.
//
// --- disabled ---
//int64_t nTargetSpacing = Params().GetConsensus().nTargetSpacing;
//CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload,
// boost::ref(cs_main), boost::cref(pindexBestHeader), nTargetSpacing);
//scheduler.scheduleEvery(f, nTargetSpacing);
// --- end disabled ---
// Generate coins in the background
GenerateBitcoins(GetBoolArg("-gen", DEFAULT_GENERATE), GetArg("-genproclimit", DEFAULT_GENERATE_THREADS), chainparams);
#ifdef ENABLE_WALLET
@@ -1470,7 +1457,8 @@ bool AppInit2(Config& config, boost::thread_group& threadGroup, CScheduler& sche
if (!GetBoolArg("-staking", true))
LogPrintf("Staking disabled\n");
else if (pwalletMain)
threadGroup.create_thread(boost::bind(&ThreadStakeMiner, pwalletMain, chainparams));
threadGroup.create_thread(boost::bind(&ThreadStakeMiner, pwalletMain, chainparams));
// ********************************************************* Step 12: finished
#endif
SetRPCWarmupFinished();

View File

@@ -2496,68 +2496,6 @@ 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 CBlockIndex *const &bestHeader,
int64_t nTargetSpacing)
{
if (bestHeader == NULL || 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 / nTargetSpacing;
boost::math::poisson_distribution<double> poisson(BLOCKS_EXPECTED);
std::string strWarning;
int64_t startTime = GetAdjustedTime()-SPAN_SECONDS;
LOCK(cs);
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 sync'ed
}
// 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;
AlertNotify(strWarning, true);
lastAlertTime = now;
}
}
// Protected by cs_main
static VersionBitsCache versionbitscache;

View File

@@ -241,8 +241,6 @@ bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto);
/** Run an instance of the script checking thread */
void ThreadScriptCheck();
/** Try to detect Partition (network isolation) attacks against us */
void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nTargetSpacing);
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
bool IsInitialBlockDownload();
/** Format a string that describes several potential problems detected by the core.

View File

@@ -1,81 +0,0 @@
// Copyright (c) 2013-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
// Unit tests for alert system
#include "chainparams.h"
#include "main.h" // For PartitionCheck
#include "util.h"
#include "utilstrencodings.h"
#include "test/test_bitcoin.h"
#include <boost/test/unit_test.hpp>
BOOST_FIXTURE_TEST_SUITE(Alert_tests, TestingSetup)
static bool falseFunc() { return false; }
BOOST_AUTO_TEST_CASE(PartitionAlert)
{
// Test PartitionCheck
CCriticalSection csDummy;
CBlockIndex indexDummy[100];
CChainParams& params = Params(CBaseChainParams::MAIN);
int64_t nTargetSpacing = params.GetConsensus().nTargetSpacing;
// Generate fake blockchain timestamps relative to
// an arbitrary time:
int64_t now = 1427379054;
SetMockTime(now);
for (int i = 0; i < 100; i++)
{
indexDummy[i].phashBlock = NULL;
if (i == 0) indexDummy[i].pprev = NULL;
else indexDummy[i].pprev = &indexDummy[i-1];
indexDummy[i].nHeight = i;
indexDummy[i].nTime = now - (100-i)*nTargetSpacing;
// Other members don't matter, the partition check code doesn't
// use them
}
strMiscWarning = "";
// Test 1: chain with blocks every nTargetSpacing seconds,
// as normal, no worries:
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nTargetSpacing);
BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning);
// Test 2: go 3.5 hours without a block, expect a warning:
now += 3*60*60+30*60;
SetMockTime(now);
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nTargetSpacing);
BOOST_CHECK(!strMiscWarning.empty());
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
strMiscWarning = "";
// Test 3: test the "partition alerts only go off once per day"
// code:
now += 60*10;
SetMockTime(now);
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nTargetSpacing);
BOOST_CHECK(strMiscWarning.empty());
// Test 4: get 2.5 times as many blocks as expected:
now += 60*60*24; // Pretend it is a day later
SetMockTime(now);
int64_t quickSpacing = nTargetSpacing*2/5;
for (int i = 0; i < 100; i++) // Tweak chain timestamps:
indexDummy[i].nTime = now - (100-i)*quickSpacing;
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nTargetSpacing);
BOOST_CHECK(!strMiscWarning.empty());
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
strMiscWarning = "";
SetMockTime(0);
}
BOOST_AUTO_TEST_SUITE_END()