hiero-hackers/hiero-streams-rs
GitHub: hiero-hackers/hiero-streams-rs
解析并加密验证 Hedera 主网节点的记录流文件和区块流,为审计、索引和数据对账提供可独立验证的基准事实。
Stars: 2 | Forks: 1
# hiero-streams (Rust)
解析并加密验证 Hedera 的 **记录流文件** —— 每个主网节点发布的
已签名共识输出 —— **跨越两个时代**:
v6 记录文件(2022 年中至今)和 HIP-1056 区块流。一个
轻依赖、无 GC 的 Rust crate 和一个零运行时的 CLI。
**为什么要信任另一个解析器?网络即是参照基准。** 这里的正确性
不是“我们的测试通过了”——每一个断言都锚定在网络本身
签名的数据或某个独立实现计算出的结果上:
- **网络证明了解析过程。** 对于 v6,共识节点的
签名元数据哈希可以根据该解析器*自身提取的
字段*复现——如果解析错误,RSA 签名将无法
验证。(`verify`、`attest` 和离线测试均运行此过程。)
- **窗口穷举的镜像节点差异化测试。** 每个已提交主网固定窗口中的每一笔交易,都会与镜像节点对同一文件的
独立解码进行逐字段比对——这
捕获了一个内嵌 protos 尚未知晓的、真实的发布后响应码(527)。
- **逐项检查的证明路径一致性——跨越独立的加密技术栈。** 区块时代的证明验证(hinTS BLS 阈值、
聚合 Schnorr、WRAPS Groth16+KZG)与
[`hiero-block-verifier-js`](https://github.com/hiero-hackers/hiero-block-verifier-js) 进行了差异化测试,
基于 `hiero-block-node` 固定测试集——不仅限于最终判定,每一次单独的检查都必须一致(`tests/block_proof_differential.rs`)。这种
差异是有意为之的:JS 验证器构建于纯 JS 的
`@noble/curves` 之上,而本 crate 基于 arkworks——两种不同语言中毫不相干的曲线
实现,在相同的字节上推导出完全相同的配对、
转录和判定。共享依赖的
实现之间的一致性能证明的东西要少得多。
- **连续性是经过证明的,而非假设的。** v6 的 running-hash 链和
区块时代的 root 链(重新计算的 merkle root == 下一个 footer 的声明)在
每一对连续的固定测试数据以及每次
`etl --verify-chain` 运行期间都会进行断言。
- **已提交的快照锁定了输出契约**,因此规范的 JSON
结构不会发生静默偏移。
CLI:
```
hiero-streams etl --dir downloaded/ --out data --transfers --verify-chain
# threaded backfill: record files → day-partitioned Parquet with a
# stable, contract-tested schema.
# --verify-chain asserts the running-hash chain within and across
# day boundaries as it transforms — the backfill is provably
# gapless and un-reordered by construction, or it exits non-zero
# naming the exact file where the chain breaks
hiero-streams parse file.rcd.gz # or file.blk.gz — format auto-detected
hiero-streams verify file.rcd.gz file.rcd_sig \
--address-book book.bin --node 0.0.3 # exit 0 only when valid
hiero-streams verify file.blk.gz --bootstrap genesis.blk.gz
# block era (build with --features block-proofs): verifies the
# in-band proof — recomputed merkle root, hinTS threshold
# signature, Schnorr/WRAPS suffix — no signature file to fetch.
# --bootstrap is the genesis block carrying the ledger-ID
# publication; genesis verifies with no flag
hiero-streams block-activity file.blk.gz
# per-block node liveness: which consensus nodes authored gossip
# events in the block — a signal the record era never exposed
hiero-streams attest file.rcd.gz --project
# fetches every node's signature + the live address book;
# exit 0 only when >= 1/3 of the network signed these bytes
```
```
use hiero_streams::{parse_record_file, verify_record_file, parse_address_book};
let file = parse_record_file(&bytes)?; // .rcd.gz or .rcd, as-is
for tx in &file.transactions {
// consensus_timestamp, payer, tx_type, result, charged_fee_tinybar,
// transfers (every HBAR leg), token_transfers
}
let book = parse_address_book(&address_book_bytes)?;
let result = verify_record_file(&bytes, &signatures, &book)?;
result.attested; // >= 1/3 of the address book signed this exact file
```
## 适用人群
记录流是网络的**原始、已签名输出**——镜像
节点、浏览器和仪表盘都是*衍生*自它们。当需要
直接获取该基准事实时,请使用本 crate:
- **大规模历史数据的索引器与分析。** 公共镜像
REST API 在速率限制下每页仅提供约 100 行;而流是
数据消防水管。在不到一秒的时间内解析完整的
主网数据(约 43k 个文件,约 30 万笔
交易),并输入到你自己的存储中——无需 API
密钥,无速率限制,无中间人。
- **审计员、交易所、托管机构。** “证明此交易
发生过”不应意味着“API 是这么说的”。`verify_record_file`
将记录文件 + 签名文件 + 地址簿转化为
密码学证明,证明 ≥ ⅓ 的网络对这些
精确字节进行了签名。CLI 将其打造成一个单一的静态二进制文件,审计员
可以在零运行时环境的情况下运行它——跨越两个时代:`verify` 检查
区块流的带内证明,与检查记录
文件的节点签名的方式相同。
- **根据基准事实检查衍生数据。** 镜像节点可能
出错(我们发现了真实的差异)。当余额、手续费总额
或供应量数据看起来不对时,流就是你进行对账的
基准。
- **区块流的未来,已来。** Hedera 正在
从记录文件切换到区块流 (HIP-1056);在网络的
10k-TPS 设计目标下,无 GC 的解析器不再是可有可无的奢侈品。本
crate 已经在相同的纪元检测 API 下解析并验证了新格式的证明,并已通过主网预览版验证。
- **对区块节点时代本身的检验。** HIP-1081 引入了
一类新的中介者——独立的(包括商业的)
区块节点运营者——其信任模型要求消费者应
信任*证明*,而非节点声誉。这句话只有在
存在独立的证明验证器时才有意义:目前
恰好有两个,`hiero-block-verifier-js` 和本 crate,并且它们之间进行了差异化测试。网络与你之间有更多人参与,增强了验证的必要性,而不是削弱了它。
并且 v6 时代永远不会迁移:四年的历史仅以
记录文件的形式存在(即使作为 HIP-1193 包装区块提供,其负载仍是
v6 字节)——对其进行审计需要永久维护一个 v6 验证器。
## 为什么选择 Rust?
1. **关键场景下的高吞吐量——实测且真实。** 完整真实
主网数据(2026-07-10,节点 0.0.3:43,140 个记录文件,307,991
笔交易;文件已预加载,因此这是解析时间而非磁盘读取时间;
8 核机器,5 次运行中的最佳结果):
| 配置 | 一整天 | 吞吐量 |
| --- | --- | --- |
| Rust,单线程 | 2.61 s | 118k tx/s |
| **Rust,8 线程** | **0.37 s** | **834k tx/s** |
| Rust 通过 Node 绑定 (JSON 往返) | 6.31 s | 49k tx/s |
整整一天的共识输出——花了 24 小时
生成的数据——只需大约**三分之一秒**即可解析完。其结构性
优势在于**并行处理**(这里是 7 倍提升,在 8 核上接近线性扩展——这对于
多年数据的回填至关重要),长时间运行的任务无 GC 停顿,并且
为每个包含多出几个数量级交易的区块流时代
文件留有余地。Node 绑定的存在是为了
**输出一致的跨平台移植性**,而不是为了速度——其 JSON 交互
成本比解析本身还要高(可通过 `cargo run
--release --example parse_dir -- ` 复现)。
2. **零运行时的可分发程序。** `hiero-streams verify` 是
一个单独的静态二进制文件。
3. **一套实现,多种语言。** Rust 暴露了 C FFI,因此
Python/Go/JVM 绑定可以包装这一个经过审计的核心。
4. **对不可信输入可证明的内存安全。** 该库是
`#![forbid(unsafe_code)]`——在 crate 中的任何地方,
包括生成的 protobuf 代码在内,出现任何 `unsafe` 都会导致
编译错误。对于一个
完全工作就是解码攻击者控制的字节的工具来说,“解析/验证核心不包含内存不安全性”是编译器强制执行的保证,而不是 README 中的一纸空谈。
## 集成到你的项目中
**从 Rust 中**——直接使用该 crate(在
crates.io 发布之前使用 git 依赖):
```
[dependencies]
hiero-streams = { git = "https://github.com/hiero-hackers/hiero-streams-rs" }
```
**从任何其他语言中**——通过 shell 调用 CLI;其契约就是
标准输出上的 JSON 和退出码。不需要链接任何库:
```
// Node.js
import { execFileSync } from "node:child_process";
const parsed = JSON.parse(
execFileSync("hiero-streams", ["parse", "file.rcd.gz"]),
);
```
```
# Python
import json, subprocess
r = subprocess.run(["hiero-streams", "verify", rcd, sig,
"--address-book", book, "--node", "0.0.3"],
capture_output=True, text=True)
attested_by_node = r.returncode == 0
verdict = json.loads(r.stdout)
```
这些 JSON 结构是稳定的——由已提交的快照测试锁定——因此
使用者可以基于它们进行构建,而无需追踪本 crate 的
内部实现。
**原生 Node 绑定**——`bindings/node` (napi-rs) 暴露了
`parseRecordFileJson`、`parseBlockJson`、`verifyBlockProofJson`、
`recordFileHashHex` 和 `verifyNodeSignature`,返回与
所有其他接口完全相同的黄金标准 JSON 结构——该绑定的测试
断言其区块证明输出与 CLI 的输出完全相同,二者都是
由同一个库序列化器构建的。将其用于单审计核心的跨平台移植;
如果追求纯粹的速度,请原生使用该库(见
上表)。PyO3 和
WASM 仍在路线图上。
## 环境要求与 Google Cloud 设置
该库和离线验证只需要 **Rust 1.82+**(即
`Cargo.toml` 中的 `rust-version`,由 CI 强制执行)和 **protoc**
(`brew install protobuf`)。任何涉及公共
流存储桶的操作(`attest`,以及为 `etl` 下载的数据)还需要
一个 Google Cloud 项目,因为这些存储桶是** requester-pays(请求者付费)**的——
Google 会向*你的*项目收取读取费用;这就是原始数据在
没有 Hedera 资助无限流出费用的情况下保持
公开的方式。
一次性设置(约 10 分钟):
1. [console.cloud.google.com](https://console.cloud.google.com) → 登录 → **New project**(任意名称;记下*项目 ID*)。
2. **Billing** → 绑定一种支付方式。新账户可获得约 300 美元的免费
额度,这足以覆盖下文
成本表中的所有内容。
3. 安装并认证 CLI:
brew install --cask google-cloud-sdk
gcloud auth login
gcloud config set project YOUR_PROJECT_ID
就是这样——`attest` 会通过 shell 调用 `gcloud auth print-access-token`
(或者设置 `GCS_OAUTH_TOKEN`),下载操作使用
`gcloud storage cp --billing-project=YOUR_PROJECT_ID`。
## 成本与时间模型——经过测量,并带有真实的时代说明
两个驱动因素以不同的方式扩展,将它们混为一谈是导致估计
出错的原因(包括我们自己,已经出错两次了):
- **文件数量是恒定的**:大约每 2 秒 1 个文件,每天 43,200 个,v6 时代总计约 6400 万个文件——*与流量无关*。这决定了 GET 操作的成本(约 $0.0004/1,000 → **整个 v6 时代约 $26**)以及下载时间的
延迟下限。
- **文件大小随交易量扩展**:实测压缩后每笔交易约 600 字节。这决定了流出费用(约 $0.12/GB → **每百万笔交易约 $0.07**)和
下载时间中受带宽限制的部分。
我们测得的基准(主网 2026-07-04T00 这一个小时:1,800 个文件,8 MB,
3.8 tx/s)是一个**平静期的下限**。v6 时代包括
2022–2024 年的高 TPS 时期(atma.io 和其他重 HCS 的应用
推动了持续数百到数千的 tx/s),这些日子的数据量是今天的
10-100 倍。因此,成本取决于*总交易量*,而不是天数:在 v6 时代有数百亿笔交易的情况下,
预计整个时代需要**大约 10–30 TB 的带宽和 $1,200–3,600 的流出费用**——加上固定的约 $26 的操作费。限定时间窗口的成本很低:现代的一天约 $0.04,一个月约 $1;
2023 年的某一天峰值可能达到几美元。
**时间估计**(在本机上测量,单进程;平静期的数字来自一次真实的连续 7 天运行,2026-07-05 →
07-11,共 302,211 个文件):
| 步骤 | 实测耗时 | 推算 |
| --- | --- | --- |
| 下载,平静的一天 (43,200 个文件, ~0.2 GB) | 持续约 220 个文件/秒 (受限于延迟;连续 7 天每天耗时 3-3.5 分钟) | ~3.5 分钟 |
| 下载,繁重的 2023 年某天 (43,200 个文件, 数十 GB) | 受限于带宽 | ~30-60 分钟 (以 30 MB/s 计算) |
| 下载,完整的 v6 时代 | 两种模式均有 | **单台机器约 4 天-2 周** (在 220 个文件/秒下延迟下限约为 3.5 天 + 带宽受限的繁重时代);通过日期范围并行处理可线性减少耗时 |
| 解析/转换 (`etl`),每天 | 完整一周耗时 32.6 秒 → 4.7 秒/天,包含磁盘读取 + Parquet 写入 | **时代 6400 万个文件的开销约为 2 小时**,加上繁重日子的解析时间 (解析核心可维持 834k tx/s) |
解析永远不会成为瓶颈;完整回填的实际耗时在于
下载,而美元成本在于繁重时代的流出费用。
GET 操作和平静期的流出费用可以忽略不计。从所有约 29 个节点获取签名文件会使操作计数增加 29 倍——请
有选择地进行 attest,不要在回填期间对每个文件都执行 attest。
预计某些节点会在存储桶中缺失:attestation 仅需
地址簿的 ⅓,并且单个节点可能
在很长一段时间内停止运行,但仍被列在地址中(在主网上观察到:一个节点
沉默了数月,使得 28/29 成为了健康的基准)。网络每天
规范的活动记录是账户
0.0.802 的每日终 payouts——未出现在该转移列表中的节点在前一天是
非活跃的:
```
/api/v1/transactions?transactiontype=CRYPTOTRANSFER&result=success&type=debit&account.id=0.0.802
```
## 回填流水线
`hiero-streams etl` 是获取批量历史数据的快车道:下载记录
文件(`gcloud storage cp`,支持并行 + 可断点续传),然后运行
多线程流水线。在完整的主网**一周**(2026-07-05 → 07-11:
302,211 个文件,3,259,764 笔交易)上,它在同一台 8 核机器上仅需 **33 秒**即可完成转换——包含磁盘读取——并通过 `--verify-chain`
证明整个周的数据无断层且未被重新排序:running-hash
链在每一天内*以及在所有六个午夜边界点*均保持有效。
该数据集精确匹配:对所有 302k 个文件进行的独立重新解析,与 Parquet 数据集中每一天的行数以及精确到 tinybar 的 `sum(fee_tinybar)` 完全一致(一周总计 81,138.9769 ℏ)。在笔记本电脑上查询
结果:
```
SELECT day, type, sum(fee_tinybar) / 1e8 AS fees_hbar
FROM read_parquet('data/transactions/*/*.parquet', hive_partitioning=1)
GROUP BY ALL ORDER BY day, fees_hbar DESC;
```
## 为什么信任它:网络即是参照基准
正确性锚定在网络本身——它的签名和
它自己的独立解码器——而不是该 crate 自己证明自己:
- **共识节点对每个文件级字段的解析进行加密证明。** 每个 `.rcd_sig` 中的签名元数据哈希包含了版本、HAPI 版本、两个 running hashes 和区块号——所有这些都是该解析器提取的字段。测试套件从*解析出的*字段重新计算
该哈希,并在签名
节点的真实 RSA 密钥下进行验证:如果这些字段的解析是错误的,网络自己的
签名将会拒绝它。
- **镜像节点——网络团队自己的实现——逐字段完全一致。** `tests/record_mirror_differential.rs` 解析已提交的
主网记录文件,并断言交易集合的相等性,同时针对
为该共识窗口专门获取的镜像节点数据,在交易类型、支付者、结果、费用和完整的转移列表上达成
逐笔交易的一致(固定数据集已提交;测试
离线运行)。因为记录文件是网络的完整输出,这是一次
详尽的窗口比对,而不是抽查。
- **该链证明了大规模下的提取正确性**:1,800 个连续的主网
文件(13,587 笔交易)链验证零中断——每个
文件解析出的 running hashes 和区块号与相邻文件协调一致(解析耗时约 0.5 秒)。
- **签名验证使用了真实的已签名固定数据集进行测试**(来自
hiero-mirror-node 仓库)以及实际对其进行签名的地址簿:签名
节点的密钥验证通过,同级节点的密钥被拒绝,并且
哪怕翻转单个字节也会失败。
- 已提交的**输出快照**锁定了
已签名固定数据集的精确规范 JSON 结构(`tests/record_snapshot.rs`),因此重构不能
静默更改使用者接收到的内容。
经验证确定的格式事实被逐位保留:已签名哈希的域是**整个未压缩文件**(包含版本头部),并且 RSA-3072 签名 (SHA384withRSA) 是针对
48 字节的哈希本身进行的。
### v6 签名格式参考
记录在此处是因为它在其他任何地方都没有规范:HIP-435 定义了
`SignatureFile.metadata_signature`,但没有说明元数据哈希所覆盖的字节是什么——这种布局仅存在于
`SignatureWriterV6.writeSignatureFile` (hiero-consensus-node) 中。Preimage 是大端序拼接
```
int32(recordFileVersion = 6) | int32(hapi major) | int32(minor)
| int32(patch) | startObjectRunningHash.hash (48 raw bytes)
| endObjectRunningHash.hash (48 raw bytes) | int64(blockNumber)
```
使用 SHA-384 进行哈希,并像文件签名一样使用 SHA384withRSA 进行签名。
已针对真实的主网 `.rcd_sig` 文件进行了确认:重建的
摘要可通过签名节点的 RSA-3072 密钥进行验证(任何字段的
遗漏、重新排序或字节交换都会失败)。这对于低成本的
历史审计很重要:元数据签名让你能够从约 1 KB 的 sig 文件中验证链的连续性
(running hashes + 区块号),而无需
下载完整的记录文件——在 v6 时代,这大约能减少 300 倍的数据量。
## 文档
- [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — 本 crate 的工作原理:数据
流、模块图、每个依赖及其存在原因、信任模型,以及
哪些内容依赖于本仓库(已发布的 JSON 契约、Parquet 模式一致性)。
- [`docs/MIGRATION.md`](docs/MIGRATION.md) — HIP-1056 区块迁移:
发生了什么变化,哪些被证明没有变化,证明验证移植计划
(以 `hiero-block-verifier-js` 作为参考实现),需要注意的陷阱
,以及切换检查清单。
- [`docs/CODE-TOUR.md`](docs/CODE-TOUR.md) — 如何深入源码:
模块图、字节追踪路径、你原本可能会踩坑的
设计决策、哪个测试锁定了哪个契约,以及常见
修改的指南。
- [`ROADMAP.md`](ROADMAP.md) — 接下来要做什么,什么是刻意
推迟的,以及重大依赖决策背后的探索过程。
## 范围与路线图
- **v6 记录文件**(主网 2022 年中至今);早期的 v2/v5 格式
将被明确拒绝。
- **区块流 (HIP-1056)** —— 解析已发布,并已通过主网预览验证。**证明验证已发布**,位于
默认关闭的 `block-proofs` 特性之后:所有三条带内证明路径
(BabyJubjub 上的聚合 Schnorr,BLS12-381 上的 hinTS BLS 阈值,
BN254 上的 WRAPS Groth16+KZG)以及区块 merkle root 的重新计算,
均已对照
[`hiero-block-verifier-js`](https://github.com/hiero-hackers/hiero-block-verifier-js) 进行了逐项差异化测试,
基于来自 `hiero-block-node` 的测试集。**ETL 已发布**:`etl`
会进行时代检测,并从 `.blk.gz` 文件中写入相同的 Parquet 数据集契约
,同时 `--verify-chain` 断言区块号无断层且
root 链连续。GA 的标签需要等待
HIP-1193 切换的正式确定(包装的记录区块——在
HIP PR #1427 中提出——为这种过渡搭建了桥梁)。
- 完整的 v6 验证:文件 + 元数据签名,⅓ 地址簿的
证明(使用 `attest` 获取器),以及跨连续文件的 running-hash 链。
- 库中无 I/O 操作:调用者提供字节(存储桶客户端、文件),
由该 crate 进行解析和验证。高吞吐量的回填/ETL 二进制文件
是配套 crate 的候选对象。
## 示例
`examples/` 下的可运行示例(`cargo run --release
--example [-- args]`):
| 示例 | 展示内容 | 依赖项 |
| --- | --- | --- |
| `verify_offline` | 针对内置的真实签名固定测试集进行完整的 v6 验证(哈希、文件 + 元数据签名) | 无 |
| `verify_block` | 针对内置测试集进行区块时代的带内证明验证(merkle root、hinTS、Schnorr + WRAPS)——需要 `--features block-proofs` | 无 |
| `parse_one` | 一个文件 → 可读的交易记录行 | 无 (内置测试数据) |
| `chain_check -- ` | 目录上的 running-hash 链——证明序列无断层且未被重新排序 | 下载的文件 |
| `fee_report -- ` | 迷你分析:手续费最高支付者 + 按类型划分的手续费 | 下载的文件 |
| `parse_dir -- ` | 吞吐量基准测试,顺序与多线程对比 | 下载的文件 |
合理性基准:在批量语料库上,`chain_check` 验证了所有 1,800 个
文件链完整(区块 97200914..=97202713),并且 `fee_report` 的
总和与 Parquet 数据集的 `sum(fee_tinybar)` 完全一致。
## 目录结构
```
proto/, proto-hapi/ vendored protobuf definitions (record era / block era)
build.rs prost codegen (two compile units, one per proto tree)
src/record/ v6 record files: parsing + trust (signatures, chain, attestation)
src/block/ HIP-1056 block streams: parsing + in-band proof verification
src/transaction.rs the shared output vocabulary both eras produce
src/cli/ the CLI (bin-only): parse / verify / block-activity / attest / etl
examples/ runnable illustrations (see Examples)
bindings/node/ the N-API binding
tests/ the contract pins — snapshots, differentials, real-crypto
tests/fixtures/ real signed stream files from dev-net, mainnet, and test networks
```
Golden 文件是解析器对固定测试集的规范
输出的已提交快照。仅在*有意*更改输出时重新生成一个
(`hiero-streams parse `),并像审查契约变更一样审查 diff。新固定测试集会针对其共识窗口的镜像节点数据进行验证(参见 `tests/record_mirror_differential.rs`),然后才会提交其快照。
## 许可证
Apache-2.0 — 见 [`LICENSE`](LICENSE)。不附属于或受
Hedera、Hashgraph、Hiero 项目或 LF Decentralized Trust 的认可。
标签:Hedera, Rust, 共识机制, 区块链, 可视化界面, 密码学验证, 数据解析, 网络流量审计, 通知系统