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, 共识机制, 区块链, 可视化界面, 密码学验证, 数据解析, 网络流量审计, 通知系统