Skip to content

Commit 7a4a2a3

Browse files
committed
Merge bitcoin/bitcoin#27826: validation: log which peer sent us a header
abe43df doc: release note for #27826 (Sjors Provoost) f9fa287 Use LogBlockHeader for compact blocks (Sjors Provoost) bad7c91 Log which peer sent us a header (Sjors Provoost) 9d3e39c Log block header in net_processing (Sjors Provoost) Pull request description: Fixes #27744 Since #27278 we log received headers. For compact blocks we also log which peer sent it (e5ce857), but not for regular headers. That required an additional refactor, which this PR provides. Move the logging from validation to net_processing. This also reduces the number of log entries (under default configuration) per compact block header from 3 to 2: one for the header and one for the connected tip. The PR introduces a new helper method `LogBlockHeader`. When receiving a _compact block_ we call `LogBlockHeader` from the exact same place as where we previously logged. So that log message doesn't change. What does change is that we no longer _also_ log from `AcceptBlockHeader`. When receiving a regular header(s) message, _we only log the last one_. This is a change in behaviour because it was simpler to implement, but it's probably better anyway. It does mean that if a peer sends of a bunch of headers of which _any_ is invalid, we won't log it (here). Lastly I expanded the code comment explaining why we log this. It initially only covered selfish mining, but we also care about peers sending us headers but not following up (see e.g. #27626). Example log: ``` 2023-06-05T13:12:21Z Saw new header hash=000000000000000000045910263ef84b575ae3af151865238f1e5c619e69c330 height=792964 peer=0 2023-06-05T13:12:23Z UpdateTip: new best=000000000000000000045910263ef84b575ae3af151865238f1e5c619e69c330 height=792964 version=0x20000000 log2_work=94.223098 tx=848176824 date='2023-06-05T13:11:49Z' progress=1.000000 cache=6.4MiB(54615txo) 2023-06-05T13:14:05Z Saw new cmpctblock header hash=00000000000000000003c6fd4ef2e1246a3f9e1fffab7247344f94cadb9de979 height=792965 peer=0 2023-06-05T13:14:05Z UpdateTip: new best=00000000000000000003c6fd4ef2e1246a3f9e1fffab7247344f94cadb9de979 height=792965 version=0x20000000 log2_work=94.223112 tx=848179461 date='2023-06-05T13:13:58Z' progress=1.000000 cache=7.2MiB(61275txo) 2023-06-05T13:14:41Z Saw new header hash=000000000000000000048e6d69c8399992782d08cb57f5d6cbc81a9f996c3f43 height=792966 peer=8 2023-06-05T13:14:42Z UpdateTip: new best=000000000000000000048e6d69c8399992782d08cb57f5d6cbc81a9f996c3f43 height=792966 version=0x2db3c000 log2_work=94.223126 tx=848182944 date='2023-06-05T13:14:35Z' progress=1.000000 cache=8.0MiB(69837txo) ``` ACKs for top commit: danielabrozzoni: tACK abe43df achow101: ACK abe43df vasild: ACK abe43df Tree-SHA512: 081e0de62cbd8a0b35cf54daaa09e3e6991d0cc9f706ef3eb50908752fe7815de69b367f7313381c90cd8d5de0ae5f532d1cd54948c5c1133b1832f266d9c232
2 parents 4694732 + abe43df commit 7a4a2a3

File tree

4 files changed

+44
-22
lines changed

4 files changed

+44
-22
lines changed

doc/release-notes-27826.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- Logs now include which peer sent us a header. Additionaly there are fewer
2+
redundant header log messages. A side-effect of this change is that for
3+
some untypical cases new headers aren't logged anymore, e.g. a direct
4+
`BLOCK` message with a previously unknown header and `submitheader` RPC. (#27826)

src/net_processing.cpp

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,8 @@ class PeerManagerImpl final : public PeerManager
10711071

10721072
void AddAddressKnown(Peer& peer, const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
10731073
void PushAddress(Peer& peer, const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
1074+
1075+
void LogBlockHeader(const CBlockIndex& index, const CNode& peer, bool via_compact_block);
10741076
};
10751077

10761078
const CNodeState* PeerManagerImpl::State(NodeId pnode) const
@@ -2970,14 +2972,21 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
29702972

29712973
// Now process all the headers.
29722974
BlockValidationState state;
2973-
if (!m_chainman.ProcessNewBlockHeaders(headers, /*min_pow_checked=*/true, state, &pindexLast)) {
2975+
const bool processed{m_chainman.ProcessNewBlockHeaders(headers,
2976+
/*min_pow_checked=*/true,
2977+
state, &pindexLast)};
2978+
if (!processed) {
29742979
if (state.IsInvalid()) {
29752980
MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
29762981
return;
29772982
}
29782983
}
29792984
assert(pindexLast);
29802985

2986+
if (processed && received_new_header) {
2987+
LogBlockHeader(*pindexLast, pfrom, /*via_compact_block=*/false);
2988+
}
2989+
29812990
// Consider fetching more headers if we are not using our headers-sync mechanism.
29822991
if (nCount == m_opts.max_headers_result && !have_headers_sync) {
29832992
// Headers message had its maximum size; the peer may have more headers.
@@ -3405,6 +3414,32 @@ void PeerManagerImpl::ProcessCompactBlockTxns(CNode& pfrom, Peer& peer, const Bl
34053414
return;
34063415
}
34073416

3417+
void PeerManagerImpl::LogBlockHeader(const CBlockIndex& index, const CNode& peer, bool via_compact_block) {
3418+
// To prevent log spam, this function should only be called after it was determined that a
3419+
// header is both new and valid.
3420+
//
3421+
// These messages are valuable for detecting potential selfish mining behavior;
3422+
// if multiple displacing headers are seen near simultaneously across many
3423+
// nodes in the network, this might be an indication of selfish mining.
3424+
// In addition it can be used to identify peers which send us a header, but
3425+
// don't followup with a complete and valid (compact) block.
3426+
// Having this log by default when not in IBD ensures broad availability of
3427+
// this data in case investigation is merited.
3428+
const auto msg = strprintf(
3429+
"Saw new %sheader hash=%s height=%d peer=%d%s",
3430+
via_compact_block ? "cmpctblock " : "",
3431+
index.GetBlockHash().ToString(),
3432+
index.nHeight,
3433+
peer.GetId(),
3434+
peer.LogIP(fLogIPs)
3435+
);
3436+
if (m_chainman.IsInitialBlockDownload()) {
3437+
LogDebug(BCLog::VALIDATION, "%s", msg);
3438+
} else {
3439+
LogInfo("%s", msg);
3440+
}
3441+
}
3442+
34083443
void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, DataStream& vRecv,
34093444
const std::chrono::microseconds time_received,
34103445
const std::atomic<bool>& interruptMsgProc)
@@ -4353,9 +4388,10 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
43534388
}
43544389
}
43554390

4391+
// If AcceptBlockHeader returned true, it set pindex
4392+
Assert(pindex);
43564393
if (received_new_header) {
4357-
LogInfo("Saw new cmpctblock header hash=%s peer=%d\n",
4358-
blockhash.ToString(), pfrom.GetId());
4394+
LogBlockHeader(*pindex, pfrom, /*via_compact_block=*/true);
43594395
}
43604396

43614397
bool fProcessBLOCKTXN = false;
@@ -4371,8 +4407,6 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
43714407

43724408
{
43734409
LOCK(cs_main);
4374-
// If AcceptBlockHeader returned true, it set pindex
4375-
assert(pindex);
43764410
UpdateBlockAvailability(pfrom.GetId(), pindex->GetBlockHash());
43774411

43784412
CNodeState *nodestate = State(pfrom.GetId());

src/validation.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4376,23 +4376,6 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida
43764376
if (ppindex)
43774377
*ppindex = pindex;
43784378

4379-
// Since this is the earliest point at which we have determined that a
4380-
// header is both new and valid, log here.
4381-
//
4382-
// These messages are valuable for detecting potential selfish mining behavior;
4383-
// if multiple displacing headers are seen near simultaneously across many
4384-
// nodes in the network, this might be an indication of selfish mining. Having
4385-
// this log by default when not in IBD ensures broad availability of this data
4386-
// in case investigation is merited.
4387-
const auto msg = strprintf(
4388-
"Saw new header hash=%s height=%d", hash.ToString(), pindex->nHeight);
4389-
4390-
if (IsInitialBlockDownload()) {
4391-
LogPrintLevel(BCLog::VALIDATION, BCLog::Level::Debug, "%s\n", msg);
4392-
} else {
4393-
LogPrintf("%s\n", msg);
4394-
}
4395-
43964379
return true;
43974380
}
43984381

src/validation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,7 @@ class ChainstateManager
12161216
* @param[in] min_pow_checked True if proof-of-work anti-DoS checks have been done by caller for headers chain
12171217
* @param[out] state This may be set to an Error state if any error occurred processing them
12181218
* @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers
1219+
* @returns false if AcceptBlockHeader fails on any of the headers, true otherwise (including if headers were already known)
12191220
*/
12201221
bool ProcessNewBlockHeaders(std::span<const CBlockHeader> headers, bool min_pow_checked, BlockValidationState& state, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
12211222

0 commit comments

Comments
 (0)