mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-08-25 20:51:33 +02:00
Merge bitcoin/bitcoin#33083: qa: test that we do not disconnect a peer for submitting an invalid compact block
c157438116
qa: test that we do disconnect upon a second invalid compact block being announced (Antoine Poinsot)fb2dcbb160
qa: test cached failure for compact block (Antoine Poinsot)f12d8b104e
qa: test a compact block with an invalid transaction (Antoine Poinsot)d6c37b28a7
qa: remove unnecessary tx removal from compact block (Antoine Poinsot) Pull request description: In thinking about https://github.com/bitcoin/bitcoin/pull/33050 and https://github.com/bitcoin/bitcoin/pull/33012#issuecomment-3111631541, i went through the code paths for peer disconnection upon submitting an invalid block. It turns out that the fact we exempt a peer from disconnection upon submitting an invalid compact block was not properly tested, as can be checked with these diffs: ```diff diff --git a/src/net_processing.cpp b/src/net_processing.cpp index0c4a89c44c..d243fb88d4
100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1805,10 +1805,10 @@ void PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati // The node is providing invalid data: case BlockValidationResult::BLOCK_CONSENSUS: case BlockValidationResult::BLOCK_MUTATED: - if (!via_compact_block) { + //if (!via_compact_block) { if (peer) Misbehaving(*peer, message); return; - } + //} break; case BlockValidationResult::BLOCK_CACHED_INVALID: { ``` ```diff diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 0c4a89c44cb..e8e0c805367 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1814,10 +1814,10 @@ void PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidati { // Discourage outbound (but not inbound) peers if on an invalid chain. // Exempt HB compact block peers. Manual connections are always protected from discouragement. - if (peer && !via_compact_block && !peer->m_is_inbound) { + //if (peer && !via_compact_block && !peer->m_is_inbound) { if (peer) Misbehaving(*peer, message); return; - } + //} break; } case BlockValidationResult::BLOCK_INVALID_HEADER: ``` We do have a test for this, but it actually uses a coinbase witness commitment error, which is checked much earlier in `FillBlock`. This PR adds coverage for the two exemptions in `MaybePunishNodeForBlock`. ACKs for top commit: kevkevinpal: ACK [c157438
](c157438116
) nervana21: tACK [c157438
](c157438116
) instagibbs: crACKc157438116
stratospher: ACKc157438116
. Tree-SHA512: a77d5a9768c0d73f122b06db2e416e80d0b3c3fd261dae8e340ecec2ae92d947d31988894bc732cb6dad2e338b3c82f33e75eb3280f8b0933b285657cf3b212c
This commit is contained in:
@@ -54,6 +54,7 @@ from test_framework.script import (
|
||||
CScript,
|
||||
OP_DROP,
|
||||
OP_TRUE,
|
||||
OP_RETURN,
|
||||
)
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
@@ -709,7 +710,6 @@ class CompactBlocksTest(BitcoinTestFramework):
|
||||
utxo = self.utxos[0]
|
||||
|
||||
block = self.build_block_with_transactions(node, utxo, 5)
|
||||
del block.vtx[3]
|
||||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
# Drop the coinbase witness but include the witness commitment.
|
||||
add_witness_commitment(block)
|
||||
@@ -727,6 +727,37 @@ class CompactBlocksTest(BitcoinTestFramework):
|
||||
assert_not_equal(node.getbestblockhash(), block.hash_hex)
|
||||
test_node.sync_with_ping()
|
||||
|
||||
# Re-establish a proper witness commitment with the coinbase witness, but
|
||||
# invalidate the last tx in the block.
|
||||
block.vtx[4].vin[0].scriptSig = CScript([OP_RETURN])
|
||||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
add_witness_commitment(block)
|
||||
block.solve()
|
||||
|
||||
# This will lead to a consensus failure for which we also won't be disconnected but which
|
||||
# will be cached.
|
||||
comp_block.initialize_from_block(block, prefill_list=list(range(len(block.vtx))), use_witness=True)
|
||||
msg = msg_cmpctblock(comp_block.to_p2p())
|
||||
test_node.send_and_ping(msg)
|
||||
|
||||
# The tip still didn't advance.
|
||||
assert_not_equal(node.getbestblockhash(), block.hash_hex)
|
||||
test_node.sync_with_ping()
|
||||
|
||||
# The failure above was cached. Submitting the compact block again will returned a cached
|
||||
# consensus error (the code path is different) and still not get us disconnected (nor
|
||||
# advance the tip).
|
||||
test_node.send_and_ping(msg)
|
||||
assert_not_equal(node.getbestblockhash(), block.hash_hex)
|
||||
test_node.sync_with_ping()
|
||||
|
||||
# Now, announcing a second block building on top of the invalid one will get us disconnected.
|
||||
block.hashPrevBlock = block.hash_int
|
||||
block.solve()
|
||||
comp_block.initialize_from_block(block, prefill_list=list(range(len(block.vtx))), use_witness=True)
|
||||
msg = msg_cmpctblock(comp_block.to_p2p())
|
||||
test_node.send_await_disconnect(msg)
|
||||
|
||||
# Helper for enabling cb announcements
|
||||
# Send the sendcmpct request and sync headers
|
||||
def request_cb_announcements(self, peer):
|
||||
@@ -943,6 +974,9 @@ class CompactBlocksTest(BitcoinTestFramework):
|
||||
self.log.info("Testing handling of invalid compact blocks...")
|
||||
self.test_invalid_tx_in_compactblock(self.segwit_node)
|
||||
|
||||
# The previous test will lead to a disconnection. Reconnect before continuing.
|
||||
self.segwit_node = self.nodes[0].add_p2p_connection(TestP2PConn())
|
||||
|
||||
self.log.info("Testing invalid index in cmpctblock message...")
|
||||
self.test_invalid_cmpctblock_message()
|
||||
|
||||
|
Reference in New Issue
Block a user