|
1 | 1 | ---
|
2 | 2 | sidebar_position: 3
|
3 | 3 | ---
|
| 4 | + |
4 | 5 | # ZMQ Instructions
|
| 6 | + |
| 7 | +Introducing How to Use ZMQ Functionality and How to Configure It |
| 8 | + |
| 9 | +## Introduction to ZMQ |
| 10 | + |
| 11 | +ZeroMQ is a lightweight messaging queue solution that provides publish-subscribe services via TCP links, inter-process |
| 12 | +communication (IPC), and shared memory. ZeroMQ is known for being lightweight, high-performance, low-latency, supporting |
| 13 | +multiple languages, multiple operating systems, and various messaging patterns. |
| 14 | + |
| 15 | +While the node P2P protocol in MVC can itself serve as a trusted messaging propagation route to facilitate communication |
| 16 | +within the MVC network, make consensus decisions, broadcast transactions, etc., in some scenarios, a more flexible |
| 17 | +messaging queue solution is needed. Applications that need to listen for events like mempool transactions and new blocks |
| 18 | +require real-time and high availability, which are more cumbersome to implement via the P2P protocol and not as |
| 19 | +user-friendly for clients. |
| 20 | + |
| 21 | +Therefore, we have introduced ZeroMQ as a messaging queue solution to provide more flexible messaging services. ZeroMQ |
| 22 | +allows for real-time notifications by subscribing to events of interest, such as listening for new blocks and mempool |
| 23 | +transactions. |
| 24 | + |
| 25 | +## Features of MVC Node ZMQ Push |
| 26 | + |
| 27 | +The ZeroMQ functionality implements a specific set of notification interfaces, primarily including notifiers for new |
| 28 | +blocks and new transactions. Node ZMQ is read-only, requiring only connection to the corresponding ZeroMQ subscription |
| 29 | +port in the receiving software; it does not perform authentication nor does it involve bidirectional protocols. |
| 30 | +Therefore, subscribers should verify the received data (e.g., using merkle proofs, making secondary node RPC |
| 31 | +verifications, etc.), as this data might be outdated, incomplete, or even invalid. |
| 32 | + |
| 33 | +ZeroMQ sockets are self-connecting and self-healing; that is, the connection between two endpoints will automatically |
| 34 | +resume after an interruption, and either end can freely start or stop in any order. |
| 35 | + |
| 36 | +Additionally, because ZeroMQ is message-oriented, the transactions and blocks received by subscribers are one-time |
| 37 | +occurrences and do not require any buffering or reassembly. |
| 38 | + |
| 39 | +## Enabling ZMQ Functionality When Building the Node |
| 40 | + |
| 41 | +When compiling the node, you can specify whether to enable ZMQ functionality. If you need to enable ZMQ, you will need |
| 42 | +to install the libzmq3-dev dependency library on the build machine. The official default binary package already includes |
| 43 | +support for ZMQ. If you are compiling the node yourself and wish to include ZMQ functionality, you can refer to the |
| 44 | +following compile option: |
| 45 | + |
| 46 | +```bash |
| 47 | +$ ./configure --disable-zmq (other options) |
| 48 | +``` |
| 49 | + |
| 50 | +If you are using the default binary package, no additional steps are necessary; you can start the node directly as the |
| 51 | +ZMQ functionality is already installed in the node. |
| 52 | + |
| 53 | +## ZMQ Configuration |
| 54 | + |
| 55 | +ZMQ functionality needs to be configured in the node's configuration file. You can freely choose the port number and the |
| 56 | +types of events to subscribe to. Configure the following in the mvc.conf file (refer to the ZMQ-related content |
| 57 | +in [Startup Options](../installation/start-up-command.md)): |
| 58 | + |
| 59 | +```text |
| 60 | +
|
| 61 | +-zmqpubhashtx=address |
| 62 | +-zmqpubhashblock=address |
| 63 | +-zmqpubrawblock=address |
| 64 | +-zmqpubrawtx=address |
| 65 | +-zmqpubinvalidtx=address |
| 66 | +-zmqpubdiscardedfrommempool=address |
| 67 | +-zmqpubremovedfrommempoolblock=address |
| 68 | +
|
| 69 | +-zmqpubhashtx2=address |
| 70 | +-zmqpubhashblock2=address |
| 71 | +-zmqpubrawblock2=address |
| 72 | +-zmqpubrawtx2=address |
| 73 | +
|
| 74 | +``` |
| 75 | + |
| 76 | +The socket type is PUB, and the address starts with "tcp://" or "ipc://". If you do not need notifications for a |
| 77 | +particular event, you do not need to configure an address for that event. The same address can be used to listen to |
| 78 | +multiple channels. For example: |
| 79 | + |
| 80 | +```bash |
| 81 | +$ mvcd -zmqpubhashtx=tcp://0.0.0.0:29882 -zmqpubhashblock=0.0.0.0:29882 -zmqpubrawtx=ipc:///tmp/mvcd.tx.raw |
| 82 | +``` |
| 83 | + |
| 84 | +Similarly, these configurations can also be set in the mvc.conf file, such as: |
| 85 | + |
| 86 | +```text |
| 87 | +zmqpubhashtx=tcp://0.0.0.0:29882 |
| 88 | +zmqpubhashblock=tcp://0.0.0.0:29882 |
| 89 | +zmqpubrawtx=ipc:///tmp/mvcd.tx.raw |
| 90 | +``` |
| 91 | + |
| 92 | +Each PUB notification comes with a topic and a message body, with the notification type included in the message header. |
| 93 | +For example, the ***zmqpubhashtx*** notification's topic is "hashtx," and the message body is the transaction hash. The |
| 94 | +message body is a 32-byte hexadecimal string, which can be obtained in detail via the node's RPC interface. |
| 95 | + |
| 96 | +Meanwhile, the topics for ***zmqpubdiscardedfrommempool*** and ***zmqpubremovedfrommempoolblock*** notifications are " |
| 97 | +discardedfrommempool" and "removedfrommempoolblock," respectively, and their message bodies are JSON strings: |
| 98 | + |
| 99 | +```json |
| 100 | +{ |
| 101 | + "txid": "hexstring", |
| 102 | + "reason": "string", |
| 103 | + "collidedWith": { |
| 104 | + "txid": "hexstring", |
| 105 | + "size": 100, |
| 106 | + "hex": "hexstring" |
| 107 | + }, |
| 108 | + "blockhash": "hexstring" |
| 109 | +} |
| 110 | +``` |
| 111 | + |
| 112 | +The `collidedWith` field indicates which transaction this transaction conflicted with, and the `blockhash` field |
| 113 | +indicates which block this transaction was included in. |
| 114 | + |
| 115 | +The `reason` field in ***zmqpubdiscardedfrommempool*** indicates why this transaction was discarded, with reasons |
| 116 | +including: |
| 117 | + |
| 118 | +* expired |
| 119 | +* mempool-sizelimit-exceeded |
| 120 | +* collision-in-block-tx |
| 121 | + |
| 122 | +The `reason` field in ***zmqpubremovedfrommempoolblock*** indicates why this transaction was removed from the mempool, |
| 123 | +with reasons including: |
| 124 | + |
| 125 | +* reorg |
| 126 | +* included-in-block |
| 127 | + |
| 128 | +***zmqpub2*** |
| 129 | +(such as zmqpubhashtx2 and other suffixes ending with 2) functions similarly to their non-suffix counterparts, the only |
| 130 | +difference being that they no longer push duplicate messages. For example, the original zmqpubhashtx would push messages |
| 131 | +twice, both when entering the mempool and when being packaged into a block, whereas zmqpubhashtx2 pushes only once. |
| 132 | +Additionally, in the event of a reorganization, the entire reorganization chain is pushed, not just the tip. |
| 133 | + |
| 134 | +## Remarks |
| 135 | + |
| 136 | +From the perspective of `mvcd`, ZeroMQ sockets are write-only; PUB sockets do not even have a read function. Therefore, |
| 137 | +they do not directly introduce any state into MVC. Additionally, MVC does not broadcast any information that has not |
| 138 | +been received from the public P2P network. |
| 139 | + |
| 140 | +When connecting clients, no authentication or authorization is performed; thus, it is crucial to ensure that the ZeroMQ |
| 141 | +ports are open only to trusted networks and are protected by firewalls or other means. |
| 142 | + |
| 143 | +Please note that reorganizations can occur when the highest point of the blockchain changes, and only the highest point |
| 144 | +will be notified. Subscribers need to retrieve from the last known block to the new highest point. |
| 145 | + |
| 146 | +Depending on the type of communication used, ZMQ notifications may be lost during transmission. MVC includes an |
| 147 | +incrementing sequence number in each notification, allowing listeners to detect missing notifications. |
| 148 | + |
| 149 | +## Practice: Using a ZMQ Client to Listen for ZMQ Events |
| 150 | + |
| 151 | +This example uses Python to demonstrate how to use a ZMQ client to listen for ZMQ events. |
| 152 | + |
| 153 | +Ensure that your local system has installed the ZMQ and Python libraries and that the ZMQ port is open. |
| 154 | + |
| 155 | +Install Python3 and related dependencies: |
| 156 | + |
| 157 | +```bash |
| 158 | +sudo apt update |
| 159 | +sudo apt install python3 |
| 160 | +sudo apt install python3-pip |
| 161 | +sudo apt install libzmq3-dev python3-zmq |
| 162 | +pip3 install pyzmq |
| 163 | +``` |
| 164 | + |
| 165 | +Create the following Python file ***zmq_subscriber.py***. The code below listens to the local ZMQ port, listens to the |
| 166 | +hashtx channel, and prints the data received: |
| 167 | + |
| 168 | +```python |
| 169 | +# File: zmq_subscriber.py |
| 170 | +import zmq |
| 171 | + |
| 172 | +# Prepare our context and subscriber socket |
| 173 | +context = zmq.Context() |
| 174 | +socket = context.socket(zmq.SUB) |
| 175 | + |
| 176 | +# Connect to the publisher's socket |
| 177 | +# Adjust the address and port accordingly |
| 178 | +socket.connect("tcp://localhost:28332") |
| 179 | + |
| 180 | +# Subscribe to all messages |
| 181 | +socket.setsockopt_string(zmq.SUBSCRIBE, 'hashtx') |
| 182 | + |
| 183 | +# Receive messages as bytes |
| 184 | +while True: |
| 185 | + message = socket.recv() # Use recv instead of recv_string |
| 186 | + try: |
| 187 | + # Attempt to decode as UTF-8, or handle as binary data |
| 188 | + print("Received:", message.decode('utf-8')) |
| 189 | + except UnicodeDecodeError: |
| 190 | + hex_message = message.hex() # Convert bytes to hex string |
| 191 | + print("Received:", hex_message) |
| 192 | +``` |
| 193 | + |
| 194 | +If the program is correctly configured and running successfully, you will see the following output: |
| 195 | + |
| 196 | +```bash |
| 197 | +Received: hashtx |
| 198 | +Received: 679b984049c2b8aeff04291f32415b9346429867e6ae69b4b9569b52fa85ea42 |
| 199 | +Received: 3fab0700 |
| 200 | +Received: hashtx |
| 201 | +Received: fbe397992b8ce963792a65c91aa9a32c8afb836e15b464ecf7fffd8af450baa9 |
| 202 | +Received: 40ab0700 |
| 203 | +Received: hashtx |
| 204 | +Received: f2153a5a34707f57c21f6c3dc335a30c095be59a53ed5cd0df0af0383d2677db |
| 205 | +Received: 41ab0700 |
| 206 | +Received: hashtx |
| 207 | +Received: 365ec39e879ccf6b70a64432064a98f782b1998cd26dccc0ad630b503e95edb6 |
| 208 | +Received: 42ab0700 |
| 209 | +Received: hashtx |
| 210 | +Received: 94dda55fc6fe14c05bdb31feead994d6dd9bbec6ea5b95842dadfe9d490f8841 |
| 211 | +Received: 43ab0700 |
| 212 | +Received: hashtx |
| 213 | +Received: b3cfde1630610903c17a73bb871c008c3f3cc7bcdbeed2185f55ec3a96901ef9 |
| 214 | +Received: 44ab0700 |
| 215 | +Received: hashtx |
| 216 | +Received: fb1937d2fe7f1b5bc0252acb88bde3123fdc32800f385562c02ed3bbb5f7fd3b |
| 217 | +Received: 45ab0700 |
| 218 | +Received: hashtx |
| 219 | +Received: 03123d1aa0f40965eecede4c1dd7531df7dfc87c55ac06264b0d7c90203acdc7 |
| 220 | +Received: 46ab0700 |
| 221 | +Received: hashtx |
| 222 | +Received: 0b8ddf99ea66f522319f8f8e7aa6c439b44c3b1fff79a41c58356447a7283654 |
| 223 | +Received: 47ab0700 |
| 224 | +Received: hashtx |
| 225 | +Received: bae9ca06c4fa9dc50756aded981d36d78f301e9e80b14e6031464c36e4a8d28b |
| 226 | +Received: 48ab0700 |
| 227 | +Received: hashtx |
| 228 | +Received: 5f4b4d0ff3c595188041c2a1abc00612aad3151ed845c62a9fb41a71214f4ad5 |
| 229 | +Received: 49ab0700 |
| 230 | +Received: hashtx |
| 231 | +Received: 078f211de0a24a37379199fdda9bdc54323e798899edfadcfeacb834fa2a54c0 |
| 232 | +Received: 4aab0700 |
| 233 | +``` |
| 234 | + |
| 235 | +The message includes messages from the hashtx channel, the message body, and the transaction hash (real transaction, can |
| 236 | +be confirmed on-chain), as well as an additional continuous sequence to detect missing messages. You can also set up to |
| 237 | +listen to other channels and print output for debugging. |
| 238 | + |
0 commit comments