0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-08 10:31:50 -05:00

test: Add functional test for stalling at tip

When at the tip, the near-tip stalling still applies, but
it will interact with compact block requests. Add tests for this.
This commit is contained in:
Martin Zumsande 2024-10-09 18:52:06 -04:00
parent 9019c08e4e
commit 5e1ff82251

View file

@ -13,14 +13,26 @@ from test_framework.blocktools import (
create_coinbase
)
from test_framework.messages import (
COutPoint,
CTransaction,
CTxIn,
CTxOut,
HeaderAndShortIDs,
MSG_BLOCK,
MSG_TYPE_MASK,
msg_cmpctblock,
msg_sendcmpct,
)
from test_framework.script import (
CScript,
OP_TRUE,
)
from test_framework.p2p import (
CBlockHeader,
msg_block,
msg_headers,
P2PDataStore,
p2p_lock,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@ -50,7 +62,7 @@ class P2PStaller(P2PDataStore):
class P2PIBDStallingTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
self.num_nodes = 3
def setup_network(self):
self.setup_nodes()
@ -65,7 +77,7 @@ class P2PIBDStallingTest(BitcoinTestFramework):
node = self.nodes[0]
tip = int(node.getbestblockhash(), 16)
height = 1
block_time = node.getblock(node.getbestblockhash())['time'] + 1
block_time = int(time.time())
for _ in range(self.NUM_BLOCKS):
self.blocks.append(create_block(tip, create_coinbase(height), block_time))
self.blocks[-1].solve()
@ -212,6 +224,59 @@ class P2PIBDStallingTest(BitcoinTestFramework):
self.wait_until(lambda: node.getblockcount() == self.NUM_BLOCKS - 1)
node.disconnect_p2ps()
def at_tip_stalling(self):
self.log.info("Test stalling and interaction with compact blocks when at tip")
node = self.nodes[2]
peers = []
# Create a block with a tx (would be invalid, but this doesn't matter since we will only ever send the header)
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.blocks[1].vtx[0].sha256, 0), scriptSig=b""))
tx.vout.append(CTxOut(49 * 100000000, CScript([OP_TRUE])))
tx.calc_sha256()
block_time = self.blocks[1].nTime + 1
block = create_block(self.blocks[1].sha256, create_coinbase(3), block_time, txlist=[tx])
block.solve()
for id in range(3):
peers.append(node.add_outbound_p2p_connection(P2PStaller(block.sha256), p2p_idx=id, connection_type="outbound-full-relay"))
# First Peer is a high-bw compact block peer
peers[0].send_and_ping(msg_sendcmpct(announce=True, version=2))
peers[0].block_store = self.block_dict
headers_message = msg_headers()
headers_message.headers = [CBlockHeader(b) for b in self.blocks[:2]]
peers[0].send_message(headers_message)
self.wait_until(lambda: node.getblockcount() == 2)
self.log.info("First peer announces via cmpctblock")
cmpct_block = HeaderAndShortIDs()
cmpct_block.initialize_from_block(block)
peers[0].send_and_ping(msg_cmpctblock(cmpct_block.to_p2p()))
with p2p_lock:
assert "getblocktxn" in peers[0].last_message
self.log.info("Also announce block from other peers by header")
headers_message = msg_headers()
headers_message.headers = [CBlockHeader(block)]
for peer in peers[1:4]:
peer.send_and_ping(headers_message)
self.log.info("Check that block is requested from two more header-announcing peers")
self.wait_until(lambda: sum(peer.stall_block_requested for peer in peers) == 0)
self.mocktime = int(time.time()) + 31
node.setmocktime(self.mocktime)
self.wait_until(lambda: sum(peer.stall_block_requested for peer in peers) == 1)
self.mocktime += 31
node.setmocktime(self.mocktime)
self.wait_until(lambda: sum(peer.stall_block_requested for peer in peers) == 2)
self.log.info("Check that block is not requested from a third header-announcing peer")
self.mocktime += 31
node.setmocktime(self.mocktime)
self.wait_until(lambda: sum(peer.stall_block_requested for peer in peers) == 2)
def all_sync_send_with_ping(self, peers):
for p in peers:
if p.is_connected:
@ -227,6 +292,7 @@ class P2PIBDStallingTest(BitcoinTestFramework):
self.prepare_blocks()
self.ibd_stalling()
self.near_tip_stalling()
self.at_tip_stalling()
if __name__ == '__main__':