mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 10:43:19 -03:00
test: add test for chains building on invalid blocks
This commit is contained in:
parent
155002ae12
commit
ee61607a6a
2 changed files with 106 additions and 0 deletions
105
test/functional/p2p_invalid_chain.py
Executable file
105
test/functional/p2p_invalid_chain.py
Executable file
|
@ -0,0 +1,105 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2024-present The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test how invalid blocks will influence chain behavior, in particular
|
||||
the acceptance of future blocks and / or headers building on an invalid chain
|
||||
For simplicity, submitheader / submitblock rpcs will be used in this test. The
|
||||
behavior will be the same if blocks / headers are received through the p2p network.
|
||||
"""
|
||||
|
||||
from test_framework.blocktools import (
|
||||
create_block,
|
||||
create_coinbase,
|
||||
)
|
||||
from test_framework.script import CScript
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
assert_raises_rpc_error,
|
||||
)
|
||||
|
||||
|
||||
class InvalidChainTest (BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
|
||||
def run_test(self):
|
||||
node = self.nodes[0]
|
||||
tip = int(node.getbestblockhash(), 16)
|
||||
start_height = self.nodes[0].getblockcount()
|
||||
|
||||
self.log.info("Test chain with an invalid block (found invalid during connect)")
|
||||
# Create invalid block (too high coinbase)
|
||||
block_time = node.getblock(node.getbestblockhash())['time'] + 1
|
||||
invalid_block = create_block(tip, create_coinbase(start_height + 1, nValue=100), block_time)
|
||||
invalid_block.solve()
|
||||
# Submit the valid header of the invalid block and a header that builds on it
|
||||
node.submitheader(invalid_block.serialize().hex())
|
||||
block_time += 1
|
||||
block2a = create_block(invalid_block.sha256, create_coinbase(start_height + 2), block_time)
|
||||
block2a.solve()
|
||||
node.submitheader(block2a.serialize().hex())
|
||||
# Submit the invalid block
|
||||
assert_equal(node.submitblock(invalid_block.serialize().hex()), "bad-cb-amount")
|
||||
# Submit a block building directly on the invalid block
|
||||
block_time += 1
|
||||
block2b = create_block(invalid_block.sha256, create_coinbase(start_height + 2), block_time)
|
||||
block2b.solve()
|
||||
assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(block2b.serialize().hex()))
|
||||
# Submit a block building indirectly on the invalid block
|
||||
block_time += 1
|
||||
block3 = create_block(block2a.sha256, create_coinbase(start_height + 3), block_time)
|
||||
block3.solve()
|
||||
assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(block3.serialize().hex()))
|
||||
|
||||
self.log.info("Test chain with an invalid block (found invalid during acceptance)")
|
||||
# Create invalid block (bad coinbase height)
|
||||
block_time += 1
|
||||
invalid_block = create_block(tip, create_coinbase(start_height + 100), block_time)
|
||||
invalid_block.solve()
|
||||
# Submit the valid header of the invalid block and a header that builds on it
|
||||
node.submitheader(invalid_block.serialize().hex())
|
||||
block_time += 1
|
||||
block2a = create_block(invalid_block.sha256, create_coinbase(start_height + 2), block_time)
|
||||
block2a.solve()
|
||||
node.submitheader(block2a.serialize().hex())
|
||||
# Submit the invalid block
|
||||
assert_equal(node.submitblock(invalid_block.serialize().hex()), "bad-cb-height")
|
||||
# Submit a block building directly on the invalid block
|
||||
block_time += 1
|
||||
block2b = create_block(invalid_block.sha256, create_coinbase(start_height + 2), block_time)
|
||||
block2b.solve()
|
||||
assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(block2b.serialize().hex()))
|
||||
# Submit a block building indirectly on the invalid block
|
||||
block_time += 1
|
||||
block3 = create_block(block2a.sha256, create_coinbase(start_height + 3), block_time)
|
||||
block3.solve()
|
||||
node.submitheader(block3.serialize().hex()) # No error, we accept more headers building on a block we have marked as invalid.
|
||||
|
||||
self.log.info("Test chain with an invalid block (found invalid before acceptance)")
|
||||
# Create invalid block (too large)
|
||||
block_time += 1
|
||||
invalid_block = create_block(tip, create_coinbase(start_height + 1, extra_output_script=CScript([b'\x00' * 1000000])), block_time)
|
||||
invalid_block.solve()
|
||||
# Submit the valid header of the invalid block and a header that builds on it
|
||||
node.submitheader(invalid_block.serialize().hex())
|
||||
block_time += 1
|
||||
block2a = create_block(invalid_block.sha256, create_coinbase(start_height + 2), block_time)
|
||||
block2a.solve()
|
||||
node.submitheader(block2a.serialize().hex())
|
||||
# Submit a block building directly on the invalid block
|
||||
block_time += 1
|
||||
block2b = create_block(invalid_block.sha256, create_coinbase(start_height + 2), block_time)
|
||||
block2b.solve()
|
||||
node.submitheader(block2b.serialize().hex()) # No error, we don't mark the block permanently as invalid.
|
||||
# Submit a block building indirectly on the invalid block
|
||||
assert_equal(node.submitblock(invalid_block.serialize().hex()), "bad-blk-length")
|
||||
block_time += 1
|
||||
block3 = create_block(block2a.sha256, create_coinbase(start_height + 3), block_time)
|
||||
block3.solve()
|
||||
node.submitheader(block3.serialize().hex()) # No error, we don't mark the block permanently as invalid.
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
InvalidChainTest(__file__).main()
|
|
@ -262,6 +262,7 @@ BASE_SCRIPTS = [
|
|||
'p2p_invalid_block.py --v2transport',
|
||||
'p2p_invalid_tx.py --v1transport',
|
||||
'p2p_invalid_tx.py --v2transport',
|
||||
'p2p_invalid_chain.py',
|
||||
'p2p_v2_transport.py',
|
||||
'p2p_v2_encrypted.py',
|
||||
'p2p_v2_misbehaving.py',
|
||||
|
|
Loading…
Add table
Reference in a new issue