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:
Homu 2021-02-18 18:46:40 +00:00
commit e83ecc1dcb
4 changed files with 0 additions and 186 deletions

View File

@ -1724,12 +1724,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& 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
// Generate coins in the background
GenerateBitcoins(GetBoolArg("-gen", DEFAULT_GENERATE), GetArg("-genproclimit", DEFAULT_GENERATE_THREADS), chainparams);

View File

@ -2646,84 +2646,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)(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 nTimeConnect = 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);
/** Run an instance of the script checking thread */
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) */
bool IsInitialBlockDownload(const Consensus::Params& params);
/** Format a string that describes several potential problems detected by the core */

View File

@ -13,7 +13,6 @@
#include "fs.h"
#include "test/data/alertTests.raw.h"
#include "main.h"
#include "rpc/protocol.h"
#include "rpc/server.h"
#include "serialize.h"
@ -409,101 +408,6 @@ BOOST_AUTO_TEST_CASE(AlertDisablesRPC)
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()
#endif