Compare commits
2 Commits
b5050d06c0
...
5951ee118a
| Author | SHA1 | Date | |
|---|---|---|---|
| 5951ee118a | |||
| d2124a3038 |
24
src/main.cpp
24
src/main.cpp
@@ -328,6 +328,8 @@ namespace {
|
||||
bool fBulkHeaderSeen;
|
||||
//! (server side) time (us) we last served a bulk stream to this peer, for flood throttling.
|
||||
int64_t nLastBulkServeTime;
|
||||
//! (#8 IBD header-flood cap) cumulative headers this peer made us process while in IBD.
|
||||
int64_t nHeadersProcessed;
|
||||
|
||||
CNodeState() {
|
||||
fCurrentlyConnected = false;
|
||||
@@ -348,6 +350,7 @@ namespace {
|
||||
nBulkHashStart.SetNull();
|
||||
fBulkHeaderSeen = false;
|
||||
nLastBulkServeTime = 0;
|
||||
nHeadersProcessed = 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -7888,6 +7891,27 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
}
|
||||
}
|
||||
|
||||
// SECURITY (#8: IBD header-flood cap): bound how many headers a single peer can make us
|
||||
// store while in IBD. Honest headers-first sync needs at most ~chain-length headers from a
|
||||
// peer; one that floods far past 2x the known chain length is only trying to bloat
|
||||
// mapBlockIndex/leveldb (such headers are never selected -- nMinimumChainWork gates that --
|
||||
// but they still cost memory/disk). Cap per-peer and drop the peer. IBD-only: post-IBD the
|
||||
// RandomX check in AcceptBlockHeader already makes forged headers fail RandomX and ban.
|
||||
if (IsInitialBlockDownload()) {
|
||||
CNodeState *hstate = State(pfrom->GetId());
|
||||
if (hstate != NULL) {
|
||||
hstate->nHeadersProcessed += (int64_t)nCount;
|
||||
int knownH = std::max(pindexBestHeader ? (int)pindexBestHeader->GetHeight() : 0,
|
||||
Checkpoints::GetTotalBlocksEstimate(chainparams.Checkpoints()));
|
||||
int64_t headerCap = 2 * (int64_t)knownH + 200000;
|
||||
if (hstate->nHeadersProcessed > headerCap) {
|
||||
Misbehaving(pfrom->GetId(), 100);
|
||||
return error("%s: peer=%d flooded %lld headers during IBD (cap %lld)", __func__,
|
||||
pfrom->id, (long long)hstate->nHeadersProcessed, (long long)headerCap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pindexLast)
|
||||
UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash());
|
||||
|
||||
|
||||
16
src/pow.cpp
16
src/pow.cpp
@@ -804,8 +804,20 @@ bool CheckRandomXSolution(const CBlockHeader *pblock, int32_t height)
|
||||
|
||||
// Derive the key (shared helper) and serialize the input (identical bytes to the pool path).
|
||||
std::string rxKey = GetRandomXKey(height);
|
||||
if (rxKey.empty())
|
||||
return error("CheckRandomXSolution(): cannot derive RandomX key for height %d", height);
|
||||
if (rxKey.empty()) {
|
||||
// The RandomX key block (keyHeight = ((height-lag)/interval)*interval, looked up on the
|
||||
// ACTIVE chain) is not yet connected. This happens ONLY at header-accept when headers run
|
||||
// ahead of our connected block tip (the IBD tail / catch-up) -- block-connect always has it,
|
||||
// since blocks connect in order and keyHeight <= height-lag < the connected tip. The header
|
||||
// is NOT invalid; we simply cannot verify it YET. Defer to block-connect (which re-checks
|
||||
// with the key present) rather than returning an error -- returning an error here makes
|
||||
// CheckBlockHeader DoS(100)-ban the honest peer that sent a perfectly valid tip header we
|
||||
// just can't check yet (observed live: a post-reindex node banned the whole fleet and stalled
|
||||
// ~2000 blocks short of the tip). Flood protection is preserved for synced nodes (key present
|
||||
// -> real RandomX check) and bounded during catch-up by the per-peer IBD header cap + nMinimumChainWork.
|
||||
LogPrint("net", "CheckRandomXSolution: RandomX key block for height %d not yet connected; deferring verification to block-connect\n", height);
|
||||
return true;
|
||||
}
|
||||
std::vector<unsigned char> ssInput = GetRandomXInput(*pblock);
|
||||
|
||||
char computedHash[RANDOMX_HASH_SIZE];
|
||||
|
||||
Reference in New Issue
Block a user