Skip to content

Commit 8f2dac5

Browse files
committed
[test] Add p2p_tx_privacy.py
1 parent ce63fca commit 8f2dac5

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

test/functional/p2p_tx_privacy.py

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2022 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
"""
6+
Test that transaction announcements are only queued for peers that have
7+
successfully completed the version handshake.
8+
9+
Topology:
10+
11+
tx_originator ----> node[0] <---- spy
12+
13+
We test that a transaction sent by tx_originator is only relayed to spy
14+
if it was received after spy's version handshake completed.
15+
16+
1. Fully connect tx_originator
17+
2. Connect spy (no version handshake)
18+
3. tx_originator sends tx1
19+
4. spy completes the version handshake
20+
5. tx_originator sends tx2
21+
6. We check that only tx2 is announced on the spy interface
22+
"""
23+
from test_framework.messages import (
24+
msg_wtxidrelay,
25+
msg_verack,
26+
msg_tx,
27+
CInv,
28+
MSG_WTX,
29+
)
30+
from test_framework.p2p import (
31+
P2PInterface,
32+
)
33+
from test_framework.test_framework import BitcoinTestFramework
34+
from test_framework.wallet import MiniWallet
35+
36+
class P2PTxSpy(P2PInterface):
37+
def __init__(self):
38+
super().__init__()
39+
self.all_invs = []
40+
41+
def on_version(self, message):
42+
self.send_message(msg_wtxidrelay())
43+
44+
def on_inv(self, message):
45+
self.all_invs += message.inv
46+
47+
def wait_for_inv_match(self, expected_inv):
48+
self.wait_until(lambda: len(self.all_invs) == 1 and self.all_invs[0] == expected_inv)
49+
50+
class TxPrivacyTest(BitcoinTestFramework):
51+
def set_test_params(self):
52+
self.num_nodes = 1
53+
54+
def run_test(self):
55+
self.wallet = MiniWallet(self.nodes[0])
56+
self.wallet.rescan_utxos()
57+
58+
tx_originator = self.nodes[0].add_p2p_connection(P2PInterface())
59+
spy = self.nodes[0].add_p2p_connection(P2PTxSpy(), wait_for_verack=False)
60+
spy.wait_for_verack()
61+
62+
# tx_originator sends tx1
63+
tx1 = self.wallet.create_self_transfer()["tx"]
64+
tx_originator.send_and_ping(msg_tx(tx1))
65+
66+
# Spy sends the verack
67+
spy.send_and_ping(msg_verack())
68+
69+
# tx_originator sends tx2
70+
tx2 = self.wallet.create_self_transfer()["tx"]
71+
tx_originator.send_and_ping(msg_tx(tx2))
72+
73+
# Spy should only get an inv for the second transaction as the first
74+
# one was received pre-verack with the spy
75+
spy.wait_for_inv_match(CInv(MSG_WTX, tx2.calc_sha256(True)))
76+
77+
if __name__ == '__main__':
78+
TxPrivacyTest().main()

test/functional/test_runner.py

+1
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@
318318
'rpc_deriveaddresses.py',
319319
'rpc_deriveaddresses.py --usecli',
320320
'p2p_ping.py',
321+
'p2p_tx_privacy.py',
321322
'rpc_scanblocks.py',
322323
'p2p_sendtxrcncl.py',
323324
'rpc_scantxoutset.py',

0 commit comments

Comments
 (0)