Makes sense! That makes the test easier to understand as well:
(to be applied on current HEAD commit of this branch)
diff --git a/test/functional/p2p_leak_tx.py b/test/functional/p2p_leak_tx.py
index 21d1d4ed2d..a0ceaedd67 100755
--- a/test/functional/p2p_leak_tx.py
+++ b/test/functional/p2p_leak_tx.py
@@ -13,10 +13,17 @@ from test_framework.util import (
wait_until,
)
+import time
+
+
+class P2PNode(P2PDataStore):
+ def on_inv(self, msg):
+ pass
+
class P2PLeakTxTest(BitcoinTestFramework):
def set_test_params(self):
- self.num_nodes = 2
+ self.num_nodes = 1
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
@@ -26,67 +33,28 @@ class P2PLeakTxTest(BitcoinTestFramework):
gen_node.generate(1)
self.sync_all()
- inbound_peer = self.nodes[0].add_p2p_connection(P2PDataStore()) # An "attacking" inbound peer
- outbound_peer = self.nodes[1] # Our outbound peer
+ inbound_peer = self.nodes[0].add_p2p_connection(P2PNode()) # An "attacking" inbound peer
- # In an adversarial setting we can generally assume that inbound peers
- # are more likely to spy on us than outbound peers. Thus, on average,
- # we announce transactions first to outbound peers, then to (all)
- # inbound peers. Inbound peers must not be able to successfully request a
- # transaction if they haven't yet received the announcement for it.
- #
- # With only one outbound peer, we expect that a tx is first announced
- # to (all) inbound peers (and thus present a potential leak) in 28.5% of
- # the cases.
- #
- # Probability( time_ann_inbound < time_ann_outbound ) =
- # ∫ f_in(x) * F_out(x) dx =
- # ∫ (lambda_in * exp(-lambda_in * x)) * (1 - exp(-lambda_out * x)) dx =
- # 0.285714
- #
- # Where,
- # * f_in is the pdf of the exponential distribution for inbound peers,
- # with lambda_in = 1 / INVENTORY_BROADCAST_INTERVAL = 1/5
- # * F_out is the cdf of the expon. distribution for outbound peers,
- # with lambda_out = 1 / (INVENTORY_BROADCAST_INTERVAL >> 1) = 1/2
- #
- # Due to measurement delays, the actual monte-carlo leak is a bit
- # higher. Assume a total delay of 0.6 s (Includes network delays and
- # rpc delay to poll the raw mempool)
- #
- # Probability( time_ann_inbound < time_ann_outbound + 0.6 ) =
- # ∫ f_in(x) * F_out(x + 0.6) dx =
- # ∫ (lambda_in * exp(-lambda_in * x)) * (1 - exp(-lambda_out * (x+.6))) dx =
- # 0.366485
- # EXPECTED_MEASURED_LEAK = .366485
- # Because this test is empirical and our testing framework isn't set up
- # to handle tests that fail with some expected likelihood, we bump this
- # value up to decrease the false positive rate.
- EXPECTED_MEASURED_LEAK = .50
-
- REPEATS = 100
- measured_leak = 0
- self.log.info('Start simulation for {} repeats'.format(REPEATS))
+ REPEATS = 10
+ self.log.info('Start test for {} repeats'.format(REPEATS))
for i in range(REPEATS):
self.log.debug('Run {}/{}'.format(i, REPEATS))
txid = gen_node.sendtoaddress(gen_node.getnewaddress(), 0.033)
+
+ time.sleep(5)
+
want_tx = msg_getdata()
want_tx.inv.append(CInv(t=1, h=int(txid, 16)))
-
- wait_until(lambda: txid in outbound_peer.getrawmempool(), lock=mininode_lock)
inbound_peer.send_message(want_tx)
inbound_peer.sync_with_ping()
if inbound_peer.last_message.get('notfound'):
+ self.log.debug('tx {} was not yet announced to us.'.format(txid))
assert_equal(inbound_peer.last_message['notfound'].vec[0].hash, int(txid, 16))
inbound_peer.last_message.pop('notfound')
else:
- measured_leak += 1
-
- measured_leak /= REPEATS
- self.log.info('Measured leak of {}'.format(measured_leak))
-
- assert_greater_than(EXPECTED_MEASURED_LEAK, measured_leak)
+ self.log.debug('tx {} was announced to us.'.format(txid))
+ assert int(txid, 16) in [inv.hash for inv in inbound_peer.last_message['inv'].inv]
if __name__ == '__main__':