Skip to content

Commit

Permalink
Ban forked peers who are stuck in a getblocks loop.
Browse files Browse the repository at this point in the history
  • Loading branch information
dooglus committed Jul 11, 2015
1 parent 196e127 commit c351f77
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3306,6 +3306,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (!IsInitialBlockDownload())
Checkpoints::AskForPendingSyncCheckpoint(pfrom);

// CDC v1.3.3: reset counts to detect forked peers
pfrom->nHighestHeightRequested = 0; /* CDC v1.3.3 */
pfrom->nHeightBackwards = 0; /* CDC v1.3.3 */
pfrom->nHeightBackwardsLast = GetTime(); /* CDC v1.3.3 */

pfrom->nTimeOffset = nTime - GetTime();

if (GetBoolArg("-synctime", true))
Expand Down Expand Up @@ -3482,6 +3487,31 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pindex = pindex->pnext;
int nLimit = 1000;
LogPrint("net", "getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString(), nLimit);

// CDC v1.3.3: detect when peers go backwards in the height of blocks that they request, which is a sign of a forked client stuck in an endless loop. if this happens too many times, ban the peer.
if (pindex) // only act when an explicit height is requested
{
if (pindex->nHeight > pfrom->nHighestHeightRequested)
{
pfrom->nHighestHeightRequested = pindex->nHeight;
} else {
if (pindex->nHeight < (pfrom->nHighestHeightRequested - 500)) // peer has gone backwards in height when requesting blocks
{
if (pfrom->nHeightBackwardsLast < (GetTime() - 3600)) pfrom->nHeightBackwards = 0; // reset penalty count if last backward leap was more than an hour ago
pfrom->nHeightBackwards++;
LogPrintf("peer %s: leap backwards in height request, from max %d to current %d. penalty=%d/100\n", pfrom->addr.ToString().c_str(), pfrom->nHighestHeightRequested, pindex->nHeight,
pfrom->nHeightBackwards);
pfrom->nHeightBackwardsLast = GetTime();
pfrom->nHighestHeightRequested = pindex->nHeight; // reset maximum to height of current request
}
}
if (pfrom->nHeightBackwards >= 100)
{
pfrom->Misbehaving(100);
return error("peer %s: sync repeatedly leaping backwards to lower height", pfrom->addr.ToString().c_str());
}
}

for (; pindex; pindex = pindex->pnext)
{
if (pindex->GetBlockHash() == hashStop)
Expand Down
6 changes: 6 additions & 0 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ class CNode
int64_t nLastSend;
int64_t nLastRecv;
int64_t nTimeConnected;
int nHighestHeightRequested; /* CDC v1.3.3 */
int nHeightBackwards; /* CDC v1.3.3 */
int64 nHeightBackwardsLast; /* CDC v1.3.3 */
CAddress addr;
std::string addrName;
CService addrLocal;
Expand Down Expand Up @@ -260,6 +263,9 @@ class CNode
nLastRecv = 0;
nSendBytes = 0;
nRecvBytes = 0;
nHighestHeightRequested = 0; /* CDC v1.3.3 */
nHeightBackwards = 0; /* CDC v1.3.3 */
nHeightBackwardsLast = GetTime(); /* CDC v1.3.3 */
nTimeConnected = GetTime();
addr = addrIn;
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
Expand Down

0 comments on commit c351f77

Please sign in to comment.