diff options
author | Gavin Andresen <gavinandresen@gmail.com> | 2015-06-08 16:34:58 -0400 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2015-06-15 10:34:07 +0200 |
commit | fce474c9dfa1fd3f98f14f7c2866a6001b21ac9a (patch) | |
tree | 19ffbac3670246fabbf1292ef9f96d4cba9ad66b | |
parent | 4d9c7fe61dd0e3e9443fd16c8ebbb3b119f7cff6 (diff) |
Use best header chain timestamps to detect partitioning
The partition checking code was using chainActive timestamps
to detect partitioning; with headers-first syncing, it should use
(and with this pull request, does use) pIndexBestHeader timestamps.
Fixes issue #6251
Github-Pull: #6256
Rebased-From: 65b94545036ae6e38e79e9c7166a3ba1ddb83f66
-rw-r--r-- | src/init.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 16 | ||||
-rw-r--r-- | src/main.h | 2 | ||||
-rw-r--r-- | src/test/alert_tests.cpp | 10 |
4 files changed, 16 insertions, 14 deletions
diff --git a/src/init.cpp b/src/init.cpp index eeb3358a12..3451632f1b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1420,7 +1420,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // Monitor the chain, and alert if we get blocks much quicker or slower than expected int64_t nPowTargetSpacing = Params().GetConsensus().nPowTargetSpacing; CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload, - boost::ref(cs_main), boost::cref(chainActive), nPowTargetSpacing); + boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing); scheduler.scheduleEvery(f, nPowTargetSpacing); #endif #ifdef ENABLE_WALLET diff --git a/src/main.cpp b/src/main.cpp index ae9e57557f..e08c3df9f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1712,9 +1712,10 @@ void ThreadScriptCheck() { // we're being fed a bad chain (blocks being generated much // too slowly or too quickly). // -void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CChain& chain, int64_t nPowTargetSpacing) +void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, + int64_t nPowTargetSpacing) { - if (initialDownloadCheck()) return; + if (bestHeader == NULL || initialDownloadCheck()) return; static int64_t lastAlertTime = 0; int64_t now = GetAdjustedTime(); @@ -1730,10 +1731,13 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const int64_t startTime = GetAdjustedTime()-SPAN_SECONDS; LOCK(cs); - int h = chain.Height(); - while (h > 0 && chain[h]->GetBlockTime() >= startTime) - --h; - int nBlocks = chain.Height()-h; + 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); diff --git a/src/main.h b/src/main.h index 696d57442b..58c717c277 100644 --- a/src/main.h +++ b/src/main.h @@ -189,7 +189,7 @@ bool SendMessages(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)(), CCriticalSection& cs, const CChain& chain, int64_t nPowTargetSpacing); +void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const CBlockIndex *const &bestHeader, int64_t nPowTargetSpacing); /** 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 */ diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 22cb475e02..38dcc6023c 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -201,7 +201,6 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) { // Test PartitionCheck CCriticalSection csDummy; - CChain chainDummy; CBlockIndex indexDummy[100]; CChainParams& params = Params(CBaseChainParams::MAIN); int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; @@ -220,17 +219,16 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) // Other members don't matter, the partition check code doesn't // use them } - chainDummy.SetTip(&indexDummy[99]); // Test 1: chain with blocks every nPowTargetSpacing seconds, // as normal, no worries: - PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); BOOST_CHECK(strMiscWarning.empty()); // Test 2: go 3.5 hours without a block, expect a warning: now += 3*60*60+30*60; SetMockTime(now); - PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); BOOST_CHECK(!strMiscWarning.empty()); BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); strMiscWarning = ""; @@ -239,7 +237,7 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) // code: now += 60*10; SetMockTime(now); - PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); BOOST_CHECK(strMiscWarning.empty()); // Test 4: get 2.5 times as many blocks as expected: @@ -248,7 +246,7 @@ BOOST_AUTO_TEST_CASE(PartitionAlert) int64_t quickSpacing = nPowTargetSpacing*2/5; for (int i = 0; i < 100; i++) // Tweak chain timestamps: indexDummy[i].nTime = now - (100-i)*quickSpacing; - PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); BOOST_CHECK(!strMiscWarning.empty()); BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); strMiscWarning = ""; |