Skip to content

Commit

Permalink
Use best header chain timestamps to detect partitioning
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gavinandresen committed Jun 8, 2015
1 parent 55294a9 commit 65b9454
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/init.cpp
Expand Up @@ -1396,7 +1396,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);

#ifdef ENABLE_WALLET
Expand Down
16 changes: 10 additions & 6 deletions src/main.cpp
Expand Up @@ -1711,9 +1711,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();
Expand All @@ -1729,10 +1730,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);
Expand Down
2 changes: 1 addition & 1 deletion src/main.h
Expand Up @@ -186,7 +186,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 */
Expand Down
10 changes: 4 additions & 6 deletions src/test/alert_tests.cpp
Expand Up @@ -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;
Expand All @@ -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 = "";
Expand All @@ -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:
Expand All @@ -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 = "";
Expand Down

0 comments on commit 65b9454

Please sign in to comment.