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;
|
bool fBulkHeaderSeen;
|
||||||
//! (server side) time (us) we last served a bulk stream to this peer, for flood throttling.
|
//! (server side) time (us) we last served a bulk stream to this peer, for flood throttling.
|
||||||
int64_t nLastBulkServeTime;
|
int64_t nLastBulkServeTime;
|
||||||
|
//! (#8 IBD header-flood cap) cumulative headers this peer made us process while in IBD.
|
||||||
|
int64_t nHeadersProcessed;
|
||||||
|
|
||||||
CNodeState() {
|
CNodeState() {
|
||||||
fCurrentlyConnected = false;
|
fCurrentlyConnected = false;
|
||||||
@@ -348,6 +350,7 @@ namespace {
|
|||||||
nBulkHashStart.SetNull();
|
nBulkHashStart.SetNull();
|
||||||
fBulkHeaderSeen = false;
|
fBulkHeaderSeen = false;
|
||||||
nLastBulkServeTime = 0;
|
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)
|
if (pindexLast)
|
||||||
UpdateBlockAvailability(pfrom->GetId(), pindexLast->GetBlockHash());
|
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).
|
// Derive the key (shared helper) and serialize the input (identical bytes to the pool path).
|
||||||
std::string rxKey = GetRandomXKey(height);
|
std::string rxKey = GetRandomXKey(height);
|
||||||
if (rxKey.empty())
|
if (rxKey.empty()) {
|
||||||
return error("CheckRandomXSolution(): cannot derive RandomX key for height %d", height);
|
// 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);
|
std::vector<unsigned char> ssInput = GetRandomXInput(*pblock);
|
||||||
|
|
||||||
char computedHash[RANDOMX_HASH_SIZE];
|
char computedHash[RANDOMX_HASH_SIZE];
|
||||||
|
|||||||
Reference in New Issue
Block a user