Browse Source

Merge pull request #6256

65b9454 Use best header chain timestamps to detect partitioning (Gavin Andresen)
0.13
Wladimir J. van der Laan 10 years ago
parent
commit
8ccc07c077
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 2
      src/init.cpp
  2. 16
      src/main.cpp
  3. 2
      src/main.h
  4. 10
      src/test/alert_tests.cpp

2
src/init.cpp

@ -1425,7 +1425,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

@ -1723,9 +1723,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();
@ -1741,10 +1742,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);

2
src/main.h

@ -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 */

10
src/test/alert_tests.cpp

@ -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…
Cancel
Save