MongoDB 事件插件

通过 MongoDB 中继插件订阅 TRON 链上事件——自带索引与条件查询能力的数据库归档。可选配合 TRON Event Query 搭建 HTTP 事件查询网关。

📘

前置阅读

MongoDB 事件插件负责将 TRON 链上产生的事件写入 MongoDB 数据库。相比于Kafka 插件,MongoDB 方案的优势在于可以直接基于数据库索引做临时条件查询(Ad-hoc Queries)。例如,可以检索“过去一小时内智能合约 A 触发的所有事件”或“地址 B 在指定区块范围内的全部交易流水”,无需额外搭建复杂的数据湖分析引擎。

如果业务需要归档链上事件,并提供条件检索与数据搜索能力,MongoDB 是更合适的选择。

一个完整的 MongoDB 事件订阅架构包含以下三个组件:

┌──────────────┐   事件投递    ┌────────────┐    数据写入    ┌──────────┐    HTTP 查询   ┌──────────┐
│ TRON 全节点  │ ──────────▶ │  事件插件  │ ──────────▶ │ MongoDB  │ ◀───────── │ 查询服务 │
│ (java-tron)  │  (进程内)   │  (.jar 包) │             │  数据库  │   数据查询  │ (选配项) │
└──────────────┘             └────────────┘             └──────────┘            └────┬─────┘
                                                                                     │ HTTP 响应
                                                                                     ▼
                                                                              ┌──────────────┐
                                                                              │  业务系统    │
                                                                              └──────────────┘

其中,全节点、插件包及 MongoDB 数据库是整套架构的必要组件。查询服务(TRON Event Query)是可选组件:如果业务系统可以直接使用 MongoDB 驱动查询数据库,可以跳过该服务的部署。

推荐硬件(全节点与插件主机)

MongoDB 插件直接在全节点进程内部运行,其 CPU 和内存开销属于全节点总工作负载的一部分。MongoDB 数据库服务建议部署在独立的服务器上运行,防止高频的数据写入与索引计算和全节点的共识进程发生 CPU/内存/磁盘 I/O 上的抢占。

资源项推荐硬件规格
CPU / 内存16 核 / 32 GB 以上
SSD 磁盘全节点数据至少 3 TB;MongoDB 容量按事件量和保留时间另行规划
运行环境Linux / macOS

1. 编译 MongoDB 事件插件

从 GitHub 克隆事件插件代码,并使用 Gradle 编译打包出 MongoDB 版本:

git clone https://github.com/tronprotocol/event-plugin.git
cd event-plugin
./gradlew build

编译成功后,当前版本生成的插件包位于:event-plugin/build/plugins/plugin-mongodb-3.0.0.zip。插件版本升级后文件名可能变化,请以 build/plugins 目录中的实际文件名为准,并在后续配置中使用同一文件名。

2. 部署 MongoDB 数据库

📘

版本说明

以下步骤以 Ubuntu 22.04 x86_64 上的 MongoDB 7.0.24 为例。ARM64 或其他操作系统应从 MongoDB 社区下载中心选择与系统和处理器架构匹配、仍在支持周期内的版本。

MongoDB 7.0 的服务端归档包不包含 MongoDB Shell,请另行按照 mongosh 安装指南安装 mongosh

# 安装 MongoDB 二进制归档包所需的系统依赖
sudo apt-get update
sudo apt-get install -y curl libcurl4 libgssapi-krb5-2 libldap-2.5-0 libwrap0 \
  libsasl2-2 libsasl2-modules libsasl2-modules-gssapi-mit openssl liblzma5

# 下载并校验归档包 — 以 Ubuntu 22.04 x86_64 上的 7.0.24 为例
MONGODB_VERSION=7.0.24
MONGODB_PLATFORM=ubuntu2204
MONGODB_ARCHIVE=mongodb-linux-x86_64-${MONGODB_PLATFORM}-${MONGODB_VERSION}.tgz
cd /home/java-tron
curl -O "https://fastdl.mongodb.org/linux/${MONGODB_ARCHIVE}"
curl -O "https://fastdl.mongodb.org/linux/${MONGODB_ARCHIVE}.sha256"
sha256sum -c "${MONGODB_ARCHIVE}.sha256"
tar zxvf "${MONGODB_ARCHIVE}"
mv "mongodb-linux-x86_64-${MONGODB_PLATFORM}-${MONGODB_VERSION}" mongodb

# 将二进制路径配置到环境变量中
export MONGOPATH=/home/java-tron/mongodb/
export PATH=$PATH:$MONGOPATH/bin

# 准备数据目录及日志文件存放路径
mkdir -p /home/java-tron/mongodb/{log,data}
touch /home/java-tron/mongodb/log/mongodb.log

在本地创建配置文件 mgdb.conf

storage:
  dbPath: /home/java-tron/mongodb/data
  wiredTiger:
    engineConfig:
      cacheSizeGB: 2
systemLog:
  destination: file
  path: /home/java-tron/mongodb/log/mongodb.log
  logAppend: true
net:
  port: 27017
  bindIp: 127.0.0.1
processManagement:
  fork: true
security:
  authorization: enabled
📘

核心参数说明

  • 如果全节点与 MongoDB 部署在同一台服务器上,保持 net.bindIp: 127.0.0.1。跨主机部署时,应将 net.bindIp 设为 127.0.0.1,<MongoDB-private-IP>,同时监听环回地址和 MongoDB 主机的明确私网 IP,并将后文的 event.subscribe.server 设为“该私网 IP + :27017”。通过防火墙或安全组仅允许全节点服务器访问,不要将 MongoDB 的 27017 端口开放给公网。
  • 解压前必须确认 sha256sum -c 返回 OK。更强的来源认证可按 MongoDB 官方指南使用发布签名验证。
  • MongoDB 会根据可用内存自动设置 WiredTiger 缓存大小。示例中的 storage.wiredTiger.engineConfig.cacheSizeGB: 2 适用于 MongoDB 与全节点共享主机时为全节点预留内存,不是通用推荐值。请按主机可用内存调整;在容器中运行或与其他内存密集型进程共用主机时,建议显式限制缓存。

启动 MongoDB 并创建鉴权账户:

# 启动 MongoDB 服务
mongod --config ./mgdb.conf

# 进入控制台
mongosh
# 进入 admin 库创建超级管理员账户
> use admin
> db.createUser({user:"root", pwd:"<Your-Password1>", roles:[{role:"root", db:"admin"}]})

# 认证超级管理员登录,并创建 eventlog 数据库及其专属的 Owner 账户
> db.auth("root", "<Your-Password1>")
> use eventlog
> db.createUser({user:"tron", pwd:"<Your-Password2>", roles:[{role:"dbOwner", db:"eventlog"}]})

请在实际部署中将 <Your-Password1><Your-Password2> 替换为强密码;后续 dbconfigdb.authmongo.password 中的 eventlog 用户密码必须与 <Your-Password2> 保持一致。

3. 配置全节点

在全节点的 config.conf 中追加 event.subscribe 配置块:

event.subscribe = {
  enable = true         // 启用事件订阅
  version = 1            // 1 表示启用 V2.0 事件框架(支持历史回填);0 表示启用 V1.0 框架(默认值)
  startSyncBlockNum = 0  // 仅在 V2.0 框架下有效——具体配置参见下方说明

  native = {
    useNativeQueue = false   // 必须配置为 false,否则事件将走 ZeroMQ 而非外部插件
    bindport = 5555
    sendqueuelength = 1000
  }

  path = "/deploy/fullnode/event-plugin/build/plugins/plugin-mongodb-3.0.0.zip" // 插件包的绝对路径
  server = "127.0.0.1:27017" // MongoDB 服务连接地址
  dbconfig = "eventlog|tron|<Your-Password2>"   // 格式为:数据库名|鉴权用户名|鉴权密码
  contractParse = true

  topics = [
    { triggerName = "block",         enable = true, topic = "block" },
    { triggerName = "transaction",   enable = true, topic = "transaction" },
    { triggerName = "contractevent", enable = true, topic = "contractevent" },
    { triggerName = "contractlog",   enable = true, topic = "contractlog" }
  ]

  filter = {
    fromblock = ""             // "", "earliest", 或特定的区块高度
    toblock = ""               // "", "latest", 或特定的区块高度
    contractAddress = [ "" ]   // 合约地址过滤;保留为空时匹配所有合约
    contractTopic = [ "" ]     // 事件哈希过滤;保留为空时匹配所有合约事件
  }
}

各配置项具体说明:

配置项名称核心含义
enable设为 true 以启用事件订阅。
version事件中继框架版本。1 代表 V2.0(支持历史回填);0 代表 V1.0。详情请阅读事件服务框架介绍
startSyncBlockNum仅在 V2.0 框架下生效。设为 0 或负值时禁用历史回填;设为正数时,启动后会从该指定的区块高度重播事件。
native.useNativeQueue必须配置为 false 以便通过插件进行投递。(若设为 true,全节点将直接走内置的 ZeroMQ 通道。)
path指向本地插件包 plugin-mongodb-3.0.0.zip 的绝对路径。
serverMongoDB 的服务连接地址,格式为 IP:Port。默认端口为 27017
dbconfig写入 MongoDB 时的认证配置,格式为 数据库名|账户名|密码
contractParse设为 true 时,智能合约事件会由全节点先根据合约 ABI 自动解析完成,然后再存入 MongoDB 中。
topics[].triggerName触发器标识符。支持的七个选项已在事件类型中说明,不可修改。
topics[].enable设为 false 可暂时停用该类型的触发投递,而无需将其从配置中删除。
topics[].topic指定存储该类型事件的 MongoDB 集合(Collection)名称。
filter可选过滤器。用于按高度区间、特定合约或事件 Topic 哈希来过滤合约事件/日志的投递范围。

4. 启动全节点与连通性验证

确保 MongoDB 服务已经正常在后台运行,并在 config.conf 中设置 event.subscribe.enable = true,然后启动全节点:

java -jar FullNode.jar -c config.conf

观察日志,验证 MongoDB 插件是否已成功加载:

tail -f logs/tron.log | grep -i eventplugin

如果加载正常,控制台会出现类似以下日志输出:

[o.t.c.l.EventPluginLoader] '/path/to/plugin-mongodb-3.0.0.zip' loaded

接着,进入 MongoDB 控制台,验证事件数据是否正在写入各数据集合中:

mongosh --host 127.0.0.1 --port 27017
> use eventlog
> db.auth("tron", "<Your-Password2>")
> show collections          # 应该包含:block, transaction, contractevent, contractlog 等集合
> db.block.find().limit(1)  # 查询最新写入的一条区块事件记录

如果 find() 正常返回了 JSON 文档,说明整套事件订阅的中继链路已正常走通。如果未生成集合,请检查全节点日志中插件中继的报错信息,并核实 MongoDB 连接鉴权及网络可达性。


5. (可选)部署 TRON Event Query 服务

TRON Event Query 服务是一个基于 Spring Boot 编写的轻量级 HTTP 接口网关。它能将底层的 MongoDB 聚合查询封装为语义更明确的 RESTful API,供前端或下游业务调用。

📘

运行环境

TRON Event Query 的构建目标为 Java 8,请使用 JDK 8 进行构建和运行。其 deploy.sh 使用 bc 计算 JVM 堆内存,运行该脚本前需安装 bc

从源码克隆并使用 Maven 进行打包编译:

git clone https://github.com/tronprotocol/tron-eventquery.git
cd tron-eventquery

# 安装并配置好 Maven 3.9+ 环境,并安装 deploy.sh 所需的 bc
sudo apt-get update
sudo apt-get install -y bc
mvn --version
mvn package

编辑 tron-eventquery/config.conf 连接配置文件:

mongo.host=<mongo-ip>
mongo.port=27017
mongo.dbname=eventlog
mongo.username=tron
mongo.password=<Your-Password2>
mongo.connectionsPerHost=8
mongo.threadsAllowedToBlockForConnectionMultiplier=4

在 MongoDB 7.0 环境中运行 insertIndex.sh 前,将脚本中的以下代码:

mongodb='mongo '$mongoIp':'$mongoPort

替换为:

mongodb="mongosh --host ${mongoIp} --port ${mongoPort}"

然后启动服务并构建必要的数据库查询索引:

sh deploy.sh
sh insertIndex.sh

该服务默认监听 8080 端口。如需自定义运行端口,可以编辑 deploy.sh 脚本:

nohup java -jar -Dserver.port=8081 target/troneventquery-1.0.0-SNAPSHOT.jar 2>&1 &

HTTP API 接口参考

该服务提供跨交易、转账、区块、日志等维度的 HTTP 查询接口。所有 API 默认返回 JSON 格式数据。接口的分页功能可通过参数 limit(默认 25 条)与 start(默认从 1 开始的索引)控制,排序可通过参数 sort 调节(前缀带 - 代表降序)。以下 base URL 为 http://<host>:<port>

交易接口

接口 Endpoint具体用途
GET /transactions分页列出所有交易;支持参数:limitsortstartblock
GET /transactions/{hash}精确获取单笔交易的详情

示例请求:GET /transactions?limit=1&sort=-timeStamp&start=2&block=0

转账接口

接口 Endpoint具体用途
GET /transfers分页获取转账历史;支持参数:limitsortstartfromtotoken
GET /transfers/{hash}获取特定交易哈希中发生的转账记录

示例请求:GET /transfers?token=trx&limit=1&from=TJ7yJNWS8RmvpXcAyXBhvFDfGpV9ZYc3vt&to=TAEcoD8J7P5QjWT32r31gat8L7Sga2qUy8

事件接口

接口 Endpoint具体用途
GET /events分页列出事件;支持参数:limitsortstartsinceblock
GET /events/transaction/{transactionId}获取特定交易产生的事件
GET /events/{contractAddress}获取指定智能合约产生的所有事件
GET /events/contract/{contractAddress}/{eventName}按合约地址 + 事件名称进行检索
GET /events/contract/{contractAddress}/{eventName}/{blockNumber}过滤查询区块高度大于等于 blockNumber 的合约事件
GET /events/timestamp查询在指定时间戳之后的事件;支持参数:sincecontractlimitsort
GET /events/confirmed仅检索已被网络固化的区块中触发的事件;支持参数同上

示例请求:GET /events/TMYcx6eoRXnePKT1jVn25ZNeMNJ6828HWk?limit=1&sort=-timeStamp&block=0

区块接口

接口 Endpoint具体用途
GET /blocks分页查询区块元数据;支持参数:limitsortstartblock
GET /blocks/{hash}按区块哈希获取单区块信息
GET /blocks/latestSolidifiedBlockNumber获取当前网络最新的固化区块高度

合约原始日志接口

接口 Endpoint具体用途
GET /contractlogs分页查询原始日志;支持参数:limitsortstartblock
GET /contractlogs/transaction/{transactionId}获取特定交易中的所有原始日志
GET /contractlogs/contract/{contractAddress}获取特定合约产生的所有原始日志
GET /contractlogs/uniqueId/{uniqueId}根据唯一日志 ID 精确获取单条日志

基于请求体提供 ABI 的实时解码接口 (3.6+)

如果所查询的合约未注册,导致日志没有被自动解码,可以直接在 HTTP 请求体(POST)中附带合约 ABI,网关会执行即时反序列化解码:

接口 Endpoint传输请求体格式
POST /contract/transaction/{transactionId}abi=<ABI 格式的 JSON 字符串>
POST /contract/contractAddress/{contractAddress}abi=<ABI 格式的 JSON 字符串>
POST /contract/uniqueId/{uniqueId}abi=<ABI 格式的 JSON 字符串>

返回的 JSON 结构与 GET /contractlogs/... 类似,但其中的 data 字段已根据 POST 请求体中的 ABI 实时解码。


相关资源