Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions qa/rpc-tests/regtest_block_relay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env python3
# Copyright (c) 2026 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
#
# Regression test for https://github.com/ZcashFoundation/zebra/issues/10332
#
# Verifies that blocks mined on node0 propagate through a linear A-B-C topology
# to node2, which neither mines blocks nor is directly connected to node0.
# Previously, node1 would receive the block but fail to rebroadcast it to node2.

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, connect_nodes

class RegtestBlockRelayTest(BitcoinTestFramework):

def __init__(self):
super().__init__()
self.cache_behavior = 'clean'
self.num_nodes = 3
self.num_wallets = 0

def setup_network(self):
# Start nodes without connecting them; run_test manages the topology.
self.nodes = self.setup_nodes()
self.zainos = self.setup_indexers()
self.wallets = self.setup_wallets()
self.is_network_split = False

def run_test(self):
# Build linear topology: node0 -- node1 -- node2
# node0 mines, node1 relays, node2 only receives.
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[1], 2)

self.nodes[0].generate(10)
self.sync_all(False)

for i in range(len(self.nodes)):
assert_equal(self.nodes[i].getbestblockheightandhash()['height'], 10)

if __name__ == '__main__':
RegtestBlockRelayTest().main()
39 changes: 9 additions & 30 deletions qa/rpc-tests/test_framework/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,30 +377,6 @@ def rebuild_cache():
block_time += PRE_BLOSSOM_BLOCK_TARGET_SPACING
# Must sync before next peer starts generating blocks
sync_blocks(rpcs)
# Shut down and restart every zebrad node.
# This works around a zebrad problem where it won't broadcast
# received blocks to other connected nodes, and is a workaround
# for zebrad not supporting `addnode remove`.
# TODO: Remove this workaround once either of the following is resolved:
# - https://github.com/ZcashFoundation/zebra/issues/10329
# - https://github.com/ZcashFoundation/zebra/issues/10332
stop_nodes(rpcs)
wait_bitcoinds()
for i in range(MAX_NODES):
config = zebrad_config(node_dir(cachedir, i))
args = [ zcashd_binary(), "-c="+config, "start" ]
bitcoind_processes[i] = subprocess.Popen(args)
if os.getenv("PYTHON_DEBUG", ""):
print("initialize_chain: %s started, waiting for RPC to come up" % (zcashd_binary(),))
wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i)
if os.getenv("PYTHON_DEBUG", ""):
print("initialize_chain: RPC successfully started")
for i in range(MAX_NODES):
try:
rpcs.append(get_rpc_proxy(rpc_url(i), i))
except:
sys.stderr.write("Error connecting to "+rpc_url(i)+"\n")
sys.exit(1)
# Check that local time isn't going backwards
assert_greater_than(time.time() + 1, block_time)

Expand Down Expand Up @@ -705,15 +681,18 @@ def wait_bitcoinds():
def connect_nodes(from_connection, node_num):
ip_port = "127.0.0.1:"+str(p2p_port(node_num))
# TODO: Replace `add` with `onetry` if zebrad implements it.
from_connection.addnode(ip_port, "add")
# zebrad may reject a duplicate `addnode add` for a peer already in its
# addnode list (it doesn't support `addnode remove`), so ignore that error.
try:
from_connection.addnode(ip_port, "add")
except JSONRPCException:
pass
# poll until version handshake complete to avoid race conditions
# with transaction relaying
while True:
for peer in from_connection.getpeerinfo():
if peer['addr'] == ip_port:
return
else:
time.sleep(1)
if any(peer['addr'] == ip_port for peer in from_connection.getpeerinfo()):
return
time.sleep(1)

def connect_nodes_bi(nodes, a, b):
connect_nodes(nodes[a], b)
Expand Down
Loading