From 31eaa83c5526dabc0508315938b8293328ef1b21 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sat, 6 Jan 2024 04:26:10 +0000 Subject: [PATCH] Warn in the debug log (only) for blocks where the block version is being abused --- src/validation.cpp | 10 +++++++++- .../functional/feature_versionbits_warning.py | 20 +++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index fc33223367..72646cddee 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2799,10 +2799,18 @@ void Chainstate::UpdateTip(const CBlockIndex* pindexNew) AppendWarning(warning_messages, warning); } } - UpdateTipLog(coins_tip, pindexNew, params, __func__, "", warning_messages.original); + if (!warning_messages.empty()) { m_chainman.GetNotifications().warning(warning_messages); } + + static constexpr int32_t BIP320_MASK = 0x1fffe000UL; + if ((pindexNew->nVersion & BIP320_MASK) && pindexNew->nVersion != m_chainman.m_versionbitscache.ComputeBlockVersion(pindexNew->pprev, params.GetConsensus())) { + const auto warning = _("Miner violated version bit protocol"); + AppendWarning(warning_messages, warning); + } + + UpdateTipLog(coins_tip, pindexNew, params, __func__, "", warning_messages.original); } /** Disconnect m_chain's tip. diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py index 17c3331f9a..ad7882d75f 100755 --- a/test/functional/feature_versionbits_warning.py +++ b/test/functional/feature_versionbits_warning.py @@ -31,6 +31,7 @@ WARN_UNKNOWN_BIT_MINED = f"Warning: Miners are attempting to activate unknown ne # NOTE: WARN_BIP320_BIT_MINED includes VB_UNKNOWN_BIT because it persists from the earlier check WARN_BIP320_BIT_MINED = f"Warning: Miners are attempting to activate unknown new rules (bit {VB_UNKNOWN_BIT}, {VB_BIP320_BIT})" WARN_UNKNOWN_RULES_ACTIVE = f"Unknown new rules activated (versionbit {VB_UNKNOWN_BIT})" +WARN_BIP320_BLOCK = "Miner violated version bit protocol" VB_PATTERN = re.compile("Unknown new rules activated.*versionbit") class VersionBitsWarningTest(BitcoinTestFramework): @@ -112,18 +113,29 @@ class VersionBitsWarningTest(BitcoinTestFramework): assert(WARN_UNKNOWN_BIT_MINED in node.getmininginfo()["warnings"]) assert(WARN_UNKNOWN_BIT_MINED in node.getnetworkinfo()["warnings"]) - self.log.info("Check that there is a warning if >75 blocks in the last 100 were a BIP320 version") - self.send_blocks_with_version(peer, VB_BIP320_THRESHOLD - 1, VB_BIP320_VERSION) + self.log.info("Check that there is a warning if BIP320 is used, and a second persistent warning if >75 blocks in the last 100 were a BIP320 version") + with node.wait_for_debug_log([WARN_BIP320_BLOCK.encode('ascii')]): + self.send_blocks_with_version(peer, VB_BIP320_THRESHOLD - 1, VB_BIP320_VERSION) # Check that get*info() doesn't shows the 76/100 unknown block version warning yet. assert(WARN_BIP320_BIT_MINED not in node.getmininginfo()["warnings"]) assert(WARN_BIP320_BIT_MINED not in node.getnetworkinfo()["warnings"]) - self.send_blocks_with_version(peer, 1, VB_BIP320_VERSION) + # ...and it shouldn't show the BIP320-specific warning + assert(WARN_BIP320_BLOCK not in node.getmininginfo()["warnings"]) + assert(WARN_BIP320_BLOCK not in node.getnetworkinfo()["warnings"]) + with node.wait_for_debug_log([WARN_BIP320_BLOCK.encode('ascii'), b'Enqueuing UpdatedBlockTip']): + self.send_blocks_with_version(peer, 1, VB_BIP320_VERSION) # Check that get*info() shows the 76/100 unknown block version warning. assert(WARN_BIP320_BIT_MINED in node.getmininginfo()["warnings"]) assert(WARN_BIP320_BIT_MINED in node.getnetworkinfo()["warnings"]) - self.generatetoaddress(node, 1, node_deterministic_address) + assert(WARN_BIP320_BLOCK not in node.getmininginfo()["warnings"]) + assert(WARN_BIP320_BLOCK not in node.getnetworkinfo()["warnings"]) + with node.wait_for_debug_log([b'Enqueuing UpdatedBlockTip'], forbid_msgs=[WARN_BIP320_BLOCK.encode('ascii')]): + self.generatetoaddress(node, 1, node_deterministic_address) + # Only the 76/100 should persist assert(WARN_BIP320_BIT_MINED in node.getmininginfo()["warnings"]) assert(WARN_BIP320_BIT_MINED in node.getnetworkinfo()["warnings"]) + assert(WARN_BIP320_BLOCK not in node.getmininginfo()["warnings"]) + assert(WARN_BIP320_BLOCK not in node.getnetworkinfo()["warnings"]) self.generatetoaddress(node, VB_PERIOD - VB_BIP320_THRESHOLD - 1, node_deterministic_address) self.log.info("Check that there is a warning if previous VB_BLOCKS have >=VB_THRESHOLD blocks with unknown versionbits version.")