From bc20629b9f5c3a2192f563ca8e51fdaaa9287c31 Mon Sep 17 00:00:00 2001 From: Duke Date: Mon, 16 Sep 2024 11:18:16 -0400 Subject: [PATCH] Revert "Fix memory DoS" This reverts commit 84377caae78116b817dbb64434def0b1ecffab74. --- src/main.cpp | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4a9de15a7..ae5e27916 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7320,8 +7320,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } LOCK(cs_main); - - const uint256* best_block{nullptr}; std::vector vToFetch; @@ -7341,31 +7339,35 @@ 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)) { - // 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; + // 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); } - } 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 (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); - } - + if (!vToFetch.empty()) + pfrom->PushMessage(NetMsgType::GETDATA, vToFetch); } else if (strCommand == NetMsgType::GETDATA) { vector vInv; vRecv >> vInv;