Makes sense! That makes the test easier to understand as well:
(to be applied on current HEAD commit of this branch)
0diff --git a/test/functional/p2p_leak_tx.py b/test/functional/p2p_leak_tx.py
1index 21d1d4ed2d..a0ceaedd67 100755
2--- a/test/functional/p2p_leak_tx.py
3+++ b/test/functional/p2p_leak_tx.py
4@@ -13,10 +13,17 @@ from test_framework.util import (
5 wait_until,
6 )
7
8+import time
9+
10+
11+class P2PNode(P2PDataStore):
12+ def on_inv(self, msg):
13+ pass
14+
15
16 class P2PLeakTxTest(BitcoinTestFramework):
17 def set_test_params(self):
18- self.num_nodes = 2
19+ self.num_nodes = 1
20
21 def skip_test_if_missing_module(self):
22 self.skip_if_no_wallet()
23@@ -26,67 +33,28 @@ class P2PLeakTxTest(BitcoinTestFramework):
24 gen_node.generate(1)
25 self.sync_all()
26
27- inbound_peer = self.nodes[0].add_p2p_connection(P2PDataStore()) # An "attacking" inbound peer
28- outbound_peer = self.nodes[1] # Our outbound peer
29+ inbound_peer = self.nodes[0].add_p2p_connection(P2PNode()) # An "attacking" inbound peer
30
31- # In an adversarial setting we can generally assume that inbound peers
32- # are more likely to spy on us than outbound peers. Thus, on average,
33- # we announce transactions first to outbound peers, then to (all)
34- # inbound peers. Inbound peers must not be able to successfully request a
35- # transaction if they haven't yet received the announcement for it.
36- #
37- # With only one outbound peer, we expect that a tx is first announced
38- # to (all) inbound peers (and thus present a potential leak) in 28.5% of
39- # the cases.
40- #
41- # Probability( time_ann_inbound < time_ann_outbound ) =
42- # ∫ f_in(x) * F_out(x) dx =
43- # ∫ (lambda_in * exp(-lambda_in * x)) * (1 - exp(-lambda_out * x)) dx =
44- # 0.285714
45- #
46- # Where,
47- # * f_in is the pdf of the exponential distribution for inbound peers,
48- # with lambda_in = 1 / INVENTORY_BROADCAST_INTERVAL = 1/5
49- # * F_out is the cdf of the expon. distribution for outbound peers,
50- # with lambda_out = 1 / (INVENTORY_BROADCAST_INTERVAL >> 1) = 1/2
51- #
52- # Due to measurement delays, the actual monte-carlo leak is a bit
53- # higher. Assume a total delay of 0.6 s (Includes network delays and
54- # rpc delay to poll the raw mempool)
55- #
56- # Probability( time_ann_inbound < time_ann_outbound + 0.6 ) =
57- # ∫ f_in(x) * F_out(x + 0.6) dx =
58- # ∫ (lambda_in * exp(-lambda_in * x)) * (1 - exp(-lambda_out * (x+.6))) dx =
59- # 0.366485
60- # EXPECTED_MEASURED_LEAK = .366485
61- # Because this test is empirical and our testing framework isn't set up
62- # to handle tests that fail with some expected likelihood, we bump this
63- # value up to decrease the false positive rate.
64- EXPECTED_MEASURED_LEAK = .50
65-
66- REPEATS = 100
67- measured_leak = 0
68- self.log.info('Start simulation for {} repeats'.format(REPEATS))
69+ REPEATS = 10
70+ self.log.info('Start test for {} repeats'.format(REPEATS))
71 for i in range(REPEATS):
72 self.log.debug('Run {}/{}'.format(i, REPEATS))
73 txid = gen_node.sendtoaddress(gen_node.getnewaddress(), 0.033)
74+
75+ time.sleep(5)
76+
77 want_tx = msg_getdata()
78 want_tx.inv.append(CInv(t=1, h=int(txid, 16)))
79-
80- wait_until(lambda: txid in outbound_peer.getrawmempool(), lock=mininode_lock)
81 inbound_peer.send_message(want_tx)
82 inbound_peer.sync_with_ping()
83
84 if inbound_peer.last_message.get('notfound'):
85+ self.log.debug('tx {} was not yet announced to us.'.format(txid))
86 assert_equal(inbound_peer.last_message['notfound'].vec[0].hash, int(txid, 16))
87 inbound_peer.last_message.pop('notfound')
88 else:
89- measured_leak += 1
90-
91- measured_leak /= REPEATS
92- self.log.info('Measured leak of {}'.format(measured_leak))
93-
94- assert_greater_than(EXPECTED_MEASURED_LEAK, measured_leak)
95+ self.log.debug('tx {} was announced to us.'.format(txid))
96+ assert int(txid, 16) in [inv.hash for inv in inbound_peer.last_message['inv'].inv]
97
98
99 if __name__ == '__main__':