Bitcoin Core 内存池尺寸语义重构:vsize、vsize_adjusted 与 vsize_bip141 完整指南

Bitcoin Core 内存池尺寸语义重构:vsize、vsize_adjusted 与 vsize_bip141 完整指南 Bitcoin Core 内存池尺寸语义重构vsize、vsize_adjusted 与 vsize_bip141 完整指南【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoin本文基于 Bitcoin Core 的发布说明 release-notes-32800.md讲解 mempool 相关 RPC 输出中尺寸字段的一次重要语义修正getrawmempool、getmempoolentry、testmempoolaccept、submitpackage四个 RPC 新增vsize_adjusted与vsize_bip141字段原先的vsize被标记为废弃DEPRECATEDgetrawtransaction则新增vsize_adjusted字段。读完后你将能够正确区分“sigop 调整后的策略尺寸”与“BIP 141 原始虚拟尺寸”写出不再依赖废弃字段、可平滑升级的尺寸计算逻辑。一、为什么要修正 vsize一次历史描述错误的代价在引入本次改动之前vsize在 RPC 帮助文本中被描述为 “BIP 141 virtual size”但它的实际取值是sigop 调整后的虚拟尺寸sigops-adjusted vsize——两者只有在交易 sigop 成本很低时恰好相等。对于包含大量 P2SH/P2WSH 脚本 sigop 的交易sigop 调整会放大计算尺寸导致按vsize计算费率feerate的脚本得到偏高的分母费率被低估依赖“BIP 141 vsize”语义做策略判断如手续费估算、RBF 比较的工具与实际行为不符。release-notes-32800.md 明确指出了这一点Whilevsizeis marked as DEPRECATED, it was previously erroneously described as the BIP 141 vsize, but is actually sigops-adjusted vsize. Usevsize_bip141to actually get that behavior or switch to the explicitvsize_adjustedfor retained behavior.因此本次改动的核心是“把语义显式化”保留旧字段以维持向后兼容同时新增两个名字自解释的字段让调用方按真实语义选择。二、两个字段的精确定义与计算公式要理解新字段的差别需要回到 BIP 141 重量与 sigop 调整的定义。核心实现在 policy.cppint64_t GetSigOpsAdjustedWeight(int64_t weight, int64_t sigop_cost, unsigned int bytes_per_sigop) { return std::max(weight, sigop_cost * bytes_per_sigop); } int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop) { return (GetSigOpsAdjustedWeight(nWeight, nSigOpCost, bytes_per_sigop) WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR; }由这两个函数可以推出两个字段的确切语义字段含义计算方式从源码结构看vsize_bip141原始 BIP 141 虚拟尺寸witness 数据按 1/4 折扣不含 sigop 调整ceil(weight / 4)即GetVirtualTransactionSize(tx)在 sigop_cost 取 0 时的值vsize_adjusted策略实际使用的 sigop 调整后尺寸mempool 策略与 RPC 尺寸统计以此为分母ceil(max(weight, sigop_cost × nBytesPerSigOp) / 4)其中nBytesPerSigOp由-bytespersigop启动参数控制默认值为 1可以推断对普通低 sigop 交易vsize_adjusted vsize_bip141当交易 P2SH 嵌套 sigop 成本较高sigop_cost × bytespersigop 超过 weight时vsize_adjusted vsize_bip141。这正是要在费率计算中注意的差异来源。三、受影响的 RPC 逐一解析1. getrawmempoolverbose与 getmempoolentry两者共用 mempool 条目的 JSON 序列化逻辑entryToJSON字段写入位于 mempool.cppinfo.pushKV(vsize_adjusted, e.GetTxSize()); info.pushKV(vsize, e.GetTxSize()); info.pushKV(vsize_bip141, GetVirtualTransactionSize(e.GetTx())); info.pushKV(weight, e.GetTxWeight());注意实现上的一个关键细节vsize_adjusted与废弃的vsize都取自同一个e.GetTxSize()而vsize_bip141是对原始交易重新调用不带 sigop 成本的GetVirtualTransactionSize。这与“vsize实际上就是 sigop 调整尺寸”的结论在代码层面完全一致。两个新字段的官方帮助文本mempool.cpp 中的MempoolEntryDescription为vsize_adjustedMaximum of sigop-adjusted size (-bytespersigop) and virtual transaction size as defined in BIP 141.vsize_bip141Virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted.vsize(DEPRECATED) Was previously erroneously described as the BIP 141 vsize, but is actually sigops-adjusted vsize.2. testmempoolaccepttestmempoolaccept用于模拟 mempool 接受测试其结果对象在allowed: true时新增尺寸字段写入逻辑见 mempool.cppconst int64_t virtual_size tx_result.m_vsize.value(); ... result_inner.pushKV(vsize_adjusted, virtual_size); result_inner.pushKV(vsize, virtual_size); result_inner.pushKV(vsize_bip141, GetVirtualTransactionSize(*tx));即vsize_adjusted来自接受结果MempoolAcceptResult中记录的m_vsize与 mempool 实际策略使用的尺寸同源vsize_bip141同样按原始 BIP 141 规则重算。结果字段的完整帮助定义见 mempool.cpp。该 RPC 还带有maxfeerate参数用vsize_adjusted作分母校验费用上限max_raw_tx_fee maxfeerate.GetFee(virtual_size)这也是“策略尺寸才是正确费率分母”的一个直接例证。3. submitpackage批量提交交易包RBF 包替换等场景的submitpackage同样在每笔交易的返回中增加vsize_adjusted与vsize_bip141并在结果描述中将vsize标记为 DEPRECATED给出与发布说明一致的迁移指引mempool.cpp。写入逻辑位于 mempool.cppresult_inner.pushKV(vsize_adjusted, it-second.m_vsize.value()); ... result_inner.pushKV(vsize_bip141, GetVirtualTransactionSize(*tx));4. getrawtransactionrelease-notes-32800.md 的第二条指出getrawtransaction新增vsize_adjusted仅当交易当前位于 mempool 时返回该字段。实现位于 rawtransaction.cpp// Add sigop-adjusted virtual size if the transaction exists in the mempool. if (blockindex nullptr hash_block.IsNull() node.mempool) { auto info node.mempool-info(tx-GetHash()); if (info.tx) { result.pushKV(vsize_adjusted, info.vsize); } }这里的判断链值得注意只有当请求未指定blockhash且查不到链上区块索引blockindex nullptr同时 mempool 中能查到该 txid 时才会附加该字段。也就是说链上交易的getrawtransaction结果不含vsize_adjusted对已确认交易而言策略尺寸本身没有持续存在的意义。字段帮助文本为 “Sigop-adjusted virtual size in bytes, present for mempool transactions.”rawtransaction.cpp。四、底层数据来源mempool 条目如何缓存尺寸上述 RPC 的值并非每次现场计算而是来自 mempool 条目对象的缓存。mempool_entry.h 中int32_t GetTxSize() const { return GetVirtualTransactionSize(nTxWeight, sigOpCost, ::nBytesPerSigOp); } int32_t GetAdjustedWeight() const { return GetSigOpsAdjustedWeight(nTxWeight, sigOpCost, ::nBytesPerSigOp); } int32_t GetTxWeight() const { return nTxWeight; } int64_t GetSigOpCost() const { return sigOpCost; }从源码结构看CTxMemPoolEntry在入池时就缓存了交易重量nTxWeight与脚本 sigop 成本sigOpCostGetTxSize()每次按需套用全局::nBytesPerSigOp对应-bytespersigop参数完成 sigop 调整。这解释了为什么修改-bytespersigop会改变vsize_adjusted的取值GetTxSize()直接引用该全局值而vsize_bip141不受影响为什么vsize_adjusted就是 mempool 驱逐、祖先/后代尺寸统计ancestorsize/descendantsize所使用的那个尺寸用它做分母才能与节点策略口径一致。五、迁移指南从 vsize 切换到新字段你的旧代码语义旧字段建议替换为“我按帮助文档以为它是 BIP 141 vsize”想要原始虚拟尺寸vsizevsize_bip141我依赖的其实就是策略/费率的 sigop 调整尺寸旧字段真实行为vsizevsize_adjustedgetrawtransaction中做 mempool 交易的策略尺寸展示原本没有新增的vsize_adjusted注意可能缺失实操建议读取时优先vsize_adjusted/vsize_bip141把vsize作为兜底兼容旧节点对getrawtransaction的结果做存在性检查后再使用vsize_adjusted因为链上交易没有该字段若按 BIP 141 vsize 计算手续费预算务必切换到vsize_bip141否则会因 sigop 放大导致估算偏差。六、测试覆盖与验证路径仓库的功能性测试对新字段做了断言覆盖可用于回归验证或本地复现mempool_sigoplimit.py围绕 sigop 限制策略验证尺寸与 sigop 的关系是观察vsize_adjusted与vsize_bip141差异的典型用例mempool_accept.pymempool 接受/拒绝路径p2p_segwit.pysegwit 交易尺寸相关断言rpc_packages.pysubmitpackage相关 RPC 的行为测试。在本地运行功能测试例如mempool_sigoplimit.py时可直接在节点启动参数中加入-bytespersigopn观察vsize_adjusted随之变化、vsize_bip141保持不变的对照现象从而直观确认两者的语义边界。七、小结本次改动见 release-notes-32800.md本质上是一次 RPC 契约的语义澄清getrawmempool、getmempoolentry、testmempoolaccept、submitpackage输出vsize_adjusted sigop 调整后尺寸策略口径与vsize_bip141 原始 BIP 141 虚拟尺寸旧vsize字段保留但标记 DEPRECATED且帮助文本改为如实描述其为 sigop 调整尺寸getrawtransaction对 mempool 内交易追加vsize_adjusted数据来源为 mempool 条目缓存的GetTxSize()计算根在 policy.cpp 的GetSigOpsAdjustedWeight/GetVirtualTransactionSizemempool 条目侧缓存于 mempool_entry.h。对钱包费率估算、RBF 工具、链上分析脚本等所有消费 mempool 尺寸的下游程序而言按本文的迁移表切换到显命名字段即可在不改变实际行为的前提下消除对废弃字段的依赖。【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考