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 插件直接在全节点进程内部运行,其计算开销已由全节点的分摊预算覆盖。但 MongoDB 数据库服务建议部署在独立的服务器上运行,防止高频的数据写入与索引计算和全节点的共识进程发生 CPU/内存/磁盘 I/O 上的抢占。

资源项推荐硬件规格
CPU / 内存16 核 / 32 GB 以上
SSD 磁盘2.5 TB 以上
运行环境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-1.0.0.zip

2. 部署 MongoDB 数据库

📘

版本说明

以下步骤以 MongoDB 7.0 LTS 版本为例(8.0 也已正式发布)。不要使用陈旧文档中已经停止维护、处于生命周期终点(EOL)的 4.0.4 版本。可以从 MongoDB 社区下载中心下载对应平台的稳定归档包。

# 下载并解压归档包 — 以 7.0.16 稳定版为例
MONGODB_VERSION=7.0.16
cd /home/java-tron
curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-${MONGODB_VERSION}.tgz
tar zxvf mongodb-linux-x86_64-${MONGODB_VERSION}.tgz
mv mongodb-linux-x86_64-${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

dbpath=/home/java-tron/mongodb/data
logpath=/home/java-tron/mongodb/log/mongodb.log
port=27017
logappend=true
fork=true
bind_ip=0.0.0.0
auth=true
wiredTigerCacheSizeGB=2
📘

核心参数说明

  • 如果全节点与 MongoDB 分别部署在不同服务器上,需要将配置设为 bind_ip=0.0.0.0。若二者部署在同一台服务器上,使用本地环回地址 127.0.0.1 安全性更高。
  • 请务必根据物理内存显式指定 wiredTigerCacheSizeGB 限制,否则 MongoDB 的缓存机制(WiredTiger Cache)默认会无限申请,极易导致主机物理内存耗尽,触发系统 OOM。

启动 MongoDB 并创建鉴权账户:

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

# 进入控制台
mongo
# 进入 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 = {
  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-1.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 = [ "" ]     // 事件哈希过滤;保留为空时匹配所有合约事件
  }
}

各配置项具体说明:

配置项名称核心含义
version事件中继框架版本。1 代表 V2.0(支持历史回填);0 代表 V1.0。详情请阅读事件服务框架介绍
startSyncBlockNum仅在 V2.0 框架下生效。设为 0 或负值时禁用历史回填;设为正数时,启动后会从该指定的区块高度重播事件。
native.useNativeQueue必须配置为 false 以便通过插件进行投递。(若设为 true,全节点将直接走内置的 ZeroMQ 通道。)
path指向本地插件包 plugin-mongodb-1.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 服务已经正常在后台运行,然后使用 --es 参数启动全节点:

java -jar FullNode.jar -c config.conf --es

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

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

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

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

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

mongo <mongo-host>: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,供前端或下游业务调用。

⚠️

运行环境限制:该服务必须运行在 Oracle JDK 8 环境下(该网关不支持基于 OpenJDK 8 启动)。

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

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

# 安装并配置好 Maven 3.9+ 环境
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

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

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 实时解码。


相关资源