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.
This commit is contained in:
iamamyth 2025-01-31 13:01:43 -08:00
parent 90359e31fd
commit 950ddbf30e

View File

@ -160,12 +160,11 @@ class P2PTest():
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,32 @@ class P2PTest():
assert len(res.tx_hash) == 32*2
txid = res.tx_hash
time.sleep(5)
for daemon in [daemon2, daemon3]:
res = daemon.get_transaction_pool_hashes()
assert len(res.tx_hashes) == 1
assert res.tx_hashes[0] == txid
# Due to Dandelion++, the network propagates transactions with a
# random delay, so poll for the transaction with a timeout. The delay
# should almost never exceed a maximum of 13s (~1/billion samples).
# Set the timeout slightly higher than the maximum delay to account
# for transmission and processing time.
timeout = 13.5
pending_daemons = set(daemons)
expected_hashes = [txid]
wait_cutoff = time.monotonic() + timeout
while True:
done = []
for daemon in pending_daemons:
res = daemon.get_transaction_pool_hashes()
hashes = res.get('tx_hashes')
if hashes:
assert hashes == expected_hashes
done.append(daemon)
pending_daemons.difference_update(done)
if len(pending_daemons) == 0:
break
max_delay = wait_cutoff - time.monotonic()
if max_delay <= 0:
break
time.sleep(min(.2, max_delay))
npending = len(pending_daemons)
assert npending == 0, '%d daemons pending' % npending
if __name__ == '__main__':