首页
/ Bitcoin Core 0.9.0 版本技术解读:钱包/CLI 拆分、手续费改革与可锻性修复

Bitcoin Core 0.9.0 版本技术解读:钱包/CLI 拆分、手续费改革与可锻性修复

2026-09-07 12:14:57作者:滕妙奇

本篇文章围绕 Bitcoin Core 官方仓库(integration/staging tree)中的 0.9.0 版本发布说明 展开,系统梳理这一里程碑版本在 RPC 接口、命令行选项、交易验证、钱包、挖矿与 P2P 协议层面的全部变更,并结合当前仓库源码验证其中仍然沿用的设计(如 walletpassphrase 语义、bitcoin-cli 职责拆分、minrelaytxfee 参数体系)。读完本文,你将掌握 0.9.0 升级注意事项、walletpassphrase 行为变更细节、手续费阈值模型、OP_RETURN 可修剪输出的设计动机,以及该版本对今日 Bitcoin Core 架构的直接遗产。

版本定位与升级指南

Bitcoin Core 0.9.0 是一个新的主版本(major version)发布,同时带来新功能与大量缺陷修复。官方当时通过 bitcoin.org 的 bin/0.9.0/ 目录提供二进制包,并通过 GitHub issue tracker 接收缺陷报告(详见原发布说明开头)。本文作为对该发布说明的技术档案解读,所有特性描述均以该文档及当前仓库中的延续性实现为准。

升级操作步骤

对于运行旧版本的用户,官方给出的升级流程为:

  1. 完全关闭正在运行的旧版本客户端;
  2. 等待进程完全退出——旧版本可能需要几分钟才能彻底停机,务必不要在中途强行重启;
  3. 卸载所有更早版本的 Bitcoin 程序;
  4. 重新安装:Windows 直接运行安装包;macOS 覆盖 /Applications/Bitcoin-Qt;Linux 覆盖 bitcoindbitcoin-qt 可执行文件。

自 0.7.2 及更早版本升级的注意事项

若从 0.7.2 或更早版本直接升到 0.9.0,首次运行会对区块链文件重新索引(re-index)。根据机器性能不同,这一过程耗时约 30 分钟到数小时。这是因为更早期版本的区块存储布局与 0.9.0 不同,必须重建本地数据库后才能继续同步。

Windows 用户:注意 32/64 位差异

  • 0.9.0 首次提供 Windows 64 位版客户端
  • 32 位系统在初始同步阶段容易出现虚拟内存耗尽的问题,官方因此强烈建议支持 64 位的机器安装 64 位版本;
  • 升级到 64 位版前,务必先卸载所有更早版本的 Bitcoin 客户端,避免两个版本并存导致数据目录冲突;
  • 0.9.0 发布候选 2(RC2)的 Windows 二进制未经代码签名,需要借助 PGP 与 SHA256SUMS.asc 校验文件确认二进制完整性;最终正式版(final)的 setup.exe 已做代码签名。这一"通过校验和文件验证二进制"的做法延续至今,当前仓库的构建产物说明可参考 contrib/verify-binaries/

macOS:最低系统要求提升

0.9.0 起不再支持 OS X 10.5 与 32 位 Mac,最低要求调整为:

  • 支持 64 位运算的 CPU;
  • Mac OS 10.6 或更高版本。

降级风险警告(Downgrading warnings)

0.9.0 的链状态数据(chainstate并非总是与旧版本兼容。如果在 0.9 上运行后再切回 0.8.x,旧版本启动时可能报区块链校验错误,原因在于:

  • 0.9.0 引入了 "被修剪的输出"(pruned outputs) 机制,即部分可证明不可花费(provably-unspendable)的输出不再计入未花费交易输出(UTXO)索引;
  • 0.8.x 的数据结构不认识这种省略,因而在一致性校验时报错。

解决方法是:使用旧版本时加 -reindex 参数启动,让旧版本重建其 chainstate 数据结构以修正问题。

另一个降级影响发生在钱包层:0.9 钱包首次被 0.8.x 打开时,会为了找回"丢失的已花费币"而重新扫描区块链,典型机器上耗时可达数十分钟。这类"扫描全链以修复状态"的思路,在后续版本中以生日(birthday)优化重扫描等机制继续演进(见下文钱包部分)。

品牌重构:正式更名 Bitcoin Core

为避免"Bitcoin 网络"与"Bitcoin 软件"两个概念之间的混淆,官方在 0.9.0 将参考客户端正式更名为 Bitcoin Core。这是项目品牌史上的一次关键转变,此后 Qt 图形客户端 bitcoin-qt 与守护进程 bitcoind 共同构成 Bitcoin Core 发行版,这一命名沿用至今(见 README.md)。

OP_RETURN 与"链上数据存储":可修剪输出的设计动机

0.9.0 中的 OP_RETURN 功能在社区中引发不少误读,发布说明专门澄清了两点:

  1. 这不是对"把任意数据写入区块链"的背书。此前一些方案(有的已经上线)把图片等任意数据编码成永远无法花费(forever-unspendable)的交易输出,导致比特币 UTXO 数据库无谓膨胀——每个这类输出都必须被每个全节点永久保留;
  2. 新方案把 OP_RETURN 输出设计为可证明可修剪(provably-prunable)的输出,即从协议上可证明该输出永远无法再被花费,从而允许节点在存储时将其从 UTXO 集中剔除。

发布说明同时给出明确态度:在区块链中存储任意数据依然是坏主意,存储非货币数据放在链外更廉价也更高效。这一"标准交易必须可被裁剪、UTXO 集只保留可能被花费的输出"的治理原则,从代码层面看已沉淀进共识与策略代码,例如 src/consensus/consensus.h 中的 MAX_OP_RETURN_RELAY 等上限约束,并沿用至今。

Autotools 构建系统迁移

0.9.0 将原先散落的各独立 (q)makefile 统一迁移到 autotools 构建系统,标准流程变为:

./autogen.sh
./configure
make

这一改动让熟悉开源生态的开发者可以更平滑地为项目贡献。官方同时提醒:从源码构建前务必先查阅对应平台的 doc/build-*.md 文档。

需要说明的是,从该仓库当前主分支的构建基础设施可以看到构建体系在 0.9 之后又经历了新一轮演进——根目录已是 CMakeLists.txtCMakePresets.json,并配套 doc/CMakeLists.txtdoc/build-unix.md 等新式文档;0.9.0 所代表的 autotools 阶段则是这一演进链路中承前启后的关键一环。为某历史版本做源码构建时,应以该版本 tag 附带的文档为准。

bitcoin-cli:RPC 客户端与服务器职责分离

0.9.0 之前,bitcoind 可执行文件同时充当服务器RPC 客户端(即"让正在运行的守护进程执行某操作"的能力内置其中)。0.9.0 把 RPC 客户端功能抽离为独立的 bitcoin-cli 可执行文件。当时计划逐步从 bitcoind 中移除 RPC 客户端代码,但为向后兼容会保留一两个版本。

这一职责拆分从当前仓库的代码结构看已经成为持久性架构:源码根目录下存在独立的 bitcoin-cli.cpp 入口(对应构建目标),其命令行手册见 bitcoin-cli.1,同时 bitcoin-tx.cppbitcoin-wallet.cppbitcoin-util.cpp 也都各自独立成可执行文件,构成"一个守护进程 + 一组瘦客户端工具"的现代形态。RPC 接口的通用文档可参考 JSON-RPC-interface.md

walletpassphrase RPC 行为变更:解锁窗口的覆盖语义

0.9.0 对 walletpassphrase 在钱包已经处于解锁状态时的行为做了语义调整,这是钱包加密使用中极易踩坑的细节,发布说明用两段对比讲得很清楚。

0.8 旧行为:重复解锁报错

旧版本在钱包已解锁时再次调用 walletpassphrase直接失败,且不改变原有解锁截止时间:

> walletpassphrase 1000
walletunlocktime = now + 1000
> walletpassphrase 10
Error: Wallet is already unlocked (old unlock time stays)

0.9 新行为:新解锁时间覆盖旧值

0.9.0 起,重复调用会用新的 timeout 重新计算解锁截止时间并覆盖旧值

> walletpassphrase 1000
walletunlocktime = now + 1000
> walletpassphrase 10
walletunlocktime = now + 10 (overriding the old unlock time)

从当前仓库源码看该语义的沉淀

"覆盖旧解锁时间"这一行为在当前仓库的 walletpassphrase RPC 实现中仍被明确写入帮助文本:src/wallet/rpc/encrypt.cpp 中的文档字符串写着 "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock time that overrides the old one.",与该版本发布说明完全一致。进一步看其实现逻辑:

  • timeout 参数不允许为负(否则会立即重新上锁),见 nSleepTime < 0 的校验分支;
  • timeout 被钳制在约 3 年(100000000 秒)以内以避免计算重新上锁时间时溢出;
  • passphrase 为空会被拒绝;口令错误时抛出 RPC_WALLET_PASSPHRASE_INCORRECT,并在口令包含空字符(\0)时给出专门提示(历史上某些旧版本设置的口令存在空字符问题,见源码注释中引用的 issue #27067);
  • 实际解锁最终落到 CWallet::UnlockCWallet::Unlock(const CKeyingMaterial&) 两条路径:前者会遍历 mapMasterKeys 中的多个主密钥(master key),逐一尝试用口令解密,成功后才真正解锁并升级描述符缓存;后者持有 cs_wallet 锁并设置解锁截止时间。

walletpassphrasechange(改密)与 walletlock(立即锁上)在同一文件中,三者共同构成加密钱包日常操作的完整闭环。

交易可锻性(Transaction Malleability)相关修复

0.9.0 针对交易 ID(TXID)可锻性问题做了一批针对性修复:

  • -nospendzeroconfchange 命令行选项:避免花费零确认的找零(change)输出,从而减少因找零可锻性引发的连锁问题;
  • 收紧 IsStandard() 交易规则:阻止中继与挖矿接收被"变异"的交易;
  • listtransactions/gettransaction 输出新增冲突信息:报告钱包中因花费相同输出而互相冲突的交易;
  • 修复 getbalance/listaccounts 余额计算缺陷:此前对双花(double-spent)或变异交易会报告错误余额;
  • 新增 -zapwallettxes 选项:重建钱包的交易信息,清除钱包层记录的、与链上状态不一致的陈旧交易记录(该历史选项后来在后续主版本中被移除,0.9.0 文档记录的是当时的设计)。

从功能语义上,这些修复直接支撑了后来 RPC 层 "conflicted(冲突)" 交易概念的落地——冲突交易在钱包中的确认数显示为 -1,参见下文 RPC 条目。该"识别并标记冲突"的机制在现代钱包代码中通过比较交易输入花费集实现,可结合当前仓库钱包实现进一步跟踪。

交易手续费政策改革:费率阈值与区块填充模型

0.9.0 对手续费政策的调整是理解 Bitcoin 费用市场的重要一课。

中继/挖矿最低费率降至 0.01 mBTC/KB

新版本将交易在网络上中继、以及矿工把交易纳入区块所要求的最低费率从之前的默认值降到 0.01 mBTC 每千字节(即 10 satoshi/B 量级的历史门槛)。

矿工打包规则并未与中继规则画等号

发布说明特别强调:交易被网络中继不保证会被矿工打包。默认情况下矿工先用约 50 KB 空间装"高优先级"交易,再用约 700 KB 装"每千字节费率最高"的交易。

相关配置参数与历史混淆

  • 最低中继/挖矿费率(按每千字节)可用 minrelaytxfee 选项调整;
  • 此前版本错误地使用 mintxfee 设置来决定哪些低优先级交易应被纳入区块——0.9.0 对此做了纠正;
  • 钱包代码在构造低优先级交易时默认费率仍为 0.1 mBTC/千字节;在交易量高峰期,即使这个费率也未必能保证交易快速确认,可用 mintxfee 选项覆盖默认值。

从当前仓库看参数体系延续

minrelaytxfeemintxfee 这两个参数名在现代 Bitcoin Core 中依然存在并作为核心费用策略参数,可在 src/node/mempool_args.cppsrc/policy/policy.hsrc/interfaces/chain.hsrc/init.cpp 中找到它们被解析、传递与使用的链路,相关 RPC(如 getmempoolinfo 展示 minrelaytxfee)实现见 src/rpc/mempool.cpp。0.9.0 确立的"区块填充从高费率到低费率排序、区分中继策略与挖矿策略"的基本框架,是理解后续费率估算器(estimatefee)等机制的历史起点。

0.9.0 完整变更条目详解

原发布说明后半部分按功能域给出了完整条目,下面逐类展开。

RPC 接口变更

新增"冲突交易"概念与相关能力:

  • conflicted 交易:钱包中相互冲突的交易被标记为确认数 -1
  • listreceivedbyaddress:新增返回交易 ID(txid);
  • gettransaction:输出新增原始交易 hex;
  • getreceivedby(account|address):更新帮助文本与测试;
  • getblock:接受第 2 个 verbose 参数(类似 getrawtransaction),默认仍为 1 以保持向后兼容;
  • 新增 verifychain:运行时校验链数据库;
  • 新增 dumpwallet / importwallet:导出/导入钱包文本(含私钥);
  • keypoolrefill:新增可选 size 参数;
  • 新增 getbestblockhash:返回最佳链顶端哈希;
  • getblock 输出新增 chainwork(自创世块以来全网完成的总工作量);
  • RPC 口令校验对时序攻击免疫化;
  • 澄清帮助信息并补充示例;
  • 新增 getrawchangeaddress:为原始交易获取找零地址;
  • sendrawtransaction 默认拒绝高得离谱的手续费
  • 新增 decodescript:解码十六进制脚本;
  • validateaddress 返回 redeemScript
  • 新增 getnetworkhashps:计算全网哈希率;
  • 新增 ping 命令,getpeerinfo 输出新增 pingtimepingwait 字段;
  • getpeerinfo 输出新增 addrlocal 字段;
  • getrawmempool:新增 verbose 布尔参数;
  • 新增 getunconfirmedbalance:获取未确认余额;
  • importprivkey:显式确保钱包处于解锁状态,并校验密钥有效性。

命令行选项变更

  • 新增 -nospendzeroconfchange:绝不花费未确认找零;
  • 新增 -zapwallettxes:重建钱包交易信息;
  • -tor 更名为 -onion,以更准确表达其用途(控制 Tor/Onion 可达性);
  • 新增 -disablewallet:即使二进制带钱包编译,也可让 bitcoind 完全无钱包运行;
  • 更新默认 -rpcsslciphers,纳入 TLSv1.2;
  • -logtimestamps 默认开启,并重写帮助文本;
  • RPC 客户端新增 -rpcwait:等待服务器启动后再发起请求;
  • 移除 -logtodebugger
  • 允许 bitcoind 使用 -noserver

区块链处理与存储

  • leveldb 升级到 1.15;
  • 校验正确创世块,防止误加载来自错误网络的数据目录;
  • 支持移除 txindex 并新增重索引对话框;
  • 记录被中止的区块数据库重建日志;
  • 孤儿块(orphan blocks)以序列化形式存储以节省内存;
  • 内存中孤儿块数量上限设为 750
  • 修复非标准断连交易导致的 mempool 孤儿问题;
  • 在区块 279,000 处新增检查点(checkpoint)。

钱包

  • 修复并新增回归测试:正确计算包含双花(或变异)交易的钱包余额;
  • 存储密钥创建时间,计算整个钱包的"生日"(birthday);
  • 优化重扫描:跳过早于生日前的区块;
  • 支持用 -wallet=foo.dat 指定钱包文件;
  • 生成币的成熟高度由 120 改为 101 块;
  • 缩短钱包加载时间;
  • 计算优先级时不计入 txin,鼓励"扫币"(sweeping)行为;
  • 读损坏钱包时不再创建空交易;
  • 修复 importprivkey 后重扫描须从头开始的问题;
  • 签名只使用低 S 值(low-S),为隔离见证时代的规范化签名打下基础。

挖矿

  • 默认 -blockmaxsize/prioritysize 提升到 750K / 50K
  • getblocktemplate 不再要求密钥即可生成区块模板;
  • 挖矿代码的费用策略与中继费用策略对齐。

协议与网络

  • 中继费率降至 0.01 mBTC/KB;
  • version 消息附带交易中继标志;
  • 新增 P2P reject 消息(对应 BIP 61 草案);
  • 地址每 15 分钟 dump 一次(此前为 10 秒);
  • OP_RETURN 数据输出作为标准交易类型被中继;
  • 中继时移除 CENT 输出免手续费规则;
  • 降低免手续费交易的创建体积上限;
  • mempool 超过 MAX_INV_SZ 时拆分多条 inv 消息发送;
  • MIN_PROTO_VERSION 拆分为 INIT_PROTO_VERSIONMIN_PEER_PROTO_VERSION
  • 广播时不再把 fFromMe 交易特殊对待;
  • 收到的消息逐条处理、消息间不再 sleep;
  • 改进连接失败日志;
  • 协议版本升至 70002
  • 增加若干网络可观测性日志;
  • 新增来自 bitcoinstats.com 的 DNS seed。

验证(Validation)

  • 记录非标准交易被拒的具体原因;
  • 修剪可证明不可花费的输出,并同步调整一致性检查;
  • 检测足够长的分叉并给出警告;
  • 发现长分叉或非法分叉时调用 -alertnotify 脚本;
  • 修复多区块重组(reorg)时的交易"复活"问题;
  • 拒绝非规范编码的序列化大小;
  • 验证阶段拒绝粉尘(dust)金额;
  • 接受在下一个区块即达成 final 的 nLockTime 交易。

构建系统

  • 切换到 autotools 构建系统(见前文);
  • 可传 --disable-wallet 给 configure 实现无钱包构建,从而移除 BerkeleyDB 依赖
  • 升级 gitian 依赖(libpng、libz、libupnpc、boost、openssl)到更新版本;
  • Windows 64 位构建支持;
  • Solaris 兼容性修复;
  • 校验 gitian 输入源码压缩包完整性;
  • 全平台开启 GCC 栈粉碎(Stack-smashing)保护

GUI(bitcoin-qt)

  • Windows 构建切换到 Qt 5.2.0;
  • 新增支付请求(BIP 70)支持;
  • 改进选项对话框;
  • 新发送确认对话框展示交易手续费;
  • 概览页展示总余额;
  • 首次启动、数据目录缺失或传入 -choosedatadir 时,允许用户选择数据目录;
  • 保存并恢复窗口位置;
  • 交易详情对话框的交易 id 中加入 vout 索引;
  • 调试窗口新增网络流量图;
  • 新增打开 URI 对话框;
  • 新增 Coin Control(币种控制)功能;
  • 改进收款流程:Receive 标签改为付款请求表单,历史地址列表移入 File 菜单;
  • 品牌改为 Bitcoin Core
  • 初始化/关闭移到独立线程,避免启动时"未响应",关闭时展示窗口;
  • 不再每次启动都重建自启动链接;
  • 显示并存储普通 bitcoin: URI 的消息;
  • 修复老版本 Qt 上的富文本检测挂死问题;
  • OS X:使用 10.8+ 用户通知中心展示类似 Growl 的通知;
  • OS X:Info.plist 增加 NSHighResolutionCapable,改善 Retina 字体渲染;
  • OS X:修复点击 Dock 图标导致 bitcoin-qt 启动崩溃的问题;
  • Linux:修复 Gnome 的 bitcoin: URI 处理器。

其他杂项

  • 新增 Linux 脚本 contrib/qos/tc.sh,基于 tc 限制外发带宽(该脚本在当前仓库仍保留在 contrib/qos/ 下);
  • 新增 -regtest 模式:类似 testnet 但完全私有,可通过 setgenerate RPC 实现即时出块——regtest 至今仍是本地开发与 功能测试 的默认基础设施;
  • 新增 contrib/linearize/linearize.py:用于生成 bootstrap.dat(原始发布说明称为 linearize-hashes.py 配套流程,当前仓库中的 linearize-data.py 即其延续);
  • 引入独立的 bitcoin-cli 客户端(见前文)。

总结与延伸阅读

Bitcoin Core 0.9.0 是一个承上启下的版本:它在品牌上确立 "Bitcoin Core",在工具形态上完成 bitcoind/bitcoin-cli 职责分离,在验证层奠定"可修剪输出"与低 S 值签名的基线,在费用层厘清中继费率与打包费率,并首次提供 Windows 64 位、regtest 与 Qt 支付请求等至今仍在使用的关键能力。许多机制——如 walletpassphrase 的覆盖语义、minrelaytxfee 参数链、RPC 客户端工具集——都能在当前仓库源码中直接找到延续实现,本文引用的 encrypt.cppwallet.cppmempool_args.cpp 即为继续深入阅读的起点。

若希望进一步探究,可查阅本仓库中该版本相关的配套历史文档(doc/release-notes/ 下以版本号命名的相邻发布说明)、doc/JSON-RPC-interface.mddoc/man/ 手册页。注意:0.9.0 距今久远,部分选项(如 -zapwallettxes-nospendzeroconfchange)与 autotools 构建流程在后续主版本中已演进或移除,实际使用应以你所构建的具体版本为准。

登录后查看全文
热门项目推荐
相关项目推荐