aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp50
1 files changed, 43 insertions, 7 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 5e8a6d50f..60c597797 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -276,6 +276,8 @@ struct CNodeState {
CBlockIndex *pindexLastCommonBlock;
//! The best header we have sent our peer.
CBlockIndex *pindexBestHeaderSent;
+ //! Length of current-streak of unconnecting headers announcements
+ int nUnconnectingHeaders;
//! Whether we've started headers synchronization with this peer.
bool fSyncStarted;
//! Since when we're stalling block download progress (in microseconds), or 0.
@@ -304,6 +306,7 @@ struct CNodeState {
hashLastUnknownBlock.SetNull();
pindexLastCommonBlock = NULL;
pindexBestHeaderSent = NULL;
+ nUnconnectingHeaders = 0;
fSyncStarted = false;
nStallingSince = 0;
nDownloadingSince = 0;
@@ -691,8 +694,8 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c
// have been mined or received.
// 100 orphans, each of which is at most 99,999 bytes big is
// at most 10 megabytes of orphans and somewhat more byprev index (in the worst case):
- unsigned int sz = GetTransactionCost(tx);
- if (sz >= MAX_STANDARD_TX_COST)
+ unsigned int sz = GetTransactionWeight(tx);
+ if (sz >= MAX_STANDARD_TX_WEIGHT)
{
LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString());
return false;
@@ -3593,13 +3596,13 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
}
// After the coinbase witness nonce and commitment are verified,
- // we can check if the block cost passes (before we've checked the
- // coinbase witness, it would be possible for the cost to be too
+ // we can check if the block weight passes (before we've checked the
+ // coinbase witness, it would be possible for the weight to be too
// large by filling up the coinbase witness, which doesn't change
// the block hash, so we couldn't mark the block as permanently
// failed).
- if (GetBlockCost(block) > MAX_BLOCK_COST) {
- return state.DoS(100, error("ContextualCheckBlock(): cost limit failed"), REJECT_INVALID, "bad-blk-cost");
+ if (GetBlockWeight(block) > MAX_BLOCK_WEIGHT) {
+ return state.DoS(100, error("ContextualCheckBlock(): weight limit failed"), REJECT_INVALID, "bad-blk-weight");
}
return true;
@@ -5773,6 +5776,35 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true;
}
+ CNodeState *nodestate = State(pfrom->GetId());
+
+ // If this looks like it could be a block announcement (nCount <
+ // MAX_BLOCKS_TO_ANNOUNCE), use special logic for handling headers that
+ // don't connect:
+ // - Send a getheaders message in response to try to connect the chain.
+ // - The peer can send up to MAX_UNCONNECTING_HEADERS in a row that
+ // don't connect before giving DoS points
+ // - Once a headers message is received that is valid and does connect,
+ // nUnconnectingHeaders gets reset back to 0.
+ if (mapBlockIndex.find(headers[0].hashPrevBlock) == mapBlockIndex.end() && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
+ nodestate->nUnconnectingHeaders++;
+ pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256());
+ LogPrint("net", "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
+ headers[0].GetHash().ToString(),
+ headers[0].hashPrevBlock.ToString(),
+ pindexBestHeader->nHeight,
+ pfrom->id, nodestate->nUnconnectingHeaders);
+ // Set hashLastUnknownBlock for this peer, so that if we
+ // eventually get the headers - even from a different peer -
+ // we can use this peer to download.
+ UpdateBlockAvailability(pfrom->GetId(), headers.back().GetHash());
+
+ if (nodestate->nUnconnectingHeaders % MAX_UNCONNECTING_HEADERS == 0) {
+ Misbehaving(pfrom->GetId(), 20);
+ }
+ return true;
+ }
+
CBlockIndex *pindexLast = NULL;
BOOST_FOREACH(const CBlockHeader& header, headers) {
CValidationState state;
@@ -5790,6 +5822,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
+ if (nodestate->nUnconnectingHeaders > 0) {
+ LogPrint("net", "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders);
+ }
+ nodestate->nUnconnectingHeaders = 0;
+
assert(pindexLast);
UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash());
@@ -5802,7 +5839,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus());
- CNodeState *nodestate = State(pfrom->GetId());
// If this set of headers is valid and ends in a block with at least as
// much work as our tip, download as much as possible.
if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && chainActive.Tip()->nChainWork <= pindexLast->nChainWork) {