Fix memory DoS
This commit is contained in:
40
src/main.cpp
40
src/main.cpp
@@ -7320,6 +7320,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
}
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
const uint256* best_block{nullptr};
|
||||
|
||||
std::vector<CInv> vToFetch;
|
||||
|
||||
@@ -7339,35 +7341,31 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
if (inv.type == MSG_BLOCK) {
|
||||
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
|
||||
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
|
||||
// First request the headers preceding the announced block. In the normal fully-synced
|
||||
// case where a new block is announced that succeeds the current tip (no reorganization),
|
||||
// there are no such headers.
|
||||
// Secondly, and only when we are close to being synced, we request the announced block directly,
|
||||
// to avoid an extra round-trip. Note that we must *first* ask for the headers, so by the
|
||||
// time the block arrives, the header chain leading up to it is already validated. Not
|
||||
// doing this will result in the received block being rejected as an orphan in case it is
|
||||
// not a direct successor.
|
||||
pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
|
||||
CNodeState *nodestate = State(pfrom->GetId());
|
||||
if (chainActive.Tip()->GetBlockTime() > GetTime() - chainparams.GetConsensus().nPowTargetSpacing * 20 &&
|
||||
nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
||||
vToFetch.push_back(inv);
|
||||
// Mark block as in flight already, even though the actual "getdata" message only goes out
|
||||
// later (within the same cs_main lock, though).
|
||||
MarkBlockAsInFlight(pfrom->GetId(), inv.hash, chainparams.GetConsensus());
|
||||
}
|
||||
LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->GetHeight(), inv.hash.ToString(), pfrom->id);
|
||||
// Headers-first is the primary method of announcement on
|
||||
// the network. If a node fell back to sending blocks by inv,
|
||||
// it's probably for a re-org. The final block hash
|
||||
// provided should be the highest, so send a getheaders and
|
||||
// then fetch the blocks we need to catch up.
|
||||
best_block = &inv.hash;
|
||||
}
|
||||
} else {
|
||||
pfrom->AddKnownWTxId(WTxId(inv.hash, inv.hashAux));
|
||||
if (fBlocksOnly)
|
||||
LogPrint("net", "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->id);
|
||||
else if (!fAlreadyHave && !IsInitialBlockDownload(chainparams.GetConsensus()))
|
||||
pfrom->AskFor(inv);
|
||||
}
|
||||
|
||||
if (pfrom->nSendSize > (SendBufferSize() * 2)) {
|
||||
Misbehaving(pfrom->GetId(), 50);
|
||||
return error("send buffer size() = %u", pfrom->nSendSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vToFetch.empty())
|
||||
pfrom->PushMessage(NetMsgType::GETDATA, vToFetch);
|
||||
if (best_block != nullptr) {
|
||||
pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexBestHeader), *best_block);
|
||||
LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->GetHeight(), best_block->ToString(), pfrom->id);
|
||||
}
|
||||
|
||||
} else if (strCommand == NetMsgType::GETDATA) {
|
||||
vector<CInv> vInv;
|
||||
vRecv >> vInv;
|
||||
|
||||
Reference in New Issue
Block a user