diff options
author | Gregory Sanders <gsanders87@gmail.com> | 2020-09-01 15:14:58 -0400 |
---|---|---|
committer | Gregory Sanders <gsanders87@gmail.com> | 2020-09-22 11:34:30 -0400 |
commit | 759d94e70f6844443106404882c7b105f3a4dba7 (patch) | |
tree | 21d8c98214a1e6e24c86f42fbe6d1ef8b59d634e | |
parent | 68c3c7e1bdd00bbe7d70592a8eb39520fa3f87f1 (diff) |
Update zmq notification documentation and sample consumer
-rwxr-xr-x | contrib/zmq/zmq_sub.py | 19 | ||||
-rw-r--r-- | doc/zmq.md | 29 |
2 files changed, 35 insertions, 13 deletions
diff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py index 06893407f5..8b8503331d 100755 --- a/contrib/zmq/zmq_sub.py +++ b/contrib/zmq/zmq_sub.py @@ -11,7 +11,8 @@ -zmqpubrawtx=tcp://127.0.0.1:28332 \ -zmqpubrawblock=tcp://127.0.0.1:28332 \ -zmqpubhashtx=tcp://127.0.0.1:28332 \ - -zmqpubhashblock=tcp://127.0.0.1:28332 + -zmqpubhashblock=tcp://127.0.0.1:28332 \ + -zmqpubsequence=tcp://127.0.0.1:28332 We use the asyncio library here. `self.handle()` installs itself as a future at the end of the function. Since it never returns with the event @@ -47,16 +48,14 @@ class ZMQHandler(): self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashtx") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawblock") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtx") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "sequence") self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % port) async def handle(self) : - msg = await self.zmqSubSocket.recv_multipart() - topic = msg[0] - body = msg[1] + topic, body, seq = await self.zmqSubSocket.recv_multipart() sequence = "Unknown" - if len(msg[-1]) == 4: - msgSequence = struct.unpack('<I', msg[-1])[-1] - sequence = str(msgSequence) + if len(seq) == 4: + sequence = str(struct.unpack('<I', seq)[-1]) if topic == b"hashblock": print('- HASH BLOCK ('+sequence+') -') print(binascii.hexlify(body)) @@ -69,6 +68,12 @@ class ZMQHandler(): elif topic == b"rawtx": print('- RAW TX ('+sequence+') -') print(binascii.hexlify(body)) + elif topic == b"sequence": + hash = binascii.hexlify(body[:32]) + label = chr(body[32]) + mempool_sequence = None if len(body) != 32+1+8 else struct.unpack("<Q", body[32+1:])[0] + print('- SEQUENCE ('+sequence+') -') + print(hash, label, mempool_sequence) # schedule ourselves to receive the next message asyncio.ensure_future(self.handle()) diff --git a/doc/zmq.md b/doc/zmq.md index 835dea23f2..f003c90d3a 100644 --- a/doc/zmq.md +++ b/doc/zmq.md @@ -63,6 +63,7 @@ Currently, the following notifications are supported: -zmqpubhashblock=address -zmqpubrawblock=address -zmqpubrawtx=address + -zmqpubsequence=address The socket type is PUB and the address must be a valid ZeroMQ socket 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 -zmqpubhashblockhwm=n -zmqpubrawblockhwm=n -zmqpubrawtxhwm=n + -zmqpubsequencehwm=address The high water mark value must be an integer greater than or equal to 0. @@ -87,7 +89,15 @@ Each PUB notification has a topic and body, where the header corresponds to the notification type. For instance, for the notification `-zmqpubhashtx` the topic is `hashtx` (no null terminator) and the body is the transaction hash (32 -bytes). +bytes) for all but `sequence` topic. For `sequence`, the body +is structured as the following based on the type of message: + + <32-byte hash>C : Blockhash connected + <32-byte hash>D : Blockhash disconnected + <32-byte hash>R<8-byte LE uint> : Transactionhash removed from mempool for non-block inclusion reason + <32-byte hash>A<8-byte LE uint> : Transactionhash added mempool + +Where the 8-byte uints correspond to the mempool sequence number. These options can also be provided in bitcoin.conf. @@ -124,13 +134,20 @@ No authentication or authorization is done on connecting clients; it is assumed that the ZeroMQ port is exposed only to trusted entities, using other means such as firewalling. -Note that when the block chain tip changes, a reorganisation may occur -and just the tip will be notified. It is up to the subscriber to -retrieve the chain from the last known block to the new tip. Also note -that no notification occurs if the tip was in the active chain - this -is the case after calling invalidateblock RPC. +Note that for `*block` topics, when the block chain tip changes, +a reorganisation may occur and just the tip will be notified. +It is up to the subscriber to retrieve the chain from the last known +block to the new tip. Also note that no notification will occur if the tip +was in the active chain--as would be the case after calling invalidateblock RPC. +In contrast, the `sequence` topic publishes all block connections and +disconnections. There are several possibilities that ZMQ notification can get lost during transmission depending on the communication type you are using. Bitcoind appends an up-counting sequence number to each notification which allows listeners to detect lost notifications. + +The `sequence` topic refers specifically to the mempool sequence +number, which is also published along with all mempool events. This +is a different sequence value than in ZMQ itself in order to allow a total +ordering of mempool events to be constructed. |