news 2026/9/7 2:50:37

Bitcoin Core 0.15.0 深度解析:per-output 链状态模型、多钱包支持与手续费估算重构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Bitcoin Core 0.15.0 深度解析:per-output 链状态模型、多钱包支持与手续费估算重构

Bitcoin Core 0.15.0 深度解析:per-output 链状态模型、多钱包支持与手续费估算重构

【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoin

Bitcoin Core 0.15.0 是该项目早期最重要的版本之一。本篇基于仓库中保留的官方发布说明 doc/release-notes/release-notes-0.15.0.md,系统梳理该版本的升级流程与兼容性约束、六大性能改进的底层原理、手续费估算体系重构、多钱包(multi-wallet)RPC 接口规范、Coin Age Priority 策略移除的影响面,以及全部新增/变更 RPC 的精确语义,并结合当前仓库源码印证这些特性在现代代码中的落点,帮助运维与开发者准确理解 0.15.0 的设计决策及其后续演进方向。

升级流程与数据兼容性

0.15.0 是重大版本升级,官方给出如下升级步骤:运行旧版本时先将其完全关闭(旧版本关闭可能需数分钟),再通过安装程序(Windows)或直接替换/Applications/Bitcoin-Qt(macOS)或bitcoind/bitcoin-qt(Linux)完成升级。

升级时必须注意三个数据格式层面的事实:

  • 链状态数据库格式变更:首次运行 0.15.0 时,chainstate 数据库会被转换到新格式,耗时从几分钟到半小时不等,取决于机器速度。
  • fee_estimates.dat文件格式变更:因此从 0.15.0 降级、或升级到 0.15.0 都会导致所有历史手续费估计数据被丢弃。
  • 无 0.8 之前版本的自动升级路径:block 数据库格式在 0.8.0 时也发生过变更,不存在从 0.7.x 及更早版本直接升级到 0.15.0 的自动代码,必须重新下载区块链。不过钱包旧版本数据仍然支持。

降级警告:0.15.0 的 chainstate 数据库与更早版本不兼容。若运行 0.15 后决定切回旧版本,需要旧版本加-reindex-chainstate选项以旧格式重建链状态数据结构;如果节点开启了剪枝(pruning),这等同于重新下载并处理整个区块链。

兼容性范围:Bitcoin Core 在 Linux 内核、macOS 10.8+ 以及 Windows Vista 及之后的系统上经过充分测试,Windows XP 不受支持;大多数其他 Unix-like 系统可以运行但测试频率较低。

0.15.0 版本特别注意事项

SegWit 地址支持的边界

0.15.0 通过addwitnessaddressRPC 支持向钱包添加隔离见证(segregated witness)地址。但官方明确将其标注为测试/专家级 RPC,不保证从备份恢复,只有清楚自己在做什么的用户才应调用它;完整的钱包端 SegWit 支持在后续版本才落地。

加密 HD 钱包的重扫问题

与之前版本一致,加密 HD 钱包在解锁之前无法补充 keypool(密钥池)。这意味着从备份恢复一个加密 HD 钱包时,用户必须以非常长的超时时间解锁钱包并手动触发重扫,否则在自动 topup 无法运行时可能丢失部分密钥。0.15.0 本身还没有rescanRPC,只能借助某个import*命令(配合另一个可信钱包生成的 dummy 地址)来触发重扫。

性能改进:六大优化及其原理

0.15.0 包含一系列显著的性能改进,使 IBD(初始块下载)、启动、交易与区块验证速度大幅提升:

1. 链状态数据库从 per-transaction 切换为 per-output 模型

这是 0.15.0 的核心数据结构变更(对应 PR 10195)。chainstate 数据库(用于跟踪 UTXO)从按交易(transaction)存储改为按输出(output)存储。该模型的优势:

  • 避免了对未使用输出进行反序列化/序列化的 CPU 开销;
  • 内存占用更可预测;
  • 代码更简单;
  • 可适配各种未来的缓存刷新策略。

量化结果:IBD 与 reindex 的区块链验证速度提升约 30-40%,内存占用减少 10-20%,落盘频率大幅降低;唯一代价是磁盘数据库体积增大约 15%,格式转换期间可能额外占用数 GB 空间。

这一变更也直接引发了后文所述的gettxout等 RPC 响应字段变化——per-output 模型不再存储未花费输出所属交易的版本号。

2. 全量-dbcache真正用作缓存

早期版本在将 UTXO 更新刷入磁盘时会出现内存尖峰,导致-dbcache配置的一半内存只能实际用作缓存,另一半要预留用于刷写缓冲。0.15.0 移除了这一限制(对应 PR 10148),-dbcache的全部额度现在都真正用作缓存,刷盘频率因此降低 2 倍以上。

3. 脚本验证结果整体缓存

此前版本只在交易进入内存池时缓存签名验证结果,0.15.0 扩展为缓存整个脚本有效性(对应 PR 10192)。这意味着若区块中的交易已被内存池接受,则无需重新执行 scriptSig 求值。经验测试显示新区块验证速度提升 40-50%。

4. LevelDB 升级至 1.20

LevelDB 升级到 1.20(对应 PR 10544),该版本在支持 SSE 4.2 的架构上启用了 CRC 硬件加速,同步与区块验证随之变快。当前仓库中src/leveldb/目录即内嵌的 LevelDB 子模块实现。

5. SHA256 的 SSE4 硬件优化

支持 SSE 4 的架构上 SHA256 提速约 50%,整体带来约 5% 的 IBD 与区块验证加速(对应 PR 10821)。注意:0.15.0 的 release 构建默认禁用SHA256 硬件优化,构建时需显式传入--enable-experimental-asm才能启用。

6. 钱包创建提速约 20 倍

keypool 补充(refill)不再在每生成一个密钥后就刷写钱包,新建钱包速度提升约 20 倍(对应 PR 10831)。部分加速收益被用于把默认 keypool 容量提升到 1000 个密钥,使备份恢复更稳健。

手续费估算体系重构

0.15.0 显著改进了手续费估算:钱包使用的估计更准确,estimatesmartfeeestimaterawfee也为高级用户提供了更宽的选项(对应 PR 10199)。

内部逻辑与钱包行为变化

  • 三个时间尺度:内部现在在 3 个不同的时间跨度(time horizon)上跟踪估计值,支持更长的确认目标,且对费率环境变化响应更快。
  • conservative 与 economical 两种模式conservative(保守)模式使用更长时间尺度,对费率快速波动不敏感;economical(经济)模式使用较短时间尺度,受短期费率变化影响更大——在交易活跃低迷期(例如周末)可能给出明显更低的估计,但如果费率迅速上涨,交易可能长时间得不到确认。
  • 钱包默认策略:默认使用 conservative 估计以保证交易在目标块数内确认的可靠性;对于标记为可替代(RBF)的交易,钱包默认改用 economical 估计,因为费率条件快速变化时可以用bumpfee提费补救(对应 PR 10589)。
  • 确认目标上限:现在支持最多 1008 个块(一周)的确认目标。
  • 存储更多历史费率数据,估计更精确。
  • 因驱逐(eviction)或其他非确认原因离开内存池的交易,现在也被纳入估算逻辑。
  • 估算逻辑会确认数据量足够才返回有意义的估计,数据不足时回退到默认费率。

手续费 RPC 接口变化

  • estimatefeeRPC 弃用,统一改用estimatesmartfee(GUI 使用的就是它)。
  • estimatesmartfee接口变更(对应 PR 10707):
    • nblocks参数改名为conf_target(与其他 RPC 命名一致);
    • 新增estimate_mode参数,取值为CONSERVATIVEECONOMICALUNSET(默认按CONSERVATIVE处理);
    • 返回对象新增errors成员,返回处理过程中遇到的错误;
    • 若节点运行时间不足、见到的块/交易数量不足以产生准确估计,会返回错误——旧版用 -1 表示错误,容易与费率值混淆。
  • 新增estimaterawfeeRPC 返回原始费率数据,供外部客户端实现自己的估算逻辑。

当前仓库中,estimatesmartfee的参数解析仍保留estimate_modeFeeEstimateMode的语义,实现位于 src/rpc/fees.cpp;费率数据的时间尺度统计由 src/policy/fees/block_policy_estimator.cpp 维护,钱包侧的估计选择逻辑在 src/wallet/fees.cpp——0.15.0 引入的这套接口骨架至今仍在使用。

多钱包(Multi-wallet)支持

Bitcoin Core 从 0.15.0 起支持加载多个相互独立的钱包(对应 PR 8694、PR 10849):各钱包的余额、密钥、收到的交易完全隔离。

启用方式:启动 Bitcoin 时使用多个-wallet参数(命令行或配置文件)。

GUI 限制:bitcoin-qt 中只显示并可操作第一个钱包(创建/签名交易);GUI 层面的多钱包选择留待后续版本。但即使如此,其余已加载钱包会在后台持续与节点当前 tip 保持同步——对剪枝节点尤为有用:否则加载一个最近同步位置高于剪枝高度的钱包会迫使重新下载并验证整条区块链。

多钱包下的 RPC 接口规则

  • 单钱包模式:RPC 接口与bitcoin-cli完全不变,所有调用方式照旧。
  • 多钱包模式下的 node-level RPC:所有不依赖钱包的节点级方法照常工作,HTTP 请求仍发往常规的<RPC IP>:<RPC 端口>端点,bitcoin-cli用法不变。
  • 多钱包模式下的 wallet-level RPC:每个请求必须指明目标钱包:
    • HTTP 请求发往<RPC IP>:<RPC 端口>/wallet/<钱包名>,例如127.0.0.1:8332/wallet/wallet1.dat
    • bitcoin-cli命令加-rpcwallet选项,例如bitcoin-cli -rpcwallet=wallet1.dat getbalance
  • 新增 node-levellistwalletsRPC:列出当前已加载的钱包,其返回的名称与 HTTP 端点及rpcwallet参数使用的名称一致。

官方同时声明:虽然多钱包已完整支持,但 0.15.0 的 RPC 多钱包接口仍应视为不稳定,未来版本可能做出向后不兼容的修改。

当前仓库中,HTTP 层在 src/httprpc.cpp 中注册/wallet/前缀的处理器,bitcoin-cli在 src/bitcoin-cli.cpp 中实现-rpcwallet参数并据此拼接/wallet/<walletname>端点,listwallets的实现位于 src/wallet/rpc/wallet.cpp,功能测试见 test/functional/wallet_multiwallet.py。

GUI 中的 Replace-by-Fee 支持

Bitcoin Core 自 0.12.0 起支持创建 opt-in RBF 交易,自 0.14.0 起提供bumpfeeRPC 以更高费用替换未确认的 opt-in RBF 交易。0.15.0 在 GUI 中同时支持这两项操作(对应 PR 9592):发送界面可勾选 RBF 选项,且内置了带用户确认的简单 fee bumper。

Coin Age Priority 的彻底移除

此前版本中,区块可保留一部分空间给按 UTXO 年龄与价值排序的交易(Coin Age Priority)。这纯属矿工的政策选择,并无共识规则;实践中只有极少数矿工还在使用。0.15.0 移除了对 Coin Age Priority 的全部残余支持(对应 PR 9602),影响面包括:

  • “免费交易”概念被移除:过去高 Coin Age Priority 交易即使不带矿工费也可被中继,现在不再可能。控制免费交易中继的-limitfreerelay-relaypriority选项因此被删除。
  • -sendfreetransactions选项被移除,因为几乎所有矿工都不打包无手续费交易。
  • -blockprioritysize选项被移除。
  • estimatepriorityestimatesmartpriorityRPC 被移除。
  • getmempoolancestorsgetmempooldescendantsgetmempoolentrygetrawmempool不再返回startingprioritycurrentpriority字段。
  • prioritisetransaction不再接受priority_delta参数,改为一个无功能的dummy占位参数以保持位置参数兼容;该 RPC 仍可通过fee_delta参数改变交易在打包时的表观费率。
  • -minrelaytxfee现在允许设置为 0。一旦设置,低于minrelaytxfee(每 kB)的手续费会被中继、挖矿和交易创建拒绝;默认值为 1000 satoshi/kB。
  • -printpriority更新为只输出挖矿代码打包进区块的交易费率与哈希。

内存池持久化开关

0.14 引入了内存池跨重启持久化(关闭前将 mempool 保存至数据目录的mempool.dat,重启时恢复)。0.15.0 增加-persistmempool命令行选项(对应 PR 9966)来控制该特性:默认值为 true,即关闭时保存、启动时加载;设为 false 则不加载也不保存mempool.dat。当前仓库中该选项在 src/init.cpp 注册(默认值取自DEFAULT_PERSIST_MEMPOOL),并新增了-persistmempoolv1选项以兼容旧格式数据文件。

0.15.0 新增的 RPC 方法

  • abortrescan:中止当前钱包重扫,例如由importprivkey触发的重扫(对应 PR 10208)。
  • combinerawtransaction:接受原始交易的 JSON 数组,合并为单个原始交易(对应 PR 10571)。
  • estimaterawfee:返回原始费率数据,便于外部实现自定义估算逻辑。
  • getchaintxstats:返回链上交易总数与速率的统计信息(对应 PR 9733)。
  • listwallets:列出当前已加载钱包,详见多钱包章节。
  • uptime:返回bitcoind自上次启动以来的总运行时长(对应 PR 10400)。

低级 RPC 变更详解

以下是 0.15.0 对既有 RPC 语义的全部底层变更,对接集成方务必逐一核对:

  • 多钱包模式下,钱包类 RPC 必须指明目标钱包。
  • per-output 模型不再存储未花费输出的交易版本号,因此:
    • gettxout响应中不再有version字段;
    • gettxoutsetinfo报告hash_serialized_2而非hash_serialized——后者不承诺(commit to)交易版本号,但承诺高度与 coinbase 信息;
    • getutxosREST 路径的 JSON 格式不再报告txvers字段,二进制格式对交易版本恒报 0。
  • estimatefee弃用,改用estimatesmartfee
  • gettxoutsetinfo响应以disk_sizebogosize取代bytes_serialized:前者是对实际磁盘占用的更准确(但非确定性)估计;后者与磁盘占用无关,是数据库无关的 UTXO 集合大小度量——每个 UTXO 条目计为 50 加上其 scriptPubKey 长度(对应 PR 10426)。
  • signrawtransaction不能再用于合并多个交易,改用combinerawtransaction(对应 PR 10571)。
  • fundrawtransaction不再接受reserveChangeKey选项。该选项曾允许用 keypool 中的密钥为找零地址出资而不将其移出 keypool,密钥随后可被getnewaddress再次取用,可能造成令人困惑甚至危险的行为(对应 PR 10784)。
  • estimatepriorityestimatesmartpriority被移除(Coin Age Priority 移除的连带结果)。
  • listunspent新增query_options参数(对应 PR 8952),为一个 JSON 对象,可含以下成员:
    • minimumAmount——每个 UTXO 的最小面值;
    • maximumAmount——每个 UTXO 的最大面值;
    • maximumCount——UTXO 的最大数量;
    • minimumSumAmount——所有 UTXO 总面额的最小值。
  • getmempoolancestorsgetmempooldescendantsgetmempoolentrygetrawmempool不再返回startingprioritycurrentpriority
  • dumpwallet现在返回转储钱包的完整绝对路径;此前即使成功也不返回任何值(对应 PR 9740)。
  • getpeerinfo每个 peer 的返回对象新增addrbind成员,包含到该 peer 连接所用的本机 IP 与端口;它补充了addrlocal(后者是 peer 所报告的本机地址)(对应 PR 10478)。
  • disconnectnode支持按节点 ID 断连(除 IP/端口外),通过新增的nodeid参数调用(对应 PR 10143)。
  • prioritisetransaction第二参数由priority_delta改名dummy,无任何功能效果,仅为位置参数兼容保留。
  • resendwallettransactions-walletbroadcast设为 false 时会抛出错误(对应 PR 10995)。
  • submitblock第二参数由parameters改名dummy——该参数从来没有任何效果,改名只是向用户明示这一点(对应 PR 10191)。注意客户端仍应使用位置参数调用submitblock以兼容 BIP 22。
  • getblockverbose参数改名为verbosity,取 0–2 的整数:0 等价于verbose=false,1 等价于verbose=true,2 输出每笔交易的完整详情(即getrawtransaction给出的格式)。旧的verbose布尔命名参数仍保持兼容。
  • 错误码修正(对应 PR 9853):
    • getblock:块不在磁盘上(例如已被剪枝)时返回 RPC_MISC_ERROR,此前为 RPC_INTERNAL_ERROR;
    • pruneblockchain:节点非剪枝模式时返回 RPC_MISC_ERROR(此前 RPC_METHOD_NOT_FOUND);时间戳太晚时返回 RPC_INVALID_PARAMETER(此前 RPC_INTERNAL_ERROR);区块链太短无法剪枝时返回 RPC_MISC_ERROR(此前 RPC_INTERNAL_ERROR);
    • setban:IP/子网无效时返回 RPC_CLIENT_INVALID_IP_OR_SUBNET(此前 RPC_CLIENT_NODE_ALREADY_ADDED);解除未封禁节点时返回 RPC_CLIENT_INVALID_IP_OR_SUBNET(此前 RPC_MISC_ERROR);
    • removeprunedfunds:无法移除交易时返回 RPC_WALLET_ERROR,交易不在钱包中时返回 RPC_INVALID_PARAMETER(此前均为 RPC_INTERNAL_ERROR);
    • fundrawtransaction:找零地址无效返回 RPC_INVALID_ADDRESS_OR_KEY;无法创建交易返回 RPC_WALLET_ERROR 且错误消息含更多细节(此前分别为 RPC_INVALID_PARAMETER / RPC_INTERNAL_ERROR);
    • bumpfee系列细化:交易在钱包中有后代返回 RPC_INVALID_PARAMETER;在内存池中有后代返回 RPC_INVALID_PARAMETER;已被挖出或与被挖交易冲突、非 BIP 125 可替代、已被其他交易提过费、包含不属于本钱包的输入、有多个找零输出、没有找零输出、费用过高、费用过低、找零输出太小不足以提费——以上一律返回 RPC_WALLET_ERROR(此前分散在 RPC_MISC_ERROR、RPC_INVALID_ADDRESS_OR_KEY、RPC_INVALID_REQUEST 等)。

变更日志概览(按模块)

0.15.0 的完整变更日志收录了约 460 个条目,按模块划分如下,读者可按需深入 doc/release-notes/release-notes-0.15.0.md 查阅逐条 PR 编号与提交哈希:

  • RPC 与其他 API:新增logginguptimegetchaintxstatsRPC;getblock支持交易详情输出;getblockchaininfo返回 BIP 激活信号统计;getmemoryinfo新增 mallocinfo 模式;generate移入 rpcwallet;大量参数与返回值修正。
  • 区块与交易处理:per-txout 链状态切换(#10195)、非原子化 UTXO 刷写(#10148)、移除 min reasonable fee(#9548)、新增-stopatheight基准测试选项(#10290)、-forcecompactdb强制 LevelDB 压实(#10985)等。
  • P2P 协议与网络:reject 消息发送正确错误码(#10135)、headers 同步超时(#10345)、广播地址周期改为每天(#10460)、Tor 控制端口解析器改进(#10408)等。
  • 验证(Validation):脚本执行结果整体缓存(#10192)、SSE4 优化 SHA256(#10821)、DisconnectTip性能改进(#9208)、非 2 的幂签名缓存大小支持(#9533)等。
  • 构建系统:Depends 工具链更新(#10325)、显式探测 BDB 5.3(#10803)、校验汇编器对 crc32 函数的支持(#10806)、修复 depends 构建缺失 sse42 的问题(#10971)等。
  • GUI:RBF 勾选框(#9592)、fee bumper 全面重写(#10449)、手续费滑条改为下拉框并扩展确认目标(#10769)、启动界面可取消 txdb 升级(#10660)、Qt 钱包单元测试(#9974)等。
  • 钱包:多钱包基础支持(#8694)与端点支持(#10849)、HD 链分离(找零用内部链,#9294)、keypool 内外部条目跟踪(#10235)、keypool 批量刷写与扩容(#10831)、-usewallet改名-rpcwallet(#10883)、listwallets与多钱包测试(#10604)等。
  • 测试与 QA:功能测试框架大幅重构(test_framework 组织、assert_start_raises_init_error、日志合并工具 combine_logs.py)、afl-fuzz 加速约 200 倍(#10415)、多钱包功能测试wallet_multiwallet.py(当前仓库位于 test/functional/wallet_multiwallet.py)等。
  • 杂项:FastRandomContext 切换到 ChaCha20(#9792)、LevelDB 日志接入比特币日志(#9999)、-txindex变更需要-reindex而非-reindex-chainstate(#11108)、RNG 使用 rdrand 熵源(#10377)等。

结语:0.15.0 的历史坐标

从源码结构看,0.15.0 引入的几乎所有关键骨架都在当前仓库中延续至今:per-output 的CCoinsMap模型、/wallet/HTTP 端点与-rpcwallet机制、estimatesmartfeeconf_target/estimate_mode参数体系、mempool.dat持久化(并进一步演化出-persistmempoolv1兼容选项)、以及bumpfee的严格错误码语义。理解这一版本的变更边界——哪些格式不向后兼容、哪些 RPC 字段消失、哪些策略选项被删除——对于维护长期运行的节点、编写跨版本兼容的钱包客户端,以及阅读当前 Bitcoin Core 代码库,都是必要的基础。

【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoin

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

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

软件工程与开发框架:技术博客选题与实战写作指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 2:49:53

Java生成微信小程序码的5种实现方式与避坑指南

简介&#xff1a;面向Java后端开发者&#xff0c;这套代码包解决微信小程序二维码生成问题&#xff0c;覆盖裂变邀请、渠道推广等需要专属小程序码的场景。作者基于微信官方getUnlimitedQRCode接口&#xff0c;从前端-后端API-微信API的安全链路切入&#xff0c;总结出5种实现方…

作者头像 李华