|
1 |
| -#!/usr/bin/env python2 |
| 1 | +#!/usr/bin/env python3 |
2 | 2 | # Copyright (c) 2014-2016 The Bitcoin Core developers
|
3 | 3 | # Distributed under the MIT software license, see the accompanying
|
4 | 4 | # file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
5 | 5 |
|
| 6 | +""" |
| 7 | + ZMQ example using python3's asyncio |
| 8 | +
|
| 9 | + Bitcoin should be started with the command line arguments: |
| 10 | + bitcoind -testnet -daemon \ |
| 11 | + -zmqpubhashblock=tcp://127.0.0.1:28332 \ |
| 12 | + -zmqpubrawtx=tcp://127.0.0.1:28332 \ |
| 13 | + -zmqpubhashtx=tcp://127.0.0.1:28332 \ |
| 14 | + -zmqpubhashblock=tcp://127.0.0.1:28332 |
| 15 | +
|
| 16 | + We use the asyncio library here. `self.handle()` installs itself as a |
| 17 | + future at the end of the function. Since it never returns with the event |
| 18 | + loop having an empty stack of futures, this creates an infinite loop. An |
| 19 | + alternative is to wrap the contents of `handle` inside `while True`. |
| 20 | +
|
| 21 | + A blocking example using python 2.7 can be obtained from the git history: |
| 22 | + https://github.com/bitcoin/bitcoin/blob/37a7fe9e440b83e2364d5498931253937abe9294/contrib/zmq/zmq_sub.py |
| 23 | +""" |
| 24 | + |
6 | 25 | import binascii
|
| 26 | +import asyncio |
7 | 27 | import zmq
|
| 28 | +import zmq.asyncio |
| 29 | +import signal |
8 | 30 | import struct
|
| 31 | +import sys |
| 32 | + |
| 33 | +if not (sys.version_info.major >= 3 and sys.version_info.minor >= 5): |
| 34 | + print("This example only works with Python 3.5 and greater") |
| 35 | + exit(1) |
9 | 36 |
|
10 | 37 | port = 28332
|
11 | 38 |
|
12 |
| -zmqContext = zmq.Context() |
13 |
| -zmqSubSocket = zmqContext.socket(zmq.SUB) |
14 |
| -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashblock") |
15 |
| -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashtx") |
16 |
| -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "rawblock") |
17 |
| -zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "rawtx") |
18 |
| -zmqSubSocket.connect("tcp://127.0.0.1:%i" % port) |
19 |
| - |
20 |
| -try: |
21 |
| - while True: |
22 |
| - msg = zmqSubSocket.recv_multipart() |
23 |
| - topic = str(msg[0]) |
| 39 | +class ZMQHandler(): |
| 40 | + def __init__(self): |
| 41 | + self.loop = zmq.asyncio.install() |
| 42 | + self.zmqContext = zmq.asyncio.Context() |
| 43 | + |
| 44 | + self.zmqSubSocket = self.zmqContext.socket(zmq.SUB) |
| 45 | + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashblock") |
| 46 | + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashtx") |
| 47 | + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawblock") |
| 48 | + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtx") |
| 49 | + self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % port) |
| 50 | + |
| 51 | + async def handle(self) : |
| 52 | + msg = await self.zmqSubSocket.recv_multipart() |
| 53 | + topic = msg[0] |
24 | 54 | body = msg[1]
|
25 | 55 | sequence = "Unknown"
|
26 | 56 | if len(msg[-1]) == 4:
|
27 | 57 | msgSequence = struct.unpack('<I', msg[-1])[-1]
|
28 | 58 | sequence = str(msgSequence)
|
29 |
| - if topic == "hashblock": |
30 |
| - print '- HASH BLOCK ('+sequence+') -' |
31 |
| - print binascii.hexlify(body) |
32 |
| - elif topic == "hashtx": |
33 |
| - print '- HASH TX ('+sequence+') -' |
34 |
| - print binascii.hexlify(body) |
35 |
| - elif topic == "rawblock": |
36 |
| - print '- RAW BLOCK HEADER ('+sequence+') -' |
37 |
| - print binascii.hexlify(body[:80]) |
38 |
| - elif topic == "rawtx": |
39 |
| - print '- RAW TX ('+sequence+') -' |
40 |
| - print binascii.hexlify(body) |
41 |
| - |
42 |
| -except KeyboardInterrupt: |
43 |
| - zmqContext.destroy() |
| 59 | + if topic == b"hashblock": |
| 60 | + print('- HASH BLOCK ('+sequence+') -') |
| 61 | + print(binascii.hexlify(body)) |
| 62 | + elif topic == b"hashtx": |
| 63 | + print('- HASH TX ('+sequence+') -') |
| 64 | + print(binascii.hexlify(body)) |
| 65 | + elif topic == b"rawblock": |
| 66 | + print('- RAW BLOCK HEADER ('+sequence+') -') |
| 67 | + print(binascii.hexlify(body[:80])) |
| 68 | + elif topic == b"rawtx": |
| 69 | + print('- RAW TX ('+sequence+') -') |
| 70 | + print(binascii.hexlify(body)) |
| 71 | + # schedule ourselves to receive the next message |
| 72 | + asyncio.ensure_future(self.handle()) |
| 73 | + |
| 74 | + def start(self): |
| 75 | + self.loop.add_signal_handler(signal.SIGINT, self.stop) |
| 76 | + self.loop.create_task(self.handle()) |
| 77 | + self.loop.run_forever() |
| 78 | + |
| 79 | + def stop(self): |
| 80 | + self.loop.stop() |
| 81 | + self.zmqContext.destroy() |
| 82 | + |
| 83 | +daemon = ZMQHandler() |
| 84 | +daemon.start() |
0 commit comments