/ test / functional / p2p_tx_privacy.py
p2p_tx_privacy.py
 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  
57          tx_originator = self.nodes[0].add_p2p_connection(P2PInterface())
58          spy = self.nodes[0].add_p2p_connection(P2PTxSpy(), wait_for_verack=False)
59          spy.wait_for_verack()
60  
61          # tx_originator sends tx1
62          tx1 = self.wallet.create_self_transfer()["tx"]
63          tx_originator.send_and_ping(msg_tx(tx1))
64  
65          # Spy sends the verack
66          spy.send_and_ping(msg_verack())
67  
68          # tx_originator sends tx2
69          tx2 = self.wallet.create_self_transfer()["tx"]
70          tx_originator.send_and_ping(msg_tx(tx2))
71  
72          # Spy should only get an inv for the second transaction as the first
73          # one was received pre-verack with the spy
74          spy.wait_for_inv_match(CInv(MSG_WTX, tx2.calc_sha256(True)))
75  
76  if __name__ == '__main__':
77      TxPrivacyTest().main()