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
This commit is contained in:
parent
55294a9fb6
commit
65b9454503
4 changed files with 16 additions and 14 deletions
|
@ -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
|
// Monitor the chain, and alert if we get blocks much quicker or slower than expected
|
||||||
int64_t nPowTargetSpacing = Params().GetConsensus().nPowTargetSpacing;
|
int64_t nPowTargetSpacing = Params().GetConsensus().nPowTargetSpacing;
|
||||||
CScheduler::Function f = boost::bind(&PartitionCheck, &IsInitialBlockDownload,
|
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);
|
scheduler.scheduleEvery(f, nPowTargetSpacing);
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
|
|
16
src/main.cpp
16
src/main.cpp
|
@ -1711,9 +1711,10 @@ void ThreadScriptCheck() {
|
||||||
// we're being fed a bad chain (blocks being generated much
|
// we're being fed a bad chain (blocks being generated much
|
||||||
// too slowly or too quickly).
|
// 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;
|
static int64_t lastAlertTime = 0;
|
||||||
int64_t now = GetAdjustedTime();
|
int64_t now = GetAdjustedTime();
|
||||||
|
@ -1729,10 +1730,13 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
|
||||||
int64_t startTime = GetAdjustedTime()-SPAN_SECONDS;
|
int64_t startTime = GetAdjustedTime()-SPAN_SECONDS;
|
||||||
|
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
int h = chain.Height();
|
const CBlockIndex* i = bestHeader;
|
||||||
while (h > 0 && chain[h]->GetBlockTime() >= startTime)
|
int nBlocks = 0;
|
||||||
--h;
|
while (i->GetBlockTime() >= startTime) {
|
||||||
int nBlocks = chain.Height()-h;
|
++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?
|
// How likely is it to find that many by chance?
|
||||||
double p = boost::math::pdf(poisson, nBlocks);
|
double p = boost::math::pdf(poisson, nBlocks);
|
||||||
|
|
|
@ -186,7 +186,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle);
|
||||||
/** Run an instance of the script checking thread */
|
/** Run an instance of the script checking thread */
|
||||||
void ThreadScriptCheck();
|
void ThreadScriptCheck();
|
||||||
/** Try to detect Partition (network isolation) attacks against us */
|
/** 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) */
|
/** Check whether we are doing an initial block download (synchronizing from disk or network) */
|
||||||
bool IsInitialBlockDownload();
|
bool IsInitialBlockDownload();
|
||||||
/** Format a string that describes several potential problems detected by the core */
|
/** Format a string that describes several potential problems detected by the core */
|
||||||
|
|
|
@ -201,7 +201,6 @@ BOOST_AUTO_TEST_CASE(PartitionAlert)
|
||||||
{
|
{
|
||||||
// Test PartitionCheck
|
// Test PartitionCheck
|
||||||
CCriticalSection csDummy;
|
CCriticalSection csDummy;
|
||||||
CChain chainDummy;
|
|
||||||
CBlockIndex indexDummy[100];
|
CBlockIndex indexDummy[100];
|
||||||
CChainParams& params = Params(CBaseChainParams::MAIN);
|
CChainParams& params = Params(CBaseChainParams::MAIN);
|
||||||
int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing;
|
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
|
// Other members don't matter, the partition check code doesn't
|
||||||
// use them
|
// use them
|
||||||
}
|
}
|
||||||
chainDummy.SetTip(&indexDummy[99]);
|
|
||||||
|
|
||||||
// Test 1: chain with blocks every nPowTargetSpacing seconds,
|
// Test 1: chain with blocks every nPowTargetSpacing seconds,
|
||||||
// as normal, no worries:
|
// as normal, no worries:
|
||||||
PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing);
|
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
|
||||||
BOOST_CHECK(strMiscWarning.empty());
|
BOOST_CHECK(strMiscWarning.empty());
|
||||||
|
|
||||||
// Test 2: go 3.5 hours without a block, expect a warning:
|
// Test 2: go 3.5 hours without a block, expect a warning:
|
||||||
now += 3*60*60+30*60;
|
now += 3*60*60+30*60;
|
||||||
SetMockTime(now);
|
SetMockTime(now);
|
||||||
PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing);
|
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
|
||||||
BOOST_CHECK(!strMiscWarning.empty());
|
BOOST_CHECK(!strMiscWarning.empty());
|
||||||
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
|
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
|
||||||
strMiscWarning = "";
|
strMiscWarning = "";
|
||||||
|
@ -239,7 +237,7 @@ BOOST_AUTO_TEST_CASE(PartitionAlert)
|
||||||
// code:
|
// code:
|
||||||
now += 60*10;
|
now += 60*10;
|
||||||
SetMockTime(now);
|
SetMockTime(now);
|
||||||
PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing);
|
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
|
||||||
BOOST_CHECK(strMiscWarning.empty());
|
BOOST_CHECK(strMiscWarning.empty());
|
||||||
|
|
||||||
// Test 4: get 2.5 times as many blocks as expected:
|
// 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;
|
int64_t quickSpacing = nPowTargetSpacing*2/5;
|
||||||
for (int i = 0; i < 100; i++) // Tweak chain timestamps:
|
for (int i = 0; i < 100; i++) // Tweak chain timestamps:
|
||||||
indexDummy[i].nTime = now - (100-i)*quickSpacing;
|
indexDummy[i].nTime = now - (100-i)*quickSpacing;
|
||||||
PartitionCheck(falseFunc, csDummy, chainDummy, nPowTargetSpacing);
|
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
|
||||||
BOOST_CHECK(!strMiscWarning.empty());
|
BOOST_CHECK(!strMiscWarning.empty());
|
||||||
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
|
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
|
||||||
strMiscWarning = "";
|
strMiscWarning = "";
|
||||||
|
|
Loading…
Reference in a new issue