From eb9cb97407f29363eac4ad46eaacbeb290b0854b Mon Sep 17 00:00:00 2001 From: iamamyth Date: Fri, 31 Jan 2025 13:01:43 -0800 Subject: [PATCH] tests: Improve p2p tx propagation functional test Reduce the likelihood of false positive failures in the p2p transaction propagation functional test by waiting up to a maximum timeout for a transaction to propagate, rather than using a fixed timeout, to reflect the random delay of Dandelion++ transaction propagation. This strategy also speeds test execution in cases where propagation occurs faster than the previously expected fixed delay. --- tests/functional_tests/p2p.py | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/tests/functional_tests/p2p.py b/tests/functional_tests/p2p.py index b878d0f14de..33cd10da683 100755 --- a/tests/functional_tests/p2p.py +++ b/tests/functional_tests/p2p.py @@ -160,12 +160,11 @@ def test_p2p_reorg(self): def test_p2p_tx_propagation(self): print('Testing P2P tx propagation') - daemon2 = Daemon(idx = 2) - daemon3 = Daemon(idx = 3) + daemons = (Daemon(idx = 2), Daemon(idx = 3)) - for daemon in [daemon2, daemon3]: + for daemon in daemons: res = daemon.get_transaction_pool_hashes() - assert not 'tx_hashes' in res or len(res.tx_hashes) == 0 + assert len(res.get('tx_hashes', [])) == 0 self.wallet.refresh() res = self.wallet.get_balance() @@ -175,12 +174,25 @@ def test_p2p_tx_propagation(self): assert len(res.tx_hash) == 32*2 txid = res.tx_hash - time.sleep(5) - - for daemon in [daemon2, daemon3]: + # Due to Dandelion++, the network propagates transactions with a + # random delay, so poll for the transaction with a timeout + timeout = 16 + remaining_daemons = list(daemons) + expected_hashes = [txid] + wait_cutoff = time.monotonic() + timeout + while remaining_daemons: + daemon = remaining_daemons[-1] res = daemon.get_transaction_pool_hashes() - assert len(res.tx_hashes) == 1 - assert res.tx_hashes[0] == txid + hashes = res.get('tx_hashes') + if hashes: + assert hashes == expected_hashes + remaining_daemons.pop() + else: + max_delay = wait_cutoff - time.monotonic() + if max_delay <= 0: + break + time.sleep(min(.25, max_delay)) + assert len(remaining_daemons) == 0 if __name__ == '__main__':