ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Bitcoin Core 25.2 发布要点解析:getrawtransaction 崩溃、钱包密钥池与区块突变校验等关键修复

2026/9/7 9:04:04 拓冰建站 浏览量
Bitcoin Core 25.2 发布要点解析:getrawtransaction 崩溃、钱包密钥池与区块突变校验等关键修复 Bitcoin Core 25.2 发布要点解析getrawtransaction 崩溃、钱包密钥池与区块突变校验等关键修复【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoin导读Bitcoin Core 25.2 是一个面向 25.x 稳定分支的维护型bugfix发布版本核心目标是修复 25.1 及更早版本中暴露的一批内存安全与稳定性问题涵盖 GUI、RPC、钱包与 P2P 网络四个模块。本文将以此版本发布说明为主体逐条展开升级与兼容性要求、各项修复的技术背景与影响面并结合当前仓库源码取证其落地形态帮助你判断是否需要升级、升级时需要注意什么以及每个修复在代码层的真实位置。版本定位一次典型的补丁式发布发布说明开篇即明确 25.2 的定位本版本包含各种错误修复bug fixes、性能改进performance improvements以及更新的翻译并未引入新的共识规则或重大功能。这与 Bitcoin Core 的版本节奏一致——主版本如 25.0发布功能而 x.1/x.2 序列专注于稳定性收尾。该发布说明在仓库中的归档位置为 doc/release-notes/release-notes-25.2.md属于 release-notes 系列文档的一部分同目录下还保留了 25.0、25.1 以及 26.x、27.x 直至 31.x 的各版本说明可横向对比版本演进。需要特别说明的是当前仓库的 顶层 CMakeLists.txt 中CLIENT_VERSION_MAJOR/MINOR/BUILD显示版本为 31.99.0 且CLIENT_VERSION_IS_RELEASE为false即本仓库主干的开发进度已远超前于 25.2。因此下文涉及的修复在主干中均已合入多年只是随着重构演化为不同的代码形态——我们恰好可以借此观察「修复当时是什么样、今天变成了什么样」。如何升级到 25.2发布说明给出的升级流程非常标准适用于从任意旧版本直升关闭节点如果正在运行旧版本先将其关闭等待完全退出务必等待进程完全退出部分情况下可能需要几分钟如钱包/数据库迁移或正常 flush替换二进制文件Windows运行安装程序installermacOS覆盖拷贝/Applications/Bitcoin-QtLinux替换bitcoind/bitcoin-qt可执行文件。两点关键提示可直接跨 EOL 版本升级文档明确说明从已经达到生命周期终点EOL的版本直接升级是可行的但如果数据目录需要迁移可能耗时较长。旧钱包格式兼容旧版本的比特币钱包legacy wallet 数据格式在一般情况下仍然受支持即不会因升级而强制丢失钱包数据。值得提醒的是发布说明本身的升级对象是「运行 25.2 之前任意版本」的用户如果你当前运行的是 25.x 系列25.2 是建议的收尾版本而本仓库主干31.99 开发版对应的最终发布则应在相应正式版本发布后再参考其发布说明进行升级。支持平台与兼容性声明25.2 发布说明中保留了与主版本一致的平台支持声明Linux 内核系列系统完全支持并经过大量测试macOS 10.15完全支持Windows 7 及更新版本完全支持其他类 Unix 系统理论上可用但测试频率较低明确建议不要在不受支持的平台上运行Bitcoin Core。这一声明是 Bitcoin Core 一贯的「支持范围保守化」策略把有限的 CI 资源集中在主流平台同时不禁止用户在更多系统上自行编译使用。Notable changes四条模块的六项修复逐条解析25.2 的修复集中在 GUI、RPC、Wallet、P2P/网络四个模块。下面逐条给出技术解读与源码取证。GUI修复交易视图勾选 Mask values 时崩溃修复条目gui#774 Fix crash on selecting Mask values in transaction view这是来自 Bitcoin Core GUI 独立仓库bitcoin-core/gui的修复合入到 25.2 的 Qt 钱包界面中。崩溃场景是用户在交易视图中启用/选中「Mask values」隐藏交易金额显示选项时触发。从修复类型看属于典型的 UI 状态切换时的空指针/无效引用问题金额遮蔽状态切换会触发交易记录列表的局部重绘或取数逻辑若某条交易记录的展示字段尚未完整填充就可能在刷新路径上发生崩溃。该修复并未改变任何链上逻辑或数据结构纯属界面健壮性改进因此本小节在源码层面只需说明Qt 界面相关的交易展示逻辑位于 src/qt/ 目录373 个文件含.ui、.cpp、.ts翻译文件金额遮蔽等展示功能不涉及 src/wallet/ 的钱包核心状态属于纯展示层缺陷。RPC修复getrawtransaction段错误修复条目#29003 rpc: fix getrawtransaction segfaultgetrawtransaction是 Bitcoin Core 最常用的底层 RPC 之一其调用链在主干中位于 src/rpc/rawtransaction.cpp。该修复解决的是特定查询路径下触发空指针解引用segfault的问题——即节点进程直接崩溃而不是返回错误码。虽然发布说明未展开崩溃的精确复现条件但从当前主干中该 RPC 的实现形态可以清晰看到为杜绝此类崩溃而设计的防御结构这正是该修复的「最终形态」调用GetTransaction(...)拿到交易指针后先判断是否为空空则构造并抛出明确的 JSON-RPC 错误rawtransaction.cpp而不是继续解引用错误消息按场景区分指定了 blockhash 但区块无数据 →RPC_MISC_ERROR Block not available区块内有该区块但找不到交易 →No such transaction found in the provided block未开-txindex且不在 mempool → 提示Use -txindex or provide a block hash to enable blockchain transaction queries-txindex正在同步 → 提示Blockchain transactions are still in the process of being indexed在 verbosity ≥ 1 的明细返回路径上若未显式提供 blockhash则依据返回的hash_block反查区块索引并显式允许该索引为空对应 mempool 交易注释原文为 “May be nullptr for mempool transactions”rawtransaction.cpp后续代码必须对空区块索引做分支处理——这正是当年段错误风险点的典型位置。此外还有一处特殊防护当请求的 txid 等于创世区块 coinbase 交易的 hashMerkleRoot 时直接抛出The genesis block coinbase is not considered an ordinary transaction and cannot be retrievedrawtransaction.cpp避免对不存在于任何区块交易集合的特殊交易做无效索引。该 RPC 的典型用法取自当前源码中的RPCExamplesrawtransaction.cppbitcoin-cli getrawtransaction mytxid bitcoin-cli getrawtransaction mytxid 1 bitcoin-cli getrawtransaction mytxid 0 myblockhash bitcoin-cli getrawtransaction mytxid 2 myblockhash默认verbosity0只返回十六进制原始交易verbosity1 返回带解码字段的 JSONverbosity2 额外返回 prevout 等上下文第三个参数 blockhash 用于绕过-txindex、直接从指定区块取交易。Wallet #29176修复WalletBatch::EraseRecords中的 use-after-free修复条目#29176 wallet: Fix use-after-free in WalletBatch::EraseRecords这是一个**内存安全use-after-free悬垂引用**修复属于最高优先级的正确性问题。WalletBatch是钱包数据库Berkeley DB 风格的批次访问层的封装EraseRecords用于按记录类型整体删除某一类钱包记录。从当前主干实现看该函数已经演化为「按 key 类型前缀整体批量擦除」的形态bool WalletBatch::EraseRecords(const std::unordered_setstd::string types) { return std::all_of(types.begin(), types.end(), { return m_batch-ErasePrefix(DataStream() type); }); }walletdb.cppuse-after-free 的根源在于早期实现中该函数基于数据库游标逐条迭代删除记录在删除进行的同时若迭代器所依赖的内部缓冲区被释放/重建就会读取到已释放内存造成崩溃或潜在的不确定行为。修复方向是放弃「迭代中逐条删除」的脆弱模式改为先构造完整的前缀 key再对整段前缀一次性擦除从根上消除了游标失效问题。这正是为什么今天我们看到的是ErasePrefix一次调用完成全部删除的形态。在主干中该方法的调用点也值得一读旧式legacy钱包删除自身全部记录时通过 scriptpubkeyman.cpp 的LegacyDataSPKM::DeleteRecordsWithDB传入DBKeys::LEGACY_TYPES调用batch.EraseRecords(...)。也就是说这段代码的每次执行都发生在「销毁/重建 legacy 钱包脚本公钥管理器」的关键路径上一旦出错会直接影响钱包迁移与重置流程。Wallet #29510getrawchangeaddress/getnewaddress失败不应损耗 descriptor 钱包密钥池修复条目#29510 wallet: getrawchangeaddress and getnewaddress failures should not affect keypools for descriptor wallets这条修复直击一个「看似错误、实为资产安全」的场景在descriptor 钱包默认新建钱包类型中调用getnewaddress新收款地址或getrawchangeaddress新找零地址时如果操作中途失败此前被预取出的密钥不应从密钥池keypool中永久扣除。先看当前主干中两个 RPC 背后 CWallet 层的调用形态wallet.cppGetNewDestination(type, label)获取脚本公钥管理器GetScriptPubKeyMan后调用spk_man-GetNewDestination(type)失败路径直接返回util::Error并且只有成功时才写入地址簿SetAddressBookGetNewChangeDestination(type)基于ReserveDestination完成「预取 → 确认」两段式流程只有GetReservedDestination成功后才调用KeepDestination()。ReserveDestination的设计是整个修复的语义核心wallet.h构造函数本身不占用任何地址必须显式调用GetReservedDestination()才算「预取」预取成功后调用KeepDestination()表示「地址已被真实使用允许从密钥池移除」若预取成功却没有调用KeepDestination()则对象析构时自动调用ReturnDestination()把密钥放回密钥池头文件注释明确写道“If an address is reserved and KeepDestination() is not called, then the address will be returned when the ReserveDestination goes out of scope.”在修复前descriptor 钱包的失败路径上存在密钥被标记为已用而未归还的缺陷用户反复发起失败的地址生成请求时密钥池会被静默消耗。修复后的语义是失败即归还、成功才扣除无论中途在哪个环节出错密钥池数量都不应减少。这也解释了为何getnewaddress/getrawchangeaddress这类「看起来只读」的调用在实现上要经过如此严格的资源管理抽象。P2P不再处理「被突变mutated」的区块修复条目#29412 p2p: Dont process mutated blocks#29524 p2p: Dont consider blocks mutated if they dont connect to known prev block这是 25.2 中网络层最重要的一组共识安全修复。所谓「突变区块mutated block」指区块头/交易数据的哈希与网络中继的承诺不一致典型如 witness 承诺与默克尔根不匹配的恶意或异常区块。在 Bitcoin Core 的BlockTransactions紧凑区块/BIP152 区块中继处理路径上节点原先可能对这类区块继续做交易请求与处理尝试造成不必要的网络带宽消耗与潜在的状态混乱。从当前主干看这一防御逻辑位于区块处理函数对完整区块的入口校验处net_processing.cppconst CBlockIndex* prev_block{WITH_LOCK(m_chainman.GetMutex(), return m_chainman.m_blockman.LookupBlockIndex(pblock-hashPrevBlock))}; // Check for possible mutation if it connects to something we know so we can check for DEPLOYMENT_SEGWIT being active if (prev_block IsBlockMutated(/*block*/*pblock, /*check_witness_root*/DeploymentActiveAfter(prev_block, m_chainman, Consensus::DEPLOYMENT_SEGWIT))) { LogDebug(BCLog::NET, Received mutated block from peer%d\n, peer.m_id); Misbehaving(peer, mutated block); WITH_LOCK(cs_main, RemoveBlockRequest(pblock-GetHash(), peer.m_id)); return; }这段代码逐行印证了 25.2 的两条修复且与主干的后续演进一脉相承#29412 的核心发现区块「被突变」后不再继续处理而是记录日志Received mutated block from peer%d、给对等节点施加惩罚Misbehaving(peer, mutated block)、移除对该区块的请求RemoveBlockRequest随后直接返回。这与修复标题 Dont process mutated blocks 完全对应。#29524 的细化突变校验被限定在「该区块能连接到已知前序区块」的前提下进行——即代码中的if (prev_block ...)守卫以及注释所强调的 “if it connects to something we know”。原因在于IsBlockMutated的 witness 根检查需要依据前序区块是否已激活 SegWitDeploymentActiveAfter(prev_block, ...)来决定检查强度。如果一个区块的前序未知我们就无法判断 SegWit 是否激活也就不应该草率判定其为「突变」并惩罚对端否则可能误伤正常节点。这正对应 #29524 的标题 Dont consider blocks mutated if they dont connect to known prev block。这两条修复合在一起构成一套完整的「突变区块拒绝」策略先确认可评估上下文再判定突变最后惩罚并丢弃。致谢与贡献者发布说明末尾列出了 25.2 的直接代码贡献者按惯例也向通过 Transifex 平台参与翻译的所有社区成员致谢。直接贡献者名单如下Martin ZumsandeSebastian FalbesonerMarcoFalkeUdjinM6dergoeggeGreg Sanders从名单可以看到 25.2 是一个「小而精」的维护版本六名直接贡献者 翻译社区工作量集中在上述几条高价值修复上没有大规模新功能符合 x.2 维护版的定位。从当前仓库追溯这些修复的实践建议由于本仓库主干31.99.0 开发版已远超 25.2若你想精确研究「25.2 发布当时」的代码差异建议结合 git 历史操作而非仅看主干文件该发布说明本身归档在 doc/release-notes/release-notes-25.2.md可作为阅读入口在仓库中执行git log --oneline --grep29412\|29510\|29003\|29176可定位对应 PR 的合并提交每条修复条目开头的#NNNNN即 Bitcoin Core 主仓库的 PR 编号可在本地git show commit中查看当时的完整 diff 与测试主干上这些代码的「今日形态」则以上文给出的文件链接为准例如 net_processing.cpp、walletdb.cpp、wallet.h、rawtransaction.cpp。小结是否应当升级到 25.2综合发布说明内容可以给出如下判断所有 25.x 用户都应升级到 25.2两条钱包内存安全修复#29176 use-after-free、#29510 密钥池损耗与一条 RPC 段错误修复#29003都属于「长期运行节点应尽快吸收」的稳定性修复P2P 的两条区块突变校验改进则直接关乎带宽与对等节点惩罚的公平性升级成本极低无共识变更、无新 RPC、无数据结构迁移声明标准的「停节点 → 等退出 → 换二进制 → 启动」流程即可GUI 用户受益于 Mask values 崩溃修复特别是经常在交易视图中切换金额显示的用户若你运行在 25.2 之后的更高版本如 26.x31.x这些修复早已包含在内无需额外操作。本文所有关于代码形态的描述均可在仓库对应路径中复核关于修复动机的描述以 doc/release-notes/release-notes-25.2.md 的条目为准未引入任何外部来源的推测性结论。【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考