Bitcoin Core 26.1 版本更新深度解读:钱包健壮性修复、RPC 稳定化与区块突变防护
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.cpp、src/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.h 与 src/wallet/walletdb.cpp,负责在钱包数据库批量操作中按前缀擦除记录(如删除某描述符对应的密钥记录)。此类内存错误通常由迭代器在容器元素删除后继续使用触发,可能导致随机崩溃或未定义行为,属于影响稳定性的安全修复,建议钱包用户尽快升级。
地址生成失败不再破坏描述符钱包 keypool(#29510)
变更 #29510 针对描述符钱包(descriptor wallet)修正了一个状态一致性问题:此前若 getrawchangeaddress 或 getnewaddress 因故失败,可能连带影响 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.cpp 的 LoadMempool 流程中:启动时先打印 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.cpp 的 ProcessMessage 处理 NetMsgType::BLOCK 分支中,节点解析完区块后会先查询其 hashPrevBlock 是否命中已知的区块索引;仅当能定位到已知前序区块时(这也是 #29524 的要点——对无法连接已知前序的孤儿区块不轻易判定为突变,避免误伤),才调用 IsBlockMutated() 做突变检测,一旦确认突变则记录日志 Received mutated block from peer=...、调用 Misbehaving(peer, "mutated block") 下调对端信誉分并移除对应的区块下载请求。
突变检测的实现位于 src/validation.cpp 的 IsBlockMutated(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.cpp 的 Session::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.sh 等 00_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 是一个无共识变更、无新网络规则的维护版本,但对于三类运营场景存在明显的升级收益:
- 公开对外提供
getrawtransaction/ 钱包 RPC 服务的节点:可消除 RPC 崩溃路径,并避免认证 cookie 被覆盖导致的外部客户端失联; - 长时间停机后需要加载大型 mempool.dat 的节点:新增进度日志让启动过程可观测;
- 注重 P2P 健壮性与 I2P 隐私连通性的节点:区块突变防护与双加密类型的 I2P 会话带来直接收益。
升级操作本身与历史版本一致:完整停掉旧进程、替换二进制后重启即可。若数据目录需从较早版本迁移,请预留充足启动时间。本版本的完整贡献者名单(含翻译贡献者)可参见 release-notes-26.1.md 末尾的 Credits 小节。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00