使用 ZeroMQ 进行区块和交易广播

  • bitcoin
  • 发布于 2025-05-30 20:56
  • 阅读 13

本文档介绍了如何在 Bitcoin Core 中使用 ZeroMQ (ZeroMQ) 接口来订阅新区块和交易的通知。通过配置 Bitcoin Core 守护进程作为可信的“边界路由器”,并启用相应的 ZeroMQ 选项,可以实现对区块和交易的实时监控。文档详细描述了 ZeroMQ 的启用方式、配置选项以及消息格式,并提供了一个 Python 客户端示例。

使用 ZeroMQ 进行区块和交易广播

ZeroMQ 是 TCP 连接、进程间通信和共享内存的轻量级封装, 提供各种面向消息的语义,例如发布/订阅、请求/回复和推送/拉取。

Bitcoin Core 守护程序可以配置为充当受信任的“边界路由器”,实现比特币网络协议和中继,做出共识决策,维护本地区块链数据库,将本地生成的交易广播到网络中,并提供可查询的 RPC 接口,以轮询方式交互来请求区块链相关数据。 然而,只有有限的服务可以通知外部软件有关新区块或交易到达之类的事件。

ZeroMQ 设备通过一组特定的通知器来实现通知接口。 目前,存在发布区块和交易的通知器。 这个只读设备只需要在接收软件中连接相应的 ZeroMQ 订阅端口; 它未经身份验证,也没有任何双向协议参与。 因此,订阅者应验证收到的数据,因为它可能已过期、不完整甚至无效。

ZeroMQ 套接字是自连接和自修复的; 也就是说,两个端点之间建立的连接在中断后会自动恢复,并且可以按任意顺序自由启动或停止两端。

由于 ZeroMQ 是面向消息的,因此订阅者可以一次性接收交易和区块,而无需实现任何类型的缓冲或重新组装。

前提条件

Bitcoin Core 中的 ZeroMQ 功能需要 ZeroMQ API >= 4.0.0 libzmq。 有关版本信息,请参见 dependencies.md。 通常,它由发行版打包为 libzmq3-dev 之类的东西。 不需要 ZeroMQ 的 C++ 封装器。

为了运行 contrib/zmq/ 目录中的示例 Python 客户端脚本,还必须安装 PyZMQ (通常使用 pip install pyzmq),但这对于守护进程操作不是必需的。

启用

默认情况下,ZeroMQ 功能不会自动编译。 要启用,请在配置构建系统时使用 -DWITH_ZMQ=ON

$ cmake -B build -DWITH_ZMQ=ON

要实际启用操作,必须在命令行或配置文件中设置适当的选项。

用法

目前,支持以下通知:

-zmqpubhashtx=地址
-zmqpubhashblock=地址
-zmqpubrawblock=地址
-zmqpubrawtx=地址
-zmqpubsequence=地址

套接字类型为 PUB,并且地址必须是有效的 ZeroMQ 套接字地址。 同一个地址可以在多个通知中使用。 可以多次指定相同的通知。

可以为每个通知单独设置用于设置 PUB 套接字的 outbound message high water mark (SNDHWM) 的选项:

-zmqpubhashtxhwm=n
-zmqpubhashblockhwm=n
-zmqpubrawblockhwm=n
-zmqpubrawtxhwm=n
-zmqpubsequencehwm=n

high water mark 的值必须是大于或等于 0 的整数。

例如:

$ bitcoind -zmqpubhashtx=tcp://127.0.0.1:28332 \
           -zmqpubhashtx=tcp://192.168.1.2:28332 \
           -zmqpubhashblock="tcp://[::1]:28333" \
           -zmqpubrawtx=ipc:///tmp/bitcoind.tx.raw \
           -zmqpubhashtxhwm=10000

bitcoin nodebitcoin gui 也可以代替 bitcoind

通知类型对应于消息主题(详细信息在下一节中)。 例如, 对于通知 -zmqpubhashtx,主题是 hashtx。 这些选项也可以在 bitcoin.conf 中提供。

消息格式

所有 ZMQ 消息都共享相同的结构,包含三个部分:主题字符串、 消息正文消息序列号

| topic     | body                                                 | message sequence number  |
|-----------+------------------------------------------------------+--------------------------|
| rawtx     | <serialized transaction>                             | <4-byte LE uint>         |
| hashtx    | <reversed 32-byte transaction hash>                  | <4-byte LE uint>         |
| rawblock  | <serialized block>                                   | <4-byte LE uint>         |
| hashblock | <reversed 32-byte block hash>                        | <4-byte LE uint>         |
| sequence  | <reversed 32-byte block hash>C                       | <4-byte LE uint>         |
| sequence  | <reversed 32-byte block hash>D                       | <4-byte LE uint>         |
| sequence  | <reversed 32-byte transaction hash>R<8-byte LE uint> | <4-byte LE uint>         |
| sequence  | <reversed 32-byte transaction hash>A<8-byte LE uint> | <4-byte LE uint>         |

其中:

  • 消息序列号表示消息计数,用于检测丢失的消息,每个主题都有不同的消息计数
  • 所有交易和区块哈希都以反转字节顺序排列(即,使用哈希函数生成的字节反转),与 RPC 接口和区块 浏览器用于显示交易和区块哈希的格式相同
rawtx

通知所有交易,无论是在添加到 mempool 时还是在新的区块到达时。 这意味着一个交易可能会多次发布:首先是在进入 mempool 时,然后在包含它的每个区块中再次发布。 消息的正文部分是序列化的交易。

hashtx

通知所有交易,无论是在添加到 mempool 时还是在新的区块到达时。 这意味着一个交易可能会多次发布:首先是在进入 mempool 时,然后在包含它的每个区块中再次发布。 消息的正文部分是反转字节顺序的 32 字节交易哈希。

rawblock

在链的顶端更新时通知。 当使用 assumeutxo 时,此通知 不会针对连接到后台验证链状态的历史区块发出。 消息的正文部分是序列化的区块。

hashblock

在链的顶端更新时通知。 当使用 assumeutxo 时,此通知 不会针对连接到后台验证链状态的历史区块发出。 消息的正文部分是反转字节顺序的 32 字节区块哈希。

sequence

8 字节的 LE uint 对应于 mempool 序列号,正文的类型为:

  • C : 连接的具有此哈希的区块
  • D : 断开连接的具有此哈希的区块
  • R : 由于非区块包含原因从 mempool 中删除的具有此哈希的交易
  • A : 添加到 mempool 的具有此哈希的交易

实现 ZMQ 客户端

ZeroMQ API 中记录了用于 TCP(和其他)的 ZeroMQ 端点说明符。

然后,在客户端,ZeroMQ 订阅者套接字必须将 ZMQ_SUBSCRIBE 选项设置为这些前缀之一(例如,仅 hash); 如果不这样做,将不会收到任何消息。 请参阅 contrib/zmq/zmq_sub.py 以获取工作示例。

已启用 ZMQ_PUB 套接字的 ZMQ_TCP_KEEPALIVE 选项。 这意味着在使用 TCP 传输时,将启用底层的 SO_KEEPALIVE 选项。 有效的 TCP keepalive 值通过底层的 操作系统配置进行管理,并且必须在建立连接之前进行配置。

例如,在 GNU/Linux 上运行时,可以使用以下命令 将 keepalive 设置降低到 10 分钟:

sudo sysctl -w net.ipv4.tcp_keepalive_time=600

为你的操作环境适当地设置 keepalive 值可能会 改善在长时间连接被网络中间盒静默丢弃的情况下的连接性。

此外,还启用了套接字的 ZMQ_IPV6 选项以接受来自 IPv6 主机的连接。 如果需要,此选项也必须在客户端设置。

备注

从 bitcoind 的角度来看,ZeroMQ 套接字是只写的; PUB 套接字甚至没有读取函数。 因此,没有状态直接引入到 bitcoind 中。 此外,不会广播任何未从公共 P2P 网络接收到的信息。

不会对连接的客户端进行身份验证或授权; 假定 ZeroMQ 端口仅暴露给受信任的实体, 使用防火墙等其他方式。

请注意,对于 *block 主题,当区块链顶端更改时, 可能会发生重组,并且只会通知顶端。 由订阅者负责从最后一个已知区块到新顶端检索链。 还要注意,如果顶端在活动链中,则不会发生通知,就像在调用 invalidateblock RPC 之后一样。 相反,sequence 主题会发布所有区块连接和 断开连接。

在传输过程中,ZMQ 通知可能会丢失,具体取决于你使用的通信类型。 Bitcoind 将一个递增的序列号附加到每个 通知,这允许侦听器检测丢失的通知。

sequence 主题专门指 mempool 序列 号,该序列号也与所有 mempool 事件一起发布。 这是一个与 ZMQ 本身不同的序列值,目的是允许构造 mempool 事件的总排序。

  • 原文链接: github.com/bitcoin/bitco...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
bitcoin
bitcoin
江湖只有他的大名,没有他的介绍。