Skip to content

Commit 759d94e

Browse files
committed
Update zmq notification documentation and sample consumer
1 parent 68c3c7e commit 759d94e

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

contrib/zmq/zmq_sub.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
-zmqpubrawtx=tcp://127.0.0.1:28332 \
1212
-zmqpubrawblock=tcp://127.0.0.1:28332 \
1313
-zmqpubhashtx=tcp://127.0.0.1:28332 \
14-
-zmqpubhashblock=tcp://127.0.0.1:28332
14+
-zmqpubhashblock=tcp://127.0.0.1:28332 \
15+
-zmqpubsequence=tcp://127.0.0.1:28332
1516
1617
We use the asyncio library here. `self.handle()` installs itself as a
1718
future at the end of the function. Since it never returns with the event
@@ -47,16 +48,14 @@ def __init__(self):
4748
self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashtx")
4849
self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawblock")
4950
self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtx")
51+
self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "sequence")
5052
self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % port)
5153

5254
async def handle(self) :
53-
msg = await self.zmqSubSocket.recv_multipart()
54-
topic = msg[0]
55-
body = msg[1]
55+
topic, body, seq = await self.zmqSubSocket.recv_multipart()
5656
sequence = "Unknown"
57-
if len(msg[-1]) == 4:
58-
msgSequence = struct.unpack('<I', msg[-1])[-1]
59-
sequence = str(msgSequence)
57+
if len(seq) == 4:
58+
sequence = str(struct.unpack('<I', seq)[-1])
6059
if topic == b"hashblock":
6160
print('- HASH BLOCK ('+sequence+') -')
6261
print(binascii.hexlify(body))
@@ -69,6 +68,12 @@ async def handle(self) :
6968
elif topic == b"rawtx":
7069
print('- RAW TX ('+sequence+') -')
7170
print(binascii.hexlify(body))
71+
elif topic == b"sequence":
72+
hash = binascii.hexlify(body[:32])
73+
label = chr(body[32])
74+
mempool_sequence = None if len(body) != 32+1+8 else struct.unpack("<Q", body[32+1:])[0]
75+
print('- SEQUENCE ('+sequence+') -')
76+
print(hash, label, mempool_sequence)
7277
# schedule ourselves to receive the next message
7378
asyncio.ensure_future(self.handle())
7479

doc/zmq.md

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ Currently, the following notifications are supported:
6363
-zmqpubhashblock=address
6464
-zmqpubrawblock=address
6565
-zmqpubrawtx=address
66+
-zmqpubsequence=address
6667

6768
The socket type is PUB and the address must be a valid ZeroMQ socket
6869
address. The same address can be used in more than one notification.
@@ -74,6 +75,7 @@ The option to set the PUB socket's outbound message high water mark
7475
-zmqpubhashblockhwm=n
7576
-zmqpubrawblockhwm=n
7677
-zmqpubrawtxhwm=n
78+
-zmqpubsequencehwm=address
7779

7880
The high water mark value must be an integer greater than or equal to 0.
7981

@@ -87,7 +89,15 @@ Each PUB notification has a topic and body, where the header
8789
corresponds to the notification type. For instance, for the
8890
notification `-zmqpubhashtx` the topic is `hashtx` (no null
8991
terminator) and the body is the transaction hash (32
90-
bytes).
92+
bytes) for all but `sequence` topic. For `sequence`, the body
93+
is structured as the following based on the type of message:
94+
95+
<32-byte hash>C : Blockhash connected
96+
<32-byte hash>D : Blockhash disconnected
97+
<32-byte hash>R<8-byte LE uint> : Transactionhash removed from mempool for non-block inclusion reason
98+
<32-byte hash>A<8-byte LE uint> : Transactionhash added mempool
99+
100+
Where the 8-byte uints correspond to the mempool sequence number.
91101

92102
These options can also be provided in bitcoin.conf.
93103

@@ -124,13 +134,20 @@ No authentication or authorization is done on connecting clients; it
124134
is assumed that the ZeroMQ port is exposed only to trusted entities,
125135
using other means such as firewalling.
126136

127-
Note that when the block chain tip changes, a reorganisation may occur
128-
and just the tip will be notified. It is up to the subscriber to
129-
retrieve the chain from the last known block to the new tip. Also note
130-
that no notification occurs if the tip was in the active chain - this
131-
is the case after calling invalidateblock RPC.
137+
Note that for `*block` topics, when the block chain tip changes,
138+
a reorganisation may occur and just the tip will be notified.
139+
It is up to the subscriber to retrieve the chain from the last known
140+
block to the new tip. Also note that no notification will occur if the tip
141+
was in the active chain--as would be the case after calling invalidateblock RPC.
142+
In contrast, the `sequence` topic publishes all block connections and
143+
disconnections.
132144

133145
There are several possibilities that ZMQ notification can get lost
134146
during transmission depending on the communication type you are
135147
using. Bitcoind appends an up-counting sequence number to each
136148
notification which allows listeners to detect lost notifications.
149+
150+
The `sequence` topic refers specifically to the mempool sequence
151+
number, which is also published along with all mempool events. This
152+
is a different sequence value than in ZMQ itself in order to allow a total
153+
ordering of mempool events to be constructed.

0 commit comments

Comments
 (0)