mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-31 10:41:08 +00:00
Merge bitcoin/bitcoin#33893: test: add -alertnotify test for large work invalid chain warning
8343a9ffcc752f77eb2248315d10b6dff4a5c98b test: add `-alertnotify` test for large work invalid chain warning (Sebastian Falbesoner)
Pull request description:
This PR adds missing test coverage for the `LARGE_WORK_INVALID_CHAIN` fork warning, checked with the `-alertnotify` option:
ead849c9f1/src/validation.cpp (L2033-L2040)
Found that this is missing during review of #32587. The test works by first creating a bunch of invalid blocks, that are first announced by headers and then submitted fully in reverse (invalid tip first), in order to set `m_best_invalid` to that value, finally leading to the best chain / invalid chain gap of >= 6 blocks. I'd be curious if there are other (more realistic?) ways to test this. One simple alternative is just to call `invalidateblock` twice (once at the tip, once at the base of the invalid chain).
Note that the written warning doesn't include the exclamation mark, as it is removed via `SanitizeString` in the `AlertNotify` function.
ACKs for top commit:
brunoerg:
reACK 8343a9ffcc752f77eb2248315d10b6dff4a5c98b
mzumsande:
re-ACK 8343a9ffcc752f77eb2248315d10b6dff4a5c98b
Tree-SHA512: d81e9ce7622026498cad5cdcdb867a22068670983737502888c72c72209ca6ff183e77d7429f758765a42c25cda439e01f795884864ac6fe6ff258a98d0bbcbc
This commit is contained in:
commit
7e129b644e
@ -7,6 +7,10 @@ import os
|
||||
import platform
|
||||
|
||||
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
|
||||
from test_framework.blocktools import (
|
||||
create_block,
|
||||
create_coinbase,
|
||||
)
|
||||
from test_framework.descriptors import descsum_create
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
@ -20,6 +24,12 @@ FILE_CHAR_END = 128
|
||||
FILE_CHARS_DISALLOWED = '/\\?%*:|"<>' if platform.system() == 'Windows' else '/'
|
||||
UNCONFIRMED_HASH_STRING = 'unconfirmed'
|
||||
|
||||
LARGE_WORK_INVALID_CHAIN_WARNING = (
|
||||
"Warning: We do not appear to fully agree with our peers " # Exclamation mark removed by SanitizeString in AlertNotify
|
||||
"You may need to upgrade, or other nodes may need to upgrade."
|
||||
)
|
||||
|
||||
|
||||
def notify_outputname(walletname, txid):
|
||||
return txid if platform.system() == 'Windows' else f'{walletname}_{txid}'
|
||||
|
||||
@ -33,6 +43,7 @@ class NotificationsTest(BitcoinTestFramework):
|
||||
def setup_network(self):
|
||||
self.wallet = ''.join(chr(i) for i in range(FILE_CHAR_START, FILE_CHAR_END) if chr(i) not in FILE_CHARS_DISALLOWED)
|
||||
self.alertnotify_dir = os.path.join(self.options.tmpdir, "alertnotify")
|
||||
self.alertnotify_file = os.path.join(self.alertnotify_dir, "alertnotify.txt")
|
||||
self.blocknotify_dir = os.path.join(self.options.tmpdir, "blocknotify")
|
||||
self.walletnotify_dir = os.path.join(self.options.tmpdir, "walletnotify")
|
||||
self.shutdownnotify_dir = os.path.join(self.options.tmpdir, "shutdownnotify")
|
||||
@ -44,7 +55,7 @@ class NotificationsTest(BitcoinTestFramework):
|
||||
|
||||
# -alertnotify and -blocknotify on node0, walletnotify on node1
|
||||
self.extra_args = [[
|
||||
f"-alertnotify=echo > {os.path.join(self.alertnotify_dir, '%s')}",
|
||||
f"-alertnotify=echo %s >> {self.alertnotify_file}",
|
||||
f"-blocknotify=echo > {os.path.join(self.blocknotify_dir, '%s')}",
|
||||
f"-shutdownnotify=echo > {self.shutdownnotify_file}",
|
||||
], [
|
||||
@ -156,12 +167,43 @@ class NotificationsTest(BitcoinTestFramework):
|
||||
self.expect_wallet_notify([(bump2, blockheight2, blockhash2), (tx2, -1, UNCONFIRMED_HASH_STRING)])
|
||||
assert_equal(self.nodes[1].gettransaction(bump2)["confirmations"], 1)
|
||||
|
||||
# TODO: add test for `-alertnotify` large fork notifications
|
||||
self.log.info("test -alertnotify with large work invalid chain")
|
||||
# create a bunch of invalid blocks
|
||||
tip = self.nodes[0].getbestblockhash()
|
||||
height = self.nodes[0].getblockcount() + 1
|
||||
block_time = self.nodes[0].getblock(tip)['time'] + 1
|
||||
|
||||
invalid_blocks = []
|
||||
for _ in range(7): # invalid chain must be longer than 6 blocks to trigger warning
|
||||
block = create_block(int(tip, 16), create_coinbase(height), block_time)
|
||||
# make block invalid by exceeding block subsidy
|
||||
block.vtx[0].vout[0].nValue += 1
|
||||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
block.solve()
|
||||
invalid_blocks.append(block)
|
||||
tip = block.hash_hex
|
||||
height += 1
|
||||
block_time += 1
|
||||
|
||||
# submit headers of invalid blocks
|
||||
for invalid_block in invalid_blocks:
|
||||
self.nodes[0].submitheader(invalid_block.serialize().hex())
|
||||
# submit invalid blocks in reverse order (tip first, to set m_best_invalid)
|
||||
for invalid_block in reversed(invalid_blocks):
|
||||
self.nodes[0].submitblock(invalid_block.serialize().hex())
|
||||
|
||||
self.wait_until(lambda: os.path.isfile(self.alertnotify_file), timeout=10)
|
||||
self.wait_until(self.large_work_invalid_chain_warning_in_alert_file, timeout=10)
|
||||
|
||||
self.log.info("test -shutdownnotify")
|
||||
self.stop_nodes()
|
||||
self.wait_until(lambda: os.path.isfile(self.shutdownnotify_file), timeout=10)
|
||||
|
||||
def large_work_invalid_chain_warning_in_alert_file(self):
|
||||
with open(self.alertnotify_file, 'r', encoding='utf8') as f:
|
||||
alert_text = f.read()
|
||||
return LARGE_WORK_INVALID_CHAIN_WARNING in alert_text
|
||||
|
||||
def expect_wallet_notify(self, tx_details):
|
||||
self.wait_until(lambda: len(os.listdir(self.walletnotify_dir)) >= len(tx_details), timeout=10)
|
||||
# Should have no more and no less files than expected
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user