Skip to content

Commit 49257c0

Browse files
committed
[net processing] Don't process mutated blocks
We preemptively perform a block mutation check before further processing a block message (similar to early sanity checks on other messsage types). The main reasons for this change are as follows: - `CBlock::GetHash()` is a foot-gun without a prior mutation check, as the hash returned only commits to the header but not to the actual transactions (`CBlock::vtx`) contained in the block. - We have observed attacks that abused mutated blocks in the past, which could have been prevented by simply not processing mutated blocks (e.g. bitcoin#27608).
1 parent 2d8495e commit 49257c0

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

src/net_processing.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4719,6 +4719,16 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
47194719

47204720
LogPrint(BCLog::NET, "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom.GetId());
47214721

4722+
const CBlockIndex* prev_block{WITH_LOCK(m_chainman.GetMutex(), return m_chainman.m_blockman.LookupBlockIndex(pblock->hashPrevBlock))};
4723+
4724+
if (IsBlockMutated(/*block=*/*pblock,
4725+
/*check_witness_root=*/DeploymentActiveAfter(prev_block, m_chainman, Consensus::DEPLOYMENT_SEGWIT))) {
4726+
LogDebug(BCLog::NET, "Received mutated block from peer=%d\n", peer->m_id);
4727+
Misbehaving(*peer, 100, "mutated block");
4728+
WITH_LOCK(cs_main, RemoveBlockRequest(pblock->GetHash(), peer->m_id));
4729+
return;
4730+
}
4731+
47224732
bool forceProcessing = false;
47234733
const uint256 hash(pblock->GetHash());
47244734
bool min_pow_checked = false;
@@ -4734,7 +4744,6 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
47344744
mapBlockSource.emplace(hash, std::make_pair(pfrom.GetId(), true));
47354745

47364746
// Check work on this block against our anti-dos thresholds.
4737-
const CBlockIndex* prev_block = m_chainman.m_blockman.LookupBlockIndex(pblock->hashPrevBlock);
47384747
if (prev_block && prev_block->nChainWork + CalculateHeadersWork({pblock->GetBlockHeader()}) >= GetAntiDoSWorkThreshold()) {
47394748
min_pow_checked = true;
47404749
}

0 commit comments

Comments
 (0)