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 stateblockchain-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日志级别取值0–4或日志分类categories字符串如bcutil:INFO--block-start arg0从指定区块高度开始统计--block-stop arg0在指定区块高度停止0表示直到数据库最高高度--with-inputs关附带输入inputs统计最小 / 最大 / 平均每笔交易的输入数--with-outputs关附带输出outputs统计最小 / 最大 / 平均每笔交易的输出数--with-ringsize关附带环大小ring size统计最小 / 最大 / 平均环大小--with-hours关附带每小时交易数txns per hourGMT 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_dircryptonote_core.cpp。它的默认值由tools::get_default_data_dir()决定util.cppUnix / macOS$HOME/.bitmoneroWindowsC:\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接受0–4的数字级别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 OKStarting from height start, stopping at height stop四、输出格式详解每一列是什么表头由源码按“默认列 按需附加列”的顺序拼接生成blockchain_stats.cpp顺序如下固定列始终存在列名含义Date统计日GMT格式%Y-%m-%dBlocks/day当日产出的区块数Blocks截至当日的累计区块数Txs/Day当日交易数不含矿工 coinbase 交易coinbase 不计入tx_hashesTxs截至当日的累计交易数Bytes/Day当日新增字节数含区块 blob、交易 pruned blob以及可用的 prunable blob见下文Bytes截至当日的累计字节数按需附加列启用对应开关后出现开关附加列含义--with-emissionEmission/day、Emission每日新增货币发行量、截至当日的累计发行总量原子单位--with-feesFees/day、Fees每日交易手续费、累计手续费原子单位--with-diffDiffMin、DiffMax、DiffAvg当日最小 / 最大 / 平均 PoW 难度--with-inputsInMin、InMax、InAvg当日单笔交易输入数的最小 / 最大 / 平均值--with-outputsOutMin、OutMax、OutAvg当日单笔交易输出数的最小 / 最大 / 平均值--with-ringsizeRingMin、RingMax、RingAvg当日单笔交易环大小签名环成员数的最小 / 最大 / 平均值--with-hours00:00…23: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区块本身的 blobget_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/fees与prevemission/prevfees维护跨天时先输出“当日值”和“累计值”再累加doprint()中逻辑。5. 难度统计对每个区块调用db-get_block_difficulty(h)取该高度的难度值维护当日最小、最大与总和跨天时输出min / max / sum ÷ blocksblockchain_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恰好落在一个自然日中间该日仍会输出部分日的统计行扫描过程中途按 CtrlC已完成的日期行都会正常输出方便长链分析时提前取数。六、进阶用 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可放心对生产节点反复运行。数据日期时区所有“每日 / 每小时”分桶均基于 GMTUTC时间。八、延伸阅读工具说明文档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),仅供参考