@@ -875,7 +875,7 @@ class PeerManagerImpl final : public PeerManager
875
875
EXCLUSIVE_LOCKS_REQUIRED(!m_most_recent_block_mutex, peer.m_getdata_requests_mutex) LOCKS_EXCLUDED(::cs_main);
876
876
877
877
/* * Process a new block. Perform any post-processing housekeeping */
878
- void ProcessBlock (CNode& node, const std::shared_ptr<const CBlock>& block, bool force_processing);
878
+ void ProcessBlock (CNode& node, const std::shared_ptr<const CBlock>& block, bool force_processing, bool min_pow_checked );
879
879
880
880
/* * Relay map (txid or wtxid -> CTransactionRef) */
881
881
typedef std::map<uint256, CTransactionRef> MapRelay;
@@ -1603,6 +1603,10 @@ bool PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati
1603
1603
switch (state.GetResult ()) {
1604
1604
case BlockValidationResult::BLOCK_RESULT_UNSET:
1605
1605
break ;
1606
+ case BlockValidationResult::BLOCK_HEADER_LOW_WORK:
1607
+ // We didn't try to process the block because the header chain may have
1608
+ // too little work.
1609
+ break ;
1606
1610
// The node is providing invalid data:
1607
1611
case BlockValidationResult::BLOCK_CONSENSUS:
1608
1612
case BlockValidationResult::BLOCK_MUTATED:
@@ -2758,7 +2762,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
2758
2762
2759
2763
// Now process all the headers.
2760
2764
BlockValidationState state;
2761
- if (!m_chainman.ProcessNewBlockHeaders (headers, state, &pindexLast)) {
2765
+ if (!m_chainman.ProcessNewBlockHeaders (headers, /* min_pow_checked= */ true , state, &pindexLast)) {
2762
2766
if (state.IsInvalid ()) {
2763
2767
MaybePunishNodeForBlock (pfrom.GetId (), state, via_compact_block, " invalid header received" );
2764
2768
return ;
@@ -3030,10 +3034,10 @@ void PeerManagerImpl::ProcessGetCFCheckPt(CNode& node, Peer& peer, CDataStream&
3030
3034
m_connman.PushMessage (&node, std::move (msg));
3031
3035
}
3032
3036
3033
- void PeerManagerImpl::ProcessBlock (CNode& node, const std::shared_ptr<const CBlock>& block, bool force_processing)
3037
+ void PeerManagerImpl::ProcessBlock (CNode& node, const std::shared_ptr<const CBlock>& block, bool force_processing, bool min_pow_checked )
3034
3038
{
3035
3039
bool new_block{false };
3036
- m_chainman.ProcessNewBlock (block, force_processing, &new_block);
3040
+ m_chainman.ProcessNewBlock (block, force_processing, min_pow_checked, &new_block);
3037
3041
if (new_block) {
3038
3042
node.m_last_block_time = GetTime<std::chrono::seconds>();
3039
3043
} else {
@@ -4008,12 +4012,17 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4008
4012
{
4009
4013
LOCK (cs_main);
4010
4014
4011
- if (!m_chainman.m_blockman .LookupBlockIndex (cmpctblock.header .hashPrevBlock )) {
4015
+ const CBlockIndex* prev_block = m_chainman.m_blockman .LookupBlockIndex (cmpctblock.header .hashPrevBlock );
4016
+ if (!prev_block) {
4012
4017
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
4013
4018
if (!m_chainman.ActiveChainstate ().IsInitialBlockDownload ()) {
4014
4019
MaybeSendGetHeaders (pfrom, GetLocator (m_chainman.m_best_header ), *peer);
4015
4020
}
4016
4021
return ;
4022
+ } else if (prev_block->nChainWork + CalculateHeadersWork ({cmpctblock.header }) < GetAntiDoSWorkThreshold ()) {
4023
+ // If we get a low-work header in a compact block, we can ignore it.
4024
+ LogPrint (BCLog::NET, " Ignoring low-work compact block from peer %d\n " , pfrom.GetId ());
4025
+ return ;
4017
4026
}
4018
4027
4019
4028
if (!m_chainman.m_blockman .LookupBlockIndex (cmpctblock.header .GetHash ())) {
@@ -4023,7 +4032,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4023
4032
4024
4033
const CBlockIndex *pindex = nullptr ;
4025
4034
BlockValidationState state;
4026
- if (!m_chainman.ProcessNewBlockHeaders ({cmpctblock.header }, state, &pindex)) {
4035
+ if (!m_chainman.ProcessNewBlockHeaders ({cmpctblock.header }, /* min_pow_checked= */ true , state, &pindex)) {
4027
4036
if (state.IsInvalid ()) {
4028
4037
MaybePunishNodeForBlock (pfrom.GetId (), state, /* via_compact_block=*/ true , " invalid header via cmpctblock" );
4029
4038
return ;
@@ -4190,7 +4199,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4190
4199
// we have a chain with at least nMinimumChainWork), and we ignore
4191
4200
// compact blocks with less work than our tip, it is safe to treat
4192
4201
// reconstructed compact blocks as having been requested.
4193
- ProcessBlock (pfrom, pblock, /* force_processing=*/ true );
4202
+ ProcessBlock (pfrom, pblock, /* force_processing=*/ true , /* min_pow_checked= */ true );
4194
4203
LOCK (cs_main); // hold cs_main for CBlockIndex::IsValid()
4195
4204
if (pindex->IsValid (BLOCK_VALID_TRANSACTIONS)) {
4196
4205
// Clear download state for this block, which is in
@@ -4273,7 +4282,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4273
4282
// disk-space attacks), but this should be safe due to the
4274
4283
// protections in the compact block handler -- see related comment
4275
4284
// in compact block optimistic reconstruction handling.
4276
- ProcessBlock (pfrom, pblock, /* force_processing=*/ true );
4285
+ ProcessBlock (pfrom, pblock, /* force_processing=*/ true , /* min_pow_checked= */ true );
4277
4286
}
4278
4287
return ;
4279
4288
}
@@ -4322,6 +4331,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4322
4331
4323
4332
bool forceProcessing = false ;
4324
4333
const uint256 hash (pblock->GetHash ());
4334
+ bool min_pow_checked = false ;
4325
4335
{
4326
4336
LOCK (cs_main);
4327
4337
// Always process the block if we requested it, since we may
@@ -4332,8 +4342,14 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
4332
4342
// which peers send us compact blocks, so the race between here and
4333
4343
// cs_main in ProcessNewBlock is fine.
4334
4344
mapBlockSource.emplace (hash, std::make_pair (pfrom.GetId (), true ));
4345
+
4346
+ // Check work on this block against our anti-dos thresholds.
4347
+ const CBlockIndex* prev_block = m_chainman.m_blockman .LookupBlockIndex (pblock->hashPrevBlock );
4348
+ if (prev_block && prev_block->nChainWork + CalculateHeadersWork ({pblock->GetBlockHeader ()}) >= GetAntiDoSWorkThreshold ()) {
4349
+ min_pow_checked = true ;
4350
+ }
4335
4351
}
4336
- ProcessBlock (pfrom, pblock, forceProcessing);
4352
+ ProcessBlock (pfrom, pblock, forceProcessing, min_pow_checked );
4337
4353
return ;
4338
4354
}
4339
4355
0 commit comments