首页
/ Bitcoin Core 26.1 版本更新深度解读:钱包健壮性修复、RPC 稳定化与区块突变防护

Bitcoin Core 26.1 版本更新深度解读:钱包健壮性修复、RPC 稳定化与区块突变防护

2026-09-06 19:00:42作者:吴年前Myrtle

Bitcoin Core 26.1 是 26.x 主线上的一个维护性(maintenance)版本,聚焦于钱包模块的若干缺陷修复、RPC 接口的崩溃修复与行为改进,并对 P2P 网络层接收区块的逻辑、I2P 会话创建方式以及构建/CI 基础设施做了多项调整。本文以官方发布说明为主体,结合本仓库源码(release-notes-26.1.md)逐条梳理这些变更的技术动机、代码落点与运维影响,帮助运行 26.x 系列的节点运营者与钱包开发者评估升级必要性并理解行为变化。

升级方式与兼容性基线

26.1 依然遵循 Bitcoin Core 一贯的升级流程:如果你运行的是旧版本,先完整关闭节点(某些情况下完全关闭可能需要数分钟),然后通过安装器覆盖(Windows),或直接替换 /Applications/Bitcoin-Qt(macOS)、bitcoind / bitcoin-qt(Linux)可执行文件即可。发布说明特别指出,从已到达生命周期终点(EOL)的版本直接升级是可行的,但若数据目录需要迁移,启动耗时可能增加;旧版钱包格式一般仍然被支持。

兼容性方面,Bitcoin Core 26.1 在 Linux kernel 系统、macOS 11.0+ 以及 Windows 7 及以上版本经过充分测试,大多数类 Unix 系统上也可工作但测试频率较低,官方不建议在不受支持的平台上运行。该版本整体没有引入新的网络共识规则,属于低风险升级,但仍建议运营者在升级前备份钱包文件与数据目录。

钱包模块:四类缺陷修复

本版本钱包部分的改动集中在地址池(keypool)生命周期、交易扫描时的出生时间(birth time)更新以及钱包数据库记录删除路径上。

SFFO 开启时跳过 BnB 选币(#28994)

变更 #28994 的核心是:当启用了 "为避免找零而被设为找零所有输入"(SFFO,即 avoid partial spends / "Single Random Draw" 场景下的"避免部分花费")相关的花费偏好时,跳过 BnB(Branch and Bound)选币算法。从 src/wallet/coinselection.cpp 及相关测试(src/wallet/test/coinselector_tests.cppsrc/wallet/test/fuzz/coinselection.cpp)可见,BnB 与 SFFO 的目标存在冲突:SFFO 倾向于让找零输出尽可能小甚至为零,而 BnB 追求恰好匹配目标金额、天然不产生找零,两者叠加会使策略预期(例如对找零次数统计、避免部分花费的效果)与算法前提不一致。该修复让这两类策略的组合选择更符合设计意图,避免在 SFFO 开启时误用 BnB 造成不符合预期的花费结果。

交易扫描期间更新钱包出生时间(#28920)

变更 #28920 让钱包在进行交易扫描(rescan)期间能够更新其"出生时间"(birth time)。出生时间用于决定从哪个区块高度开始扫描链上交易,是钱包能够正确发现历史交易的关键元数据。

仓库源码中,钱包的出生时间以原子变量 m_birth_time 保存于 src/wallet/wallet.h(初始值为极大值),并在 src/wallet/wallet.cpp 通过 MaybeUpdateBirthTime() 在收到交易、连接区块等路径上被反复触发(例如钱包发现新交易时调用 MaybeUpdateBirthTime(wtx.GetTxTime()))。若出生时间固定为钱包创建时刻,当后续通过 import/恢复导入更早的密钥或描述符时,扫描范围可能过早结束;该修复保证扫描过程中持续跟踪最早密钥/交易的时间点,相关回调信号 NotifyFirstKeyTimeChanged 亦声明于 src/wallet/scriptpubkeyman.h

修复 WalletBatch::EraseRecords 的释放后使用(#29176)

变更 #29176 修复了 WalletBatch::EraseRecords 中的一处 use-after-free(悬垂引用/释放后使用)问题。该函数位于 src/wallet/walletdb.hsrc/wallet/walletdb.cpp,负责在钱包数据库批量操作中按前缀擦除记录(如删除某描述符对应的密钥记录)。此类内存错误通常由迭代器在容器元素删除后继续使用触发,可能导致随机崩溃或未定义行为,属于影响稳定性的安全修复,建议钱包用户尽快升级。

地址生成失败不再破坏描述符钱包 keypool(#29510)

变更 #29510 针对描述符钱包(descriptor wallet)修正了一个状态一致性问题:此前若 getrawchangeaddressgetnewaddress 因故失败,可能连带影响 keypool(密钥池)中未消耗的密钥条目;修复后,单次地址生成失败不会再污染 keypool。

描述符钱包的地址供给机制围绕 keypool 展开,相关结构在 src/wallet/scriptpubkeyman.h 中有完整呈现:每个 ScriptPubKeyMan 维护 m_keypool_size(默认值来自 DEFAULT_KEYPOOL_SIZE),通过 GetNewDestination()ReserveDestination() 等接口向外部提供新地址,并以 TopUp() / TopUpWithDB(WalletBatch&, ...) 批量补充池中密钥。修复点即在于保证这些接口失败时的回滚路径不再向 keypool 写入半成品状态,确保后续调用仍能正常获得合法新地址。

RPC:崩溃修复与认证 cookie 行为优化

  • 修复 getrawtransaction 段错误(#29003):该 RPC 在特定输入场景下(如索引缺失、区块数据尚未同步等)存在触发进程段错误(segfault)的路径,属于稳定性缺陷。运行依赖 -txindex 或区块索引提供 getrawtransaction 服务的节点应特别关注此修复。
  • 保留非自身生成的 .cookie 文件(#28784):Bitcoin Core 默认采用随机生成的 cookie 文件做本地 RPC 认证。此前节点启动时若发现 .cookie 已存在,无论是否为自身生成都可能直接覆盖;修复后,仅当 cookie 确由本节点生成时才负责重建/删除。相关生成与权限逻辑可参考 src/httprpc.cpp 中的 GenerateAuthCookie-rpccookieperms 参数处理(支持 owner/group/all 三档权限字符串)。若外部工具(如钱包前端)预置了 cookie 文件,此修复可避免节点重启将其破坏。

日志:mempool 加载进度可视化(#29227)

变更 #29227 为 mempool 启动加载过程补充了进度日志。落地代码位于 src/node/mempool_persist.cppLoadMempool 流程中:启动时先打印 Loading %u mempool transactions from file...,随后周期性输出形如 Progress loading mempool transactions from file: %d%% (tried %u, %u remaining) 的百分比进度,加载完成后汇总 Imported mempool transactions from file: %i succeeded, %i failed, ...。对于 mempool.dat 规模较大、加载耗时较长的节点(尤其是经历了长时间停机、积压大量交易内存池文件的场景),运维者现在可以实时判断节点"卡在启动"是仍在正常导入交易,而非死锁。

P2P 与网络:更健壮的区块接收与 I2P 加密增强

拒绝并惩罚"被突变"区块(#29412、#29524)

这两个变更共同强化了节点在收到 block 消息时的防御逻辑。所谓"被突变"(mutated)区块,指区块内交易内容与其默克尔根(merkle root)不一致、从而可能被用于对等节点间哈希混淆攻击的畸形区块。

src/net_processing.cppProcessMessage 处理 NetMsgType::BLOCK 分支中,节点解析完区块后会先查询其 hashPrevBlock 是否命中已知的区块索引;仅当能定位到已知前序区块时(这也是 #29524 的要点——对无法连接已知前序的孤儿区块不轻易判定为突变,避免误伤),才调用 IsBlockMutated() 做突变检测,一旦确认突变则记录日志 Received mutated block from peer=...、调用 Misbehaving(peer, "mutated block") 下调对端信誉分并移除对应的区块下载请求。

突变检测的实现位于 src/validation.cppIsBlockMutated(const CBlock& block, bool check_witness_root),检测依次包含:CheckMerkleRoot(核验默克尔根是否与交易列表匹配)、非 coinbase 场景下是否包含恰好 64 字节的畸形交易(对应 Bitcoin Merkle Root Construction 的已知弱点,此类块本就不含 coinbase、本身即非法)、以及按需进行 witness 根校验(check_witness_root 由 segwit 是否已激活决定,调用点在 DeploymentActiveAfter(prev_block, ..., DEPLOYMENT_SEGWIT))。默克尔根计算辅助函数 BlockMerkleRoot 位于 src/consensus/merkle.cpp。由此,恶意或损坏节点发送的畸形块会在进入完整验证管线前即被拦截,且不触发区块索引层面的误报。

I2P 会话同时支持 ECIES-X25519 与 ElGamal 加密(#29200)

变更 #29200 让节点创建 I2P 出站会话时同时声明 ECIES-X25519 与 ElGamal 两种传输加密类型。I2P 传输加密类型由 SAM API 的 i2cp.leaseSetEncType 字段指定(4 代表 ECIES-X25519,0 代表 ElGamal)。在 src/i2p.cppSession::CreateIfNotCreatedAlready() 中可以看到两种会话创建路径都已带上了该字段:

  • 瞬时会话(m_transient,每次创建动态生成目的地)发送:SESSION CREATE STYLE=STREAM ID=... DESTINATION=TRANSIENT SIGNATURE_TYPE=7 i2cp.leaseSetEncType=4,0 inbound.quantity=1 outbound.quantity=1
  • 持久会话(从磁盘读取或新生成私钥后复用)发送:... i2cp.leaseSetEncType=4,0 inbound.quantity=3 outbound.quantity=3

即优先请求 ECIES-X25519,同时保留 ElGamal 作为对不支持前者的旧路由/I2P 网络环境的回退,以兼顾加密强度与连通性。会话创建的完整生命周期——握手(Hello)、监听(Listen/StreamAccept)、出站连接(Connect)、会话销毁(Disconnect)——均可在该文件中追踪。对使用 -i2p-i2psam 选项接入 I2P 网络的节点,此变更通常在 SAM 代理层透明生效。

构建与 CI:工程链的持续打磨

构建侧的两项变更为:

  • #29127:macOS 发布构建启用 hardened runtime(强硬化运行时)。这是 Apple 平台代码签名/公证的重要安全属性,启用后可配合系统强制实施代码签名校验、受限的库注入与内存权限策略,降低恶意代码注入面,常见于 macOS release 产物签名流程(本仓库 contrib/macdeploy 目录承载相关部署工具链)。
  • #29195:修复编译参数传递问题,涉及向 Clang 传递 -Xclang -internal-isystem 选项时的参数解析,属于面向 Clang 工具链的构建脚本修正。

CI 基础设施方面,#28992 将 asan/tsan/tidy/fuzz 等作业迁移到 Ubuntu 24.04 Noble(镜像与脚本可对照 ci/test/00_setup_env_native_asan.sh00_setup_env_*.sh 系列环境脚本);#29080 通过设置 HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK 规避 macOS Homebrew 依赖连锁升级导致的无关 CI 失败;#29610 修复了 macOS native CI 任务。

其他值得关注的杂项变更

  • #28391(重构):精简 CTxMempool/BlockAssembler 的字段,移除部分对 mapTx 的外部直接访问。这属于面向未来集群内存池(cluster mempool)等工作铺路的结构性整理,不改变运行行为。
  • #29179(测试):新增钱包重扫场景测试——父交易被重组(reorg)而子交易仍为 IsFromMe(本钱包发出)且驻留 mempool 时的行为验证。
  • #28791:修复加载 loadtxoutset(UTXO 快照)后运行 -checkblockindex 时可能发生 core dump 的问题,影响 assumeutxo 相关功能的稳定性测试。
  • #29357:MinGW(Windows 交叉编译)构建中为 fsbridge::fopen 调用移除 x(排他创建)修饰符,修正文件打开模式的跨平台差异。
  • #29529(fuzz):将 fopencookie 的使用限制在 Linux 与 FreeBSD 平台,保证模糊测试代码在其他系统的可移植编译。

升级建议小结

综合来看,Bitcoin Core 26.1 是一个无共识变更、无新网络规则的维护版本,但对于三类运营场景存在明显的升级收益:

  1. 公开对外提供 getrawtransaction / 钱包 RPC 服务的节点:可消除 RPC 崩溃路径,并避免认证 cookie 被覆盖导致的外部客户端失联;
  2. 长时间停机后需要加载大型 mempool.dat 的节点:新增进度日志让启动过程可观测;
  3. 注重 P2P 健壮性与 I2P 隐私连通性的节点:区块突变防护与双加密类型的 I2P 会话带来直接收益。

升级操作本身与历史版本一致:完整停掉旧进程、替换二进制后重启即可。若数据目录需从较早版本迁移,请预留充足启动时间。本版本的完整贡献者名单(含翻译贡献者)可参见 release-notes-26.1.md 末尾的 Credits 小节。

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