diff --git a/src/init.cpp b/src/init.cpp index 15c8e9906..3e0dea951 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1718,12 +1718,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); diff --git a/src/main.cpp b/src/main.cpp index e720f8c90..dc05c8edf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 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; diff --git a/src/main.h b/src/main.h index bca161193..155b6e893 100644 --- a/src/main.h +++ b/src/main.h @@ -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 */ diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 65f459654..ec428f451 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -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