|
56 | 56 | "regtest": b"\xfa\xbf\xb5\xda", # regtest
|
57 | 57 | }
|
58 | 58 |
|
59 |
| -class NodeConnCB(): |
60 |
| - """Callback and helper functions for P2P connection to a bitcoind node. |
61 |
| -
|
62 |
| - Individual testcases should subclass this and override the on_* methods |
63 |
| - if they want to alter message handling behaviour.""" |
64 |
| - def __init__(self): |
65 |
| - # Track whether we have a P2P connection open to the node |
66 |
| - self.connected = False |
67 |
| - self.connection = None |
68 |
| - |
69 |
| - # Track number of messages of each type received and the most recent |
70 |
| - # message of each type |
71 |
| - self.message_count = defaultdict(int) |
72 |
| - self.last_message = {} |
73 |
| - |
74 |
| - # A count of the number of ping messages we've sent to the node |
75 |
| - self.ping_counter = 1 |
76 |
| - |
77 |
| - # Message receiving methods |
78 |
| - |
79 |
| - def on_message(self, conn, message): |
80 |
| - """Receive message and dispatch message to appropriate callback. |
81 |
| -
|
82 |
| - We keep a count of how many of each message type has been received |
83 |
| - and the most recent message of each type.""" |
84 |
| - with mininode_lock: |
85 |
| - try: |
86 |
| - command = message.command.decode('ascii') |
87 |
| - self.message_count[command] += 1 |
88 |
| - self.last_message[command] = message |
89 |
| - getattr(self, 'on_' + command)(conn, message) |
90 |
| - except: |
91 |
| - print("ERROR delivering %s (%s)" % (repr(message), |
92 |
| - sys.exc_info()[0])) |
93 |
| - raise |
94 |
| - |
95 |
| - # Callback methods. Can be overridden by subclasses in individual test |
96 |
| - # cases to provide custom message handling behaviour. |
97 |
| - |
98 |
| - def on_open(self, conn): |
99 |
| - self.connected = True |
100 |
| - |
101 |
| - def on_close(self, conn): |
102 |
| - self.connected = False |
103 |
| - self.connection = None |
104 |
| - |
105 |
| - def on_addr(self, conn, message): pass |
106 |
| - def on_block(self, conn, message): pass |
107 |
| - def on_blocktxn(self, conn, message): pass |
108 |
| - def on_cmpctblock(self, conn, message): pass |
109 |
| - def on_feefilter(self, conn, message): pass |
110 |
| - def on_getaddr(self, conn, message): pass |
111 |
| - def on_getblocks(self, conn, message): pass |
112 |
| - def on_getblocktxn(self, conn, message): pass |
113 |
| - def on_getdata(self, conn, message): pass |
114 |
| - def on_getheaders(self, conn, message): pass |
115 |
| - def on_headers(self, conn, message): pass |
116 |
| - def on_mempool(self, conn): pass |
117 |
| - def on_pong(self, conn, message): pass |
118 |
| - def on_reject(self, conn, message): pass |
119 |
| - def on_sendcmpct(self, conn, message): pass |
120 |
| - def on_sendheaders(self, conn, message): pass |
121 |
| - def on_tx(self, conn, message): pass |
122 |
| - |
123 |
| - def on_inv(self, conn, message): |
124 |
| - want = msg_getdata() |
125 |
| - for i in message.inv: |
126 |
| - if i.type != 0: |
127 |
| - want.inv.append(i) |
128 |
| - if len(want.inv): |
129 |
| - conn.send_message(want) |
130 |
| - |
131 |
| - def on_ping(self, conn, message): |
132 |
| - conn.send_message(msg_pong(message.nonce)) |
133 |
| - |
134 |
| - def on_verack(self, conn, message): |
135 |
| - self.verack_received = True |
136 |
| - |
137 |
| - def on_version(self, conn, message): |
138 |
| - assert message.nVersion >= MIN_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format(message.nVersion, MIN_VERSION_SUPPORTED) |
139 |
| - conn.send_message(msg_verack()) |
140 |
| - conn.nServices = message.nServices |
141 |
| - |
142 |
| - # Connection helper methods |
143 |
| - |
144 |
| - def add_connection(self, conn): |
145 |
| - self.connection = conn |
146 |
| - |
147 |
| - def wait_for_disconnect(self, timeout=60): |
148 |
| - test_function = lambda: not self.connected |
149 |
| - wait_until(test_function, timeout=timeout, lock=mininode_lock) |
150 |
| - |
151 |
| - # Message receiving helper methods |
152 |
| - |
153 |
| - def wait_for_block(self, blockhash, timeout=60): |
154 |
| - test_function = lambda: self.last_message.get("block") and self.last_message["block"].block.rehash() == blockhash |
155 |
| - wait_until(test_function, timeout=timeout, lock=mininode_lock) |
156 |
| - |
157 |
| - def wait_for_getdata(self, timeout=60): |
158 |
| - test_function = lambda: self.last_message.get("getdata") |
159 |
| - wait_until(test_function, timeout=timeout, lock=mininode_lock) |
160 |
| - |
161 |
| - def wait_for_getheaders(self, timeout=60): |
162 |
| - test_function = lambda: self.last_message.get("getheaders") |
163 |
| - wait_until(test_function, timeout=timeout, lock=mininode_lock) |
164 |
| - |
165 |
| - def wait_for_inv(self, expected_inv, timeout=60): |
166 |
| - """Waits for an INV message and checks that the first inv object in the message was as expected.""" |
167 |
| - if len(expected_inv) > 1: |
168 |
| - raise NotImplementedError("wait_for_inv() will only verify the first inv object") |
169 |
| - test_function = lambda: self.last_message.get("inv") and \ |
170 |
| - self.last_message["inv"].inv[0].type == expected_inv[0].type and \ |
171 |
| - self.last_message["inv"].inv[0].hash == expected_inv[0].hash |
172 |
| - wait_until(test_function, timeout=timeout, lock=mininode_lock) |
173 |
| - |
174 |
| - def wait_for_verack(self, timeout=60): |
175 |
| - test_function = lambda: self.message_count["verack"] |
176 |
| - wait_until(test_function, timeout=timeout, lock=mininode_lock) |
177 |
| - |
178 |
| - # Message sending helper functions |
179 |
| - |
180 |
| - def send_message(self, message): |
181 |
| - if self.connection: |
182 |
| - self.connection.send_message(message) |
183 |
| - else: |
184 |
| - logger.error("Cannot send message. No connection to node!") |
185 |
| - |
186 |
| - def send_and_ping(self, message): |
187 |
| - self.send_message(message) |
188 |
| - self.sync_with_ping() |
189 |
| - |
190 |
| - # Sync up with the node |
191 |
| - def sync_with_ping(self, timeout=60): |
192 |
| - self.send_message(msg_ping(nonce=self.ping_counter)) |
193 |
| - test_function = lambda: self.last_message.get("pong") and self.last_message["pong"].nonce == self.ping_counter |
194 |
| - wait_until(test_function, timeout=timeout, lock=mininode_lock) |
195 |
| - self.ping_counter += 1 |
196 |
| - |
197 | 59 | class NodeConn(asyncore.dispatcher):
|
198 | 60 | """The actual NodeConn class
|
199 | 61 |
|
@@ -376,6 +238,145 @@ def _log_message(self, direction, msg):
|
376 | 238 | logger.debug(log_message)
|
377 | 239 |
|
378 | 240 |
|
| 241 | +class NodeConnCB(): |
| 242 | + """Callback and helper functions for P2P connection to a bitcoind node. |
| 243 | +
|
| 244 | + Individual testcases should subclass this and override the on_* methods |
| 245 | + if they want to alter message handling behaviour.""" |
| 246 | + def __init__(self): |
| 247 | + # Track whether we have a P2P connection open to the node |
| 248 | + self.connected = False |
| 249 | + self.connection = None |
| 250 | + |
| 251 | + # Track number of messages of each type received and the most recent |
| 252 | + # message of each type |
| 253 | + self.message_count = defaultdict(int) |
| 254 | + self.last_message = {} |
| 255 | + |
| 256 | + # A count of the number of ping messages we've sent to the node |
| 257 | + self.ping_counter = 1 |
| 258 | + |
| 259 | + # Message receiving methods |
| 260 | + |
| 261 | + def on_message(self, conn, message): |
| 262 | + """Receive message and dispatch message to appropriate callback. |
| 263 | +
|
| 264 | + We keep a count of how many of each message type has been received |
| 265 | + and the most recent message of each type.""" |
| 266 | + with mininode_lock: |
| 267 | + try: |
| 268 | + command = message.command.decode('ascii') |
| 269 | + self.message_count[command] += 1 |
| 270 | + self.last_message[command] = message |
| 271 | + getattr(self, 'on_' + command)(conn, message) |
| 272 | + except: |
| 273 | + print("ERROR delivering %s (%s)" % (repr(message), |
| 274 | + sys.exc_info()[0])) |
| 275 | + raise |
| 276 | + |
| 277 | + # Callback methods. Can be overridden by subclasses in individual test |
| 278 | + # cases to provide custom message handling behaviour. |
| 279 | + |
| 280 | + def on_open(self, conn): |
| 281 | + self.connected = True |
| 282 | + |
| 283 | + def on_close(self, conn): |
| 284 | + self.connected = False |
| 285 | + self.connection = None |
| 286 | + |
| 287 | + def on_addr(self, conn, message): pass |
| 288 | + def on_block(self, conn, message): pass |
| 289 | + def on_blocktxn(self, conn, message): pass |
| 290 | + def on_cmpctblock(self, conn, message): pass |
| 291 | + def on_feefilter(self, conn, message): pass |
| 292 | + def on_getaddr(self, conn, message): pass |
| 293 | + def on_getblocks(self, conn, message): pass |
| 294 | + def on_getblocktxn(self, conn, message): pass |
| 295 | + def on_getdata(self, conn, message): pass |
| 296 | + def on_getheaders(self, conn, message): pass |
| 297 | + def on_headers(self, conn, message): pass |
| 298 | + def on_mempool(self, conn): pass |
| 299 | + def on_pong(self, conn, message): pass |
| 300 | + def on_reject(self, conn, message): pass |
| 301 | + def on_sendcmpct(self, conn, message): pass |
| 302 | + def on_sendheaders(self, conn, message): pass |
| 303 | + def on_tx(self, conn, message): pass |
| 304 | + |
| 305 | + def on_inv(self, conn, message): |
| 306 | + want = msg_getdata() |
| 307 | + for i in message.inv: |
| 308 | + if i.type != 0: |
| 309 | + want.inv.append(i) |
| 310 | + if len(want.inv): |
| 311 | + conn.send_message(want) |
| 312 | + |
| 313 | + def on_ping(self, conn, message): |
| 314 | + conn.send_message(msg_pong(message.nonce)) |
| 315 | + |
| 316 | + def on_verack(self, conn, message): |
| 317 | + self.verack_received = True |
| 318 | + |
| 319 | + def on_version(self, conn, message): |
| 320 | + assert message.nVersion >= MIN_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format(message.nVersion, MIN_VERSION_SUPPORTED) |
| 321 | + conn.send_message(msg_verack()) |
| 322 | + conn.nServices = message.nServices |
| 323 | + |
| 324 | + # Connection helper methods |
| 325 | + |
| 326 | + def add_connection(self, conn): |
| 327 | + self.connection = conn |
| 328 | + |
| 329 | + def wait_for_disconnect(self, timeout=60): |
| 330 | + test_function = lambda: not self.connected |
| 331 | + wait_until(test_function, timeout=timeout, lock=mininode_lock) |
| 332 | + |
| 333 | + # Message receiving helper methods |
| 334 | + |
| 335 | + def wait_for_block(self, blockhash, timeout=60): |
| 336 | + test_function = lambda: self.last_message.get("block") and self.last_message["block"].block.rehash() == blockhash |
| 337 | + wait_until(test_function, timeout=timeout, lock=mininode_lock) |
| 338 | + |
| 339 | + def wait_for_getdata(self, timeout=60): |
| 340 | + test_function = lambda: self.last_message.get("getdata") |
| 341 | + wait_until(test_function, timeout=timeout, lock=mininode_lock) |
| 342 | + |
| 343 | + def wait_for_getheaders(self, timeout=60): |
| 344 | + test_function = lambda: self.last_message.get("getheaders") |
| 345 | + wait_until(test_function, timeout=timeout, lock=mininode_lock) |
| 346 | + |
| 347 | + def wait_for_inv(self, expected_inv, timeout=60): |
| 348 | + """Waits for an INV message and checks that the first inv object in the message was as expected.""" |
| 349 | + if len(expected_inv) > 1: |
| 350 | + raise NotImplementedError("wait_for_inv() will only verify the first inv object") |
| 351 | + test_function = lambda: self.last_message.get("inv") and \ |
| 352 | + self.last_message["inv"].inv[0].type == expected_inv[0].type and \ |
| 353 | + self.last_message["inv"].inv[0].hash == expected_inv[0].hash |
| 354 | + wait_until(test_function, timeout=timeout, lock=mininode_lock) |
| 355 | + |
| 356 | + def wait_for_verack(self, timeout=60): |
| 357 | + test_function = lambda: self.message_count["verack"] |
| 358 | + wait_until(test_function, timeout=timeout, lock=mininode_lock) |
| 359 | + |
| 360 | + # Message sending helper functions |
| 361 | + |
| 362 | + def send_message(self, message): |
| 363 | + if self.connection: |
| 364 | + self.connection.send_message(message) |
| 365 | + else: |
| 366 | + logger.error("Cannot send message. No connection to node!") |
| 367 | + |
| 368 | + def send_and_ping(self, message): |
| 369 | + self.send_message(message) |
| 370 | + self.sync_with_ping() |
| 371 | + |
| 372 | + # Sync up with the node |
| 373 | + def sync_with_ping(self, timeout=60): |
| 374 | + self.send_message(msg_ping(nonce=self.ping_counter)) |
| 375 | + test_function = lambda: self.last_message.get("pong") and self.last_message["pong"].nonce == self.ping_counter |
| 376 | + wait_until(test_function, timeout=timeout, lock=mininode_lock) |
| 377 | + self.ping_counter += 1 |
| 378 | + |
| 379 | + |
379 | 380 | # Keep our own socket map for asyncore, so that we can track disconnects
|
380 | 381 | # ourselves (to workaround an issue with closing an asyncore socket when
|
381 | 382 | # using select)
|
|
0 commit comments