scripted-diff: Use the C++11 keyword nullptr to denote the pointer literal instead...
[bitcoinplatinum.git] / test / functional / p2p-leaktests.py
blob33b57ef33d8d021b9ebb9b99af214fb76d1484d2
1 #!/usr/bin/env python3
2 # Copyright (c) 2017 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 """Test message sending before handshake completion.
7 A node should never send anything other than VERSION/VERACK/REJECT until it's
8 received a VERACK.
10 This test connects to a node and sends it a few messages, trying to intice it
11 into sending us something it shouldn't.
12 """
14 from test_framework.mininode import *
15 from test_framework.test_framework import BitcoinTestFramework
16 from test_framework.util import *
18 banscore = 10
20 class CLazyNode(NodeConnCB):
21 def __init__(self):
22 super().__init__()
23 self.unexpected_msg = False
24 self.ever_connected = False
26 def bad_message(self, message):
27 self.unexpected_msg = True
28 self.log.info("should not have received message: %s" % message.command)
30 def on_open(self, conn):
31 self.connected = True
32 self.ever_connected = True
34 def on_version(self, conn, message): self.bad_message(message)
35 def on_verack(self, conn, message): self.bad_message(message)
36 def on_reject(self, conn, message): self.bad_message(message)
37 def on_inv(self, conn, message): self.bad_message(message)
38 def on_addr(self, conn, message): self.bad_message(message)
39 def on_alert(self, conn, message): self.bad_message(message)
40 def on_getdata(self, conn, message): self.bad_message(message)
41 def on_getblocks(self, conn, message): self.bad_message(message)
42 def on_tx(self, conn, message): self.bad_message(message)
43 def on_block(self, conn, message): self.bad_message(message)
44 def on_getaddr(self, conn, message): self.bad_message(message)
45 def on_headers(self, conn, message): self.bad_message(message)
46 def on_getheaders(self, conn, message): self.bad_message(message)
47 def on_ping(self, conn, message): self.bad_message(message)
48 def on_mempool(self, conn): self.bad_message(message)
49 def on_pong(self, conn, message): self.bad_message(message)
50 def on_feefilter(self, conn, message): self.bad_message(message)
51 def on_sendheaders(self, conn, message): self.bad_message(message)
52 def on_sendcmpct(self, conn, message): self.bad_message(message)
53 def on_cmpctblock(self, conn, message): self.bad_message(message)
54 def on_getblocktxn(self, conn, message): self.bad_message(message)
55 def on_blocktxn(self, conn, message): self.bad_message(message)
57 # Node that never sends a version. We'll use this to send a bunch of messages
58 # anyway, and eventually get disconnected.
59 class CNodeNoVersionBan(CLazyNode):
60 # send a bunch of veracks without sending a message. This should get us disconnected.
61 # NOTE: implementation-specific check here. Remove if bitcoind ban behavior changes
62 def on_open(self, conn):
63 super().on_open(conn)
64 for i in range(banscore):
65 self.send_message(msg_verack())
67 def on_reject(self, conn, message): pass
69 # Node that never sends a version. This one just sits idle and hopes to receive
70 # any message (it shouldn't!)
71 class CNodeNoVersionIdle(CLazyNode):
72 def __init__(self):
73 super().__init__()
75 # Node that sends a version but not a verack.
76 class CNodeNoVerackIdle(CLazyNode):
77 def __init__(self):
78 self.version_received = False
79 super().__init__()
81 def on_reject(self, conn, message): pass
82 def on_verack(self, conn, message): pass
83 # When version is received, don't reply with a verack. Instead, see if the
84 # node will give us a message that it shouldn't. This is not an exhaustive
85 # list!
86 def on_version(self, conn, message):
87 self.version_received = True
88 conn.send_message(msg_ping())
89 conn.send_message(msg_getaddr())
91 class P2PLeakTest(BitcoinTestFramework):
92 def __init__(self):
93 super().__init__()
94 self.num_nodes = 1
95 self.extra_args = [['-banscore='+str(banscore)]]
97 def run_test(self):
98 no_version_bannode = CNodeNoVersionBan()
99 no_version_idlenode = CNodeNoVersionIdle()
100 no_verack_idlenode = CNodeNoVerackIdle()
102 connections = []
103 connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], no_version_bannode, send_version=False))
104 connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], no_version_idlenode, send_version=False))
105 connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], no_verack_idlenode))
106 no_version_bannode.add_connection(connections[0])
107 no_version_idlenode.add_connection(connections[1])
108 no_verack_idlenode.add_connection(connections[2])
110 NetworkThread().start() # Start up network handling in another thread
112 assert wait_until(lambda: no_version_bannode.ever_connected, timeout=10)
113 assert wait_until(lambda: no_version_idlenode.ever_connected, timeout=10)
114 assert wait_until(lambda: no_verack_idlenode.version_received, timeout=10)
116 # Mine a block and make sure that it's not sent to the connected nodes
117 self.nodes[0].generate(1)
119 #Give the node enough time to possibly leak out a message
120 time.sleep(5)
122 #This node should have been banned
123 assert not no_version_bannode.connected
125 [conn.disconnect_node() for conn in connections]
127 # Make sure no unexpected messages came in
128 assert(no_version_bannode.unexpected_msg == False)
129 assert(no_version_idlenode.unexpected_msg == False)
130 assert(no_verack_idlenode.unexpected_msg == False)
132 if __name__ == '__main__':
133 P2PLeakTest().main()