news 2026/9/23 13:28:12

Monero Blockchain Stats 工具指南:从创世块到当前状态的区块链每日统计导出

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Monero Blockchain Stats 工具指南:从创世块到当前状态的区块链每日统计导出

Monero Blockchain Stats 工具指南:从创世块到当前状态的区块链每日统计导出

【免费下载链接】moneroMonero: the secure, private, untraceable cryptocurrency项目地址: https://gitcode.com/gh_mirrors/mo/monero

导读

monero-blockchain-stats是 Monero 项目提供的一款链上数据分析工具,它直接读取本地已同步的区块链数据库(BlockchainDB),逐块扫描并聚合出从创世区块(2014 年 4 月)至今的每日统计,覆盖区块数、交易数、字节数、手续费、发行量、难度、环大小、输入输出等维度,并以 Tab 分隔的 CSV 格式输出到终端,便于重定向保存或管道接入自研脚本做进一步分析。读完本文,你将掌握该工具的完整参数用法、输出列语义,以及其底层逐块扫描与按天聚合的实现原理,能够独立用它生成 Monero 区块链增长趋势数据并绘制图表。

一、工具定位:它是做什么的

Monero Blockchain Stats utility 的官方定义是:exports daily statistics for the monero blockchain from creation through current state(blockchain-stats-readme.md)。也就是说,它把整条链上每个区块、每笔交易的关键指标,按“自然日(GMT)”为单位聚合,输出一行一条日统计记录。

与 monero-blockchain-export、monero-blockchain-import 这类“搬运区块原始数据”的工具不同,stats 工具做的是在本地链上做在线聚合分析,不产生区块数据文件,只输出统计表格。它属于 src/blockchain_utilities 目录下的实用工具家族,构建目标名与输出二进制名均为monero-blockchain-stats(见 CMakeLists.txt)。

使用前提

  • 需要一条已同步到目标高度的本地区块链数据库。工具以只读方式打开数据库(db->open(filename, DBF_RDONLY),见 blockchain_stats.cpp),不会修改任何链上数据,但也不会自行联网同步,因此必须先运行monerod完成同步(或用monero-blockchain-import导入已有数据)再执行本工具。
  • 统计范围默认从高度 0 直到数据库当前高度;也可通过--block-start/--block-stop限定区间。

二、基本用法与输出流向

直接运行

$ monero-blockchain-stats

这会加载已有的区块链数据库,并将统计结果打印到终端。输出格式为Tab 分隔的 CSV:每个自然日一行,字段之间以制表符(\t)分隔。默认列包括:

  • Blocks per Day(每日区块数)
  • Total Blocks(累计区块数)
  • Transactions per Day(每日交易数)
  • Total Transactions(累计交易数)
  • Bytes per Day(每日字节数)
  • Total Bytes(累计字节数)

保存为 CSV 文件

由于输出直接写到标准输出,重定向即可落盘:

# 保存为带日期的 CSV 文件 monero-blockchain-stats > stats-$(date +'%Y-%m-%d').csv

管道接入脚本

把输出喂给自定义脚本做入库或可视化:

monero-blockchain-stats | save-to-database.sh

注意:输出中除了数据行,还会在数据区之前打印一行# DATA注释(源码见 blockchain_stats.cpp),该行是专为 GnuPlot 的index "DATA"语法准备的索引标记,自定义脚本按\t解析时应跳过以#开头的行和表头行。

三、全部命令行选项详解

以下选项均来自源码中的po::options_description定义(blockchain_stats.cpp)。运行monero-blockchain-stats --help可查看与源码一致的最新说明。

选项默认值说明
--data-dir arg平台默认数据目录指定区块链数据库的存放位置(详见下文“数据目录解析规则”)
--testnet在 testnet(测试网)上运行
--stagenet在 stagenet(暂存网)上运行
--log-level arg0日志级别,取值04或日志分类(categories)字符串,如bcutil:INFO
--block-start arg0从指定区块高度开始统计
--block-stop arg0在指定区块高度停止(0表示直到数据库最高高度)
--with-inputs附带输入(inputs)统计:最小 / 最大 / 平均每笔交易的输入数
--with-outputs附带输出(outputs)统计:最小 / 最大 / 平均每笔交易的输出数
--with-ringsize附带环大小(ring size)统计:最小 / 最大 / 平均环大小
--with-hours附带每小时交易数(txns per hour,GMT 24 小时分桶)
--with-emission附带货币发行量(coin emission)统计:每日新增 / 累计总量
--with-fees附带交易手续费(txn fees)统计:每日手续费 / 累计手续费
--with-diff附带难度(difficulty)统计:每日最小 / 最大 / 平均难度

--regtest(回归测试模式)也在 cryptonote_core.cpp 中被定义为通用核心参数,工具继承了cryptonote::arg_regtest_on(见 blockchain_stats.cpp),主要用于测试场景。

数据目录解析规则

--data-dir底层对应cryptonote::arg_data_dir(cryptonote_core.cpp)。它的默认值由tools::get_default_data_dir()决定(util.cpp):

  • Unix / macOS:$HOME/.bitmonero
  • Windows:C:\ProgramData\bitmonero

并且该参数带有一个网络类型联动钩子:当指定--testnet时,实际数据目录自动变为<data-dir>/testnet;指定--stagenet时变为<data-dir>/stagenet;指定--regtest时变为<data-dir>/fake。这就是为什么主网、测试网、暂存网的数据彼此隔离。

网络模式互斥规则

网络类型由core::get_network_type_from_args统一解析(cryptonote_core.cpp):--testnet--stagenet--regtest三者最多只能指定一个,若同时指定多个会抛出运行时错误,避免误用错误网络的数据库。

日志级别说明

--log-level接受04的数字级别(0 最安静,4 最详细),也接受分类字符串。默认情况下日志级别为0,并额外强制开启bcutil:INFO分类(见 blockchain_stats.cpp),日志写入默认路径的monero-blockchain-stats.log。观察启动过程的关键日志包括:

  • Initializing source blockchain (BlockchainDB)
  • Loading blockchain from folder <path> ...
  • Source blockchain storage initialized OK
  • Starting from height <start>, stopping at height <stop>

四、输出格式详解:每一列是什么

表头由源码按“默认列 + 按需附加列”的顺序拼接生成(blockchain_stats.cpp),顺序如下:

固定列(始终存在)

列名含义
Date统计日(GMT,格式%Y-%m-%d
Blocks/day当日产出的区块数
Blocks截至当日的累计区块数
Txs/Day当日交易数(不含矿工 coinbase 交易,coinbase 不计入tx_hashes
Txs截至当日的累计交易数
Bytes/Day当日新增字节数(含区块 blob、交易 pruned blob,以及可用的 prunable blob,见下文)
Bytes截至当日的累计字节数

按需附加列(启用对应开关后出现)

开关附加列含义
--with-emissionEmission/dayEmission每日新增货币发行量、截至当日的累计发行总量(原子单位)
--with-feesFees/dayFees每日交易手续费、累计手续费(原子单位)
--with-diffDiffMinDiffMaxDiffAvg当日最小 / 最大 / 平均 PoW 难度
--with-inputsInMinInMaxInAvg当日单笔交易输入数的最小 / 最大 / 平均值
--with-outputsOutMinOutMaxOutAvg当日单笔交易输出数的最小 / 最大 / 平均值
--with-ringsizeRingMinRingMaxRingAvg当日单笔交易环大小(签名环成员数)的最小 / 最大 / 平均值
--with-hours00:0023:00共 24 列当日各 GMT 整点小时的交易数分桶

几个实现细节值得注意:

  • 当启用--with-inputs/--with-outputs/--with-ringsize时,平均值列会以setprecision(2) + fixed格式输出两位小数(blockchain_stats.cpp)。
  • 发行量与手续费使用print_money()输出(即不带小数点的原子单位字符串,与钱包显示习惯一致),难度、字节数等为普通整数。
  • 环大小统计只针对txin_to_key类型的输入,取的是首个输入key_offsets.size()(blockchain_stats.cpp)。
  • 当某日没有任何交易时,平均列的分母会取tottxs = 1兜底,避免除零(blockchain_stats.cpp)。

一个典型输出样例

启用全部开关后,某行数据形如(字段以\t分隔,此处用空格示意):

Date Blocks/day Blocks Txs/Day Txs Bytes/Day Bytes Emission/day Emission Fees/day Fees DiffMin DiffMax DiffAvg InMin InMax InAvg OutMin OutMax OutAvg RingMin RingMax RingAvg 00:00 01:00 ... 23:00 2014-04-18 40 40 200 200 123456 123456 300000000000 300000000000 0 0 1 100 50 1 4 2.10 1 3 2.00 1 3 2.00 5 3 ... 2

五、工作原理:源码级剖析

整个程序是一个单遍顺序扫描:从block_start开始,逐块读取、解析、累加,遇到“跨天”时输出一行统计并重置当日累计值。主循环见 blockchain_stats.cpp,单日输出逻辑见doprint()(blockchain_stats.cpp)。

1. 只读打开 BlockchainDB

工具通过工厂函数new_db()创建数据库后端实例(默认即 LMDB 实现,见 blockchain_db),然后用DBF_RDONLY标志打开,确保绝不会写入或修改数据库(blockchain_stats.cpp)。数据库文件名为data-dir下的db->get_db_name()(LMDB 下即lmdb目录)。因此哪怕在已同步节点上反复运行该工具,也是完全安全的。

2. 按天聚合与月末边界处理

工具用 GMT 时间(get_gmt_time)把每个区块的时间戳映射到自然日,判断“跨天”的条件是:

if (currtm.tm_mday > prevtm.tm_mday || (currtm.tm_mday == 1 && prevtm.tm_mday > 27))

即“日号变大”或“从月末的 27+ 跳回 1 号”。源码还专门处理了**时间戳伪造(timestamp fudging)**的边界情况:若前一天是 1 号而后一天日号大于 27(说明前一天的 1 号其实是被人为后移的时间戳),则跳过这次跨天输出,避免产生虚假的“空日”行(blockchain_stats.cpp)。

3. 字节数统计口径

每个区块的字节数包含三部分(blockchain_stats.cpp):

  • 区块本身的 blob(get_block_blob_from_height);
  • 每笔交易的pruned blobget_pruned_tx_blob,即保留签名所需前缀部分);
  • 若节点还保留了可剪除部分,则追加prunable blobget_prunable_tx_blob)的字节数。

后两者对应 blockchain_db.h 中声明的数据库接口,LMDB 实现见 db_lmdb.cpp。因此“Bytes”列反映的是本地数据库实际存储的字节口径,在已剪枝(pruned)节点上会小于全节点。

4. 发行量与手续费的计算

  • 手续费:对区块内每笔交易调用get_tx_fee(tx)累加(blockchain_stats.cpp)。
  • 发行量emission += coinbase_amount - tx_fee_amount,其中coinbase_amount来自矿工交易输出总额(get_outs_money_amount(blk.miner_tx))(blockchain_stats.cpp)。即“新增发行 = coinbase 总额 − 该块手续费”,因为手续费在 Monero 中同样由矿工收取、但本质来自用户而非新铸造。
  • 每日与累计两列分别由emission/feesprevemission/prevfees维护,跨天时先输出“当日值”和“累计值”再累加(doprint()中逻辑)。

5. 难度统计

对每个区块调用db->get_block_difficulty(h)取该高度的难度值,维护当日最小、最大与总和,跨天时输出min / max / sum ÷ blocks(blockchain_stats.cpp)。

6. 按小时分桶

启用--with-hours后,每笔交易按其区块时间戳的小时数(currtm.tm_hour)累加进txhr[0..23],跨天输出 24 个分桶值(blockchain_stats.cpp)。

7. 中断与停止条件

程序安装了 SIGINT/SIGTERM 信号处理器,收到信号后置stop_requested,主循环在下一个区块处跳出(blockchain_stats.cpp)。循环结束后若仍有未输出的当日累计值,会再调用一次doprint()收尾(blockchain_stats.cpp)。这也意味着:

  • 若指定--block-stop恰好落在一个自然日中间,该日仍会输出部分日的统计行;
  • 扫描过程中途按 Ctrl+C,已完成的日期行都会正常输出,方便长链分析时提前取数。

六、进阶:用 GnuPlot 绘制增长曲线

工具源码注释中内置了一组可直接使用的 GnuPlot 脚本(blockchain_stats.cpp),配合默认输出(仅 6 个固定列)可以快速画出 Monero 区块链增长趋势:

set key autotitle columnhead set title "Monero Blockchain Growth" set timefmt "%Y-%m-%d" set xdata time set xrange ["2014-04-17":*] set format x "%Y-%m-%d" set yrange [0:*] set y2range [0:*] set ylabel "Txs/Day" set y2label "Bytes" set y2tics nomirror plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, '' using (timecolumn(1,"%Y-%m-%d")):7 axes x1y2 with lines

要点说明:

  • index "DATA"对应输出中的# DATA注释行,GnuPlot 会跳过其之前的空行与注释;
  • 第 4 列是Txs/Day,第 7 列是Bytes(默认 6 列时第 7 列为累计 Bytes);若加了可选开关,列号会右移,需要相应调整using中的列索引;
  • 两条曲线分别使用左轴(Txs/Day)与右轴(Bytes)绘制。

七、常见问题与注意事项

场景说明
报错Error opening database--data-dir指向的路径下没有可用的 BlockchainDB,或数据库属于另一个网络。请确认节点已同步完成,且网络模式(主网 /--testnet/--stagenet)与数据库一致。
统计范围如何限定--block-start <h>从指定高度开始,用--block-stop <h>提前终止(默认 0 表示到链顶)。
输出精度平均值列保留两位小数;发行量、手续费为原子单位整数。
剪枝节点的影响Bytes 列依赖get_prunable_tx_blob是否可返回数据;在剪枝节点上字节数会偏小,但区块数、交易数、难度、发行量、手续费等统计不受影响。
是否修改链数据完全只读(DBF_RDONLY),可放心对生产节点反复运行。
数据日期时区所有“每日 / 每小时”分桶均基于 GMT(UTC)时间。

八、延伸阅读

  • 工具说明文档:blockchain-stats-readme.md
  • 核心实现:blockchain_stats.cpp
  • 构建目标与安装规则:CMakeLists.txt
  • 数据库接口(pruned / prunable blob 读取):blockchain_db.h、db_lmdb.cpp
  • 通用参数(--data-dir/--testnet/--stagenet/ 网络互斥)定义:cryptonote_core.cpp
  • 默认数据目录解析:util.cpp
  • 同目录兄弟工具:导出 blockchain_export.cpp、导入 blockchain_import.cpp、用量分析 blockchain_usage.cpp、剪枝 blockchain_prune.cpp

综上,monero-blockchain-stats是理解 Monero 链上历史演化的低成本入口:一条命令即可获得从创世块至今的每日区块、交易、字节、发行量、手续费、难度与环大小全景数据,配合重定向、管道与 GnuPlot,足以支撑独立的区块链数据分析与可视化任务。

【免费下载链接】moneroMonero: the secure, private, untraceable cryptocurrency项目地址: https://gitcode.com/gh_mirrors/mo/monero

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 13:26:52

okbiye 五大核心功能解析,一站式搞定你的毕设

2026 年&#xff0c;AI 论文工具已经成为应届生做毕设的标配&#xff0c;但市面上 AI 论文工具五花八门&#xff0c;有的功能零散&#xff0c;有的只能单独做降重&#xff0c;有的缺少文献能力&#xff0c;还有的做不了学术图表。很多同学需要同时打开多个软件来回切换&#xf…

作者头像 李华
网站建设 2026/9/23 13:24:34

US94061高侧电源控制器:电平移位与快速放电原理及嵌入式应用

简介&#xff1a;本资源为友顺&#xff08;UTC&#xff09;US94061高侧负载开关芯片的官方英文原版数据手册PDF&#xff0c;面向电子设计工程师、硬件开发人员及嵌入式系统电源管理开发者&#xff0c;解决便携设备中高效电源通断控制、电平转换与电池寿命优化等核心问题。文档完…

作者头像 李华
网站建设 2026/9/23 13:21:30

电动车大灯耐用性技术分析:散热、防水与 DC 功率匹配

跑外卖属于电动车大灯的极限工况&#xff1a;单日点灯时长可达数小时&#xff0c;远近光频繁切换&#xff0c;叠加雨雾、粉尘和持续震动。本文从 LED 结温、散热结构、密封防水、DC 功率链路四个技术维度&#xff0c;解释大灯"耐不耐用"由什么决定&#xff0c;并给出…

作者头像 李华
网站建设 2026/9/23 13:17:58

造形家搭建风力发电机及风电场三维模型,赋能多行业项目落地

随着风电新能源项目快速发展&#xff0c;风电场三维场景成为规划设计、数字孪生、方案汇报的重要素材。传统方式需要人工建模或者无人机倾斜摄影&#xff0c;存在周期长、成本高、流程复杂的痛点。造形家作为网页端 AI 三维场地建模工具&#xff0c;依托卫星影像、地形高程数据…

作者头像 李华
网站建设 2026/9/23 13:14:37

数据可视化图表选型指南:4大类22种统计图表分类框架与实战应用

1. 为什么图表选型这件事值得单独拿出来讲做数据分析的人都有一个共同的尴尬时刻&#xff1a;数据跑完了&#xff0c;结论也有了&#xff0c;但到了要给别人看的时候&#xff0c;打开图表工具&#xff0c;面对几十种图表类型&#xff0c;鼠标悬在半空&#xff0c;不知道点哪个。…

作者头像 李华