Bitcoin Core 交易中继策略(Policy)详解:非共识校验规则、标准性检查与可配置的中继参数 Bitcoin Core 交易中继策略Policy详解非共识校验规则、标准性检查与可配置的中继参数【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoinBitcoin Core 节点在将交易提交进内存池mempool之前除了共识consensus校验之外还会执行一套本地可配置的校验规则——即Policy交易中继策略 / Mempool or Transaction Relay Policy。本文基于 doc/policy/README.md 的定义结合src/policy/源码、命令行参数定义和策略子文档系统讲解这套规则的范围、标准交易的判定细节、费用与尺寸术语、mempool 聚类设计、Replace-by-FeeRBF机制以及 Package 中继策略帮助读者完整掌握节点愿意转发什么交易的底层逻辑及其可配置参数。Policy 与共识校验的本质区别按照 doc/policy/README.md 的定义Policy交易中继策略是节点在交易进入内存池之前、针对未确认交易执行的一组校验规则它是共识规则之外的本地规则且可配置——运行bitcoind -help时可以在 Node relay options 分组下找到这些选项Policy 的限制可能作用于三个层面交易本身、交易与当前链头chain tip的关系、交易与节点 mempool 已有内容的关系关键边界Policy 不应用于区块中的交易。区块校验只依赖共识规则因此不同节点即使采用不同的中继策略也能对区块的有效性达成一致——这是去中心化网络保持兼容的基础。从源码结构看这套策略规则集中在 src/policy/ 目录中实现核心文件包括文件职责src/policy/policy.h标准交易各项阈值常量尺寸、sigops、dust、脚本栈限制等与IsStandardTx等标准性判定接口src/policy/packages.h / src/policy/packages.cppPackage一子多父中继策略的校验逻辑src/policy/feerate.h / src/policy/feerate.cpp费率fee rate的表示与计算src/policy/rbf.h / src/policy/rbf.cppReplace-by-Fee 判定src/policy/settings.h / src/policy/settings.cpp策略可调设置如-bytespersigop对应的全局变量nBytesPerSigOp该文档同时明确声明它不是所有 policy 规则的穷举清单并链接了三篇更深入的子文档下文对应展开Mempool Design and LimitsMempool ReplacementsPackages此外doc/policy/mempool-terminology.md 定义了 mempool 策略中费用与尺寸的标准术语是理解后续各阈值的前提。费用与尺寸术语weight、vsize 与 modified fee理解任何中继阈值之前先要理解 doc/policy/mempool-terminology.md 中的术语定义weight 与 virtual sizevsize按 BIP 141 定义。见证witness数据打 4 折折算最终值向上取整到最近的整数sigops size交易的 sigop cost 乘以节点的-bytespersigop默认可调整的策略参数虚拟尺寸 vsize实际指的是sigops-adjusted virtual size取BIP 141 尺寸与sigops size的较大值。这样简化了同时满足区块最大重量限制与 sigop 限制的区块构建过程RPC 中 vsize 均指此值sigops-adjusted weight取 BIP 141 weight 与 4 倍 sigops size 的较大值mempool 内部用它以避免精度损失。mempool 条目中以 -weight 为后缀的字段如chunkweight、clusterweight均指该值而以 -size 为后缀的字段如ancestorsize指累计 sigops-adjusted vsizebase fee输入总额与输出总额之差modified feebase fee 加上通过prioritisetransactionRPC 引入的 fee delta。mempool 内部所有与费用相关的策略和区块构建都使用 modified fee。这个定义在源码中直接对应 src/policy/policy.h 中的函数GetVirtualTransactionSize与GetSigOpsAdjustedWeight均以weight、sigop_cost、bytes_per_sigop为参数计算 sigops 调整后尺寸。标准交易判定阈值常量全解doc/policy/README.md 所说的对交易本身的限制主要体现为IsStandard检查节点只中继标准交易而非标准交易默认不中继测试网可通过-acceptnonstdtxn放宽见后文参数节。所有阈值常量集中在 src/policy/policy.h 中以下为完整梳理交易总体尺寸限制常量值含义MAX_STANDARD_TX_WEIGHT400,000愿意中继/挖入的最大交易 weight约 100,000 vBMIN_STANDARD_TX_NONWITNESS_SIZE65最小非见证尺寸比 64 大 1TX_MIN_STANDARD_VERSION/TX_MAX_STANDARD_VERSION1 / 3标准交易版本范围。注释指出变更默认交易版本需分两步先通过提升TX_MAX_STANDARD_VERSION调整中继策略之后再在钱包/RPC 层放开sigops 与脚本限制常量值含义MAX_STANDARD_TX_SIGOPS_COSTMAX_BLOCK_SIGOPS_COST/5单笔交易允许的最大 sigop cost约为区块上限的 1/5MAX_TX_LEGACY_SIGOPS2,500单笔标准交易允许的最大潜在执行 legacy sigopsMAX_P2SH_SIGOPS15标准 P2SH 脚本中允许的最大签名校验操作数DEFAULT_BYTES_PER_SIGOP20-bytespersigop默认值MAX_STANDARD_SCRIPTSIG_SIZE1,650 字节标准 ScriptSig 最大尺寸MAX_STANDARD_P2WSH_STACK_ITEMS100标准 P2WSH 脚本的最大 witness 栈元素数MAX_STANDARD_P2WSH_STACK_ITEM_SIZE80 字节每个 witness 栈元素的最大尺寸MAX_STANDARD_P2WSH_SCRIPT_SIZE3,600 字节标准 witnessScript 的最大尺寸MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE80 字节标准 Tapscriptleaf version 0xc0每个 witness 栈元素的最大尺寸源码注释特别说明P2WSH 的这些限制足以支撑最多100-of-100使用OP_CHECKSIG、OP_ADD、OP_EQUAL组合的多重签名场景对应接口为IsWitnessStandard它同时负责检查 Tapscript 花费时的栈元素上限与不允许 annex。OP_RETURN 数据载体限制常量/默认值值含义DEFAULT_ACCEPT_DATACARRIERtrue-datacarrier默认开启中继数据载体交易MAX_OP_RETURN_RELAYMAX_STANDARD_TX_WEIGHT / 4-datacarriersize的默认上限以 vbytes 计Dust尘埃输出判定常量值含义DUST_RELAY_TX_FEE3,000 sat/kvB定义 dust 的费率阈值。注释强调修改 dust 阈值会改变哪些交易算标准应谨慎且极少改动且只有在先前版本已经不产生低于新阈值的输出之后才有理由上调MAX_DUST_OUTPUTS_PER_TX1每笔交易允许的最大 ephemeral dust 输出数判定入口为 src/policy/policy.h 中的GetDustThreshold(const CTxOut, const CFeeRate)与IsDust(...)以及返回所有 dust 输出索引的GetDust(const CTransaction, CFeeRate)。脚本验证标志Mandatory 与 Standardsrc/policy/policy.h 还定义了两组脚本验证标志是理解共识有效性与标准性分界线的关键MANDATORY_SCRIPT_VERIFY_FLAGS所有新交易必须满足的强制标志包括SCRIPT_VERIFY_P2SH、SCRIPT_VERIFY_DERSIG、SCRIPT_VERIFY_NULLDUMMY、SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY、SCRIPT_VERIFY_CHECKSEQUENCEVERIFY、SCRIPT_VERIFY_WITNESS、SCRIPT_VERIFY_TAPROOT。注释明确这不涉及共识有效性共识侧见GetBlockScriptFlags()STANDARD_SCRIPT_VERIFY_FLAGS在 Mandatory 基础上追加SCRIPT_VERIFY_STRICTENC、SCRIPT_VERIFY_MINIMALDATA、SCRIPT_VERIFY_CLEANSTACK、SCRIPT_VERIFY_LOW_S、SCRIPT_VERIFY_NULLFAIL、SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS/WITNESS_PROGRAM/TAPROOT_VERSION/OP_SUCCESS/PUBKEYTYPE等。注释强调违反这些非强制规则的交易不会导致节点被封禁或断开以改善网络的前向与后向兼容STANDARD_NOT_MANDATORY_VERIFY_FLAGS上述两组标志的差集即标准但非强制的部分STANDARD_LOCKTIME_VERIFY_FLAGS非共识代码中对 sequence/locktime 检查统一使用LOCKTIME_VERIFY_SEQUENCE。对外接口方面src/policy/policy.h 声明了IsStandard(const CScript, TxoutType)判定单个 scriptPubKey 是否为标准输出类型IsStandardTx(const CTransaction, ...)判定整笔交易是否标准参数包括max_datacarrier_bytes、permit_bare_multisig、dust_relay_fee失败原因写入reasonValidateInputsStandardness(const CTransaction, const CCoinsViewCache)检查所有输入scriptSig是否标准SpendsNonAnchorWitnessProg(const CTransaction, const CCoinsViewCache)判断交易是否花费 P2A 之外的见证程序含未定义程序对共识无效交易可能提前返回false常量DEFAULT_PERMIT_BAREMULTISIG{true}对应-permitbaremultisig选项。Mempool 设计聚类、线性化与费率图doc/policy/mempool-design.md 是理解交易与 mempool 已有内容之间的关系这一类 policy 的核心文档其内容如下图模型与术语未确认交易集合被视为一个有向图若交易 B 花费了 A 创建的输出则存在从 B 到 A 的边B 是 A 的childA 是 B 的parent。递归地有ancestors祖先与descendants后代概念。cluster是图的连通分量其中任意两笔交易均可沿边双向互达。给定某笔交易的 cluster 包含它自身、其全部祖先与后代、以及这些交易的祖先与后代依此类推。线性化与费率图feerate diagram每个 cluster 都被线性化拓扑排序任何交易不先于其祖先出现。目标是构造一种线性化使得最高费率子集排在最前其次次高依此类推这些子集称为chunks线性化的 chunks 满足费率单调递减。多个线性化 cluster 的并集可通过按费率对 chunks 做归并排序得到整体线性化。由此可对任意线性化 cluster 集合定义费率图以累计尺寸为横轴、累计费用为纵轴逐 chunk 绘制。两个费率图可以不可比互不包含、等价每个尺寸点累计费用相同、或一方严格更优可比且存在至少一个尺寸点累计费用严格更高。区块构建与驱逐、以及 RBF 的统一判据Mining/eviction整池线性化同时用于区块构建与驱逐——构建区块模板时从线性化前端选择 chunksmempool 需要腾空间时从线性化尾部驱逐 chunksReplace-by-fee在引入 cluster mempool 之前即便替换让 mempool 对矿工更有利替换仍可能被拒绝反之新交易比被替换交易更差也可能被放行。现在可以比较替换前后的费率图只有当替换使费率图严格更优或等价时才接受。这解释了 README 中policy 可用于交易与 mempool 内容的关系的具体机制祖先/后代数量与尺寸限制默认值见下节-limitancestorcount等、RBF 判定、以及 mempool 驱逐策略都建立在这套聚类线性化模型之上。Node relay options可配置参数全表doc/policy/README.md 指出 policy 参数见-help输出中的 Node relay options。这些选项在 src/init.cpp 中通过AddArg(..., OptionsCategory::NODE_RELAY)注册由 src/common/args.cpp 的GetHelpMessage()归入 Node relay options: 分组打印。以下为当前仓库中该分组下的完整参数含默认值参数默认值说明据 src/init.cpp 帮助文本-minrelaytxfeeamt100 sat/kvBDEFAULT_MIN_RELAY_TX_FEE交易最低中继费率-incrementalrelayfeeamt100 sat/kvBDEFAULT_INCREMENTAL_RELAY_FEEDEBUG_ONLY定义中继成本使用的费率用于 mempool 限制与替换策略-dustrelayfeeamt3,000 sat/kvBDUST_RELAY_TX_FEEDEBUG_ONLY定义 dust 的费率输出价值在该费率下花费它所花手续费会超过其自身价值-bytespersigop20DEFAULT_BYTES_PER_SIGOP中继与挖矿中每个 sigop 的等效字节数-datacarrier1DEFAULT_ACCEPT_DATACARRIER是否中继并挖矿数据载体OP_RETURN交易-datacarriersizeszMAX_OP_RETURN_RELAYOP_RETURN 输出的最大尺寸vbytes-permitbaremultisig1DEFAULT_PERMIT_BAREMULTISIG是否接受裸多签输出-maxtxfee区块构建相关默认 0.1 BTCNODE_RELAY 分组外的关联项—钱包侧最大可接受费率此处不展开-limitancestorcount25DEFAULT_ANCESTOR_LIMITmempool 中允许的最大祖先数-limitdescendantcount25DEFAULT_DESCENDANT_LIMITmempool 中允许的最大后代数-acceptnonstdtxn0仅测试网可用DEBUG_ONLY中继并挖矿非标准交易-whitelistforcerelay/-whitelistrelay见DEFAULT_WHITELISTFORCERELAY/DEFAULT_WHITELISTRELAY为白名单对等节点添加 forcerelay / relay 权限前者即使交易已在 mempool 也再次中继后者在节点本不中继交易时仍接受白名单节点的中继注意两个细节-incrementalrelayfee与-dustrelayfee标注为DEBUG_ONLY即普通-help不显示、需-help-debug才可见这与其改动影响哪些交易算标准/可中继、应极少调整的定位一致对应 src/policy/policy.h 中DUST_RELAY_TX_FEE的注释祖先/后代数量默认各 25而 src/policy/policy.h 中 cluster 级别的默认限制更宽DEFAULT_CLUSTER_LIMIT{64}每 cluster 最大交易数与DEFAULT_CLUSTER_SIZE_LIMIT_KVB{101}每 cluster 最大虚拟尺寸单位 kB这为 Package 中继留出了空间。Package 中继策略一子多父doc/policy/packages.md 描述的是交易本身维度之外、允许原子性地以包的形式提交一组存在依赖关系的交易典型场景父交易未入池时随子交易一起提交。实现位于 src/policy/packages.h 与 src/policy/packages.cpp包的基本定义与上限/** Default maximum number of transactions in a package. */ inline constexpr uint32_t MAX_PACKAGE_COUNT{25}; /** Default maximum total weight of transactions in a package in weight */ inline constexpr uint32_t MAX_PACKAGE_WEIGHT 404000;并且源码用static_assert保证包限制与 mempool cluster 限制自洽MAX_PACKAGE_WEIGHT MAX_STANDARD_TX_WEIGHT400,000——保证包限制至少覆盖任何单独会被接受的交易不会因包检查而误拒本可单独接受的交易DEFAULT_CLUSTER_LIMIT MAX_PACKAGE_COUNT64 ≥ 25——因为 package 属于单个 cluster包的限制必须落在 cluster 尺寸限制之内。包的校验规则src/policy/packages.h 中的注释给出了无上下文context-free包策略检查的完整清单交易数量不得超过MAX_PACKAGE_COUNT总 weight 不得超过MAX_PACKAGE_WEIGHT若交易间存在依赖父交易必须出现在子交易之前拓扑有序由IsTopoSortedPackage检查交易间不能冲突即不能花费相同的输入IsConsistentPackage检查含重复交易检测。汇总入口为IsWellFormedPackage(const Package, PackageValidationState)。失败原因通过PackageValidationResult枚举报告PCKG_POLICY包本身不合法如交易过多、PCKG_TX至少一笔交易无效、PCKG_MEMPOOL_ERRORmempool 逻辑错误。此外src/policy/packages.h 还声明了IsChildWithParents的语义一子多父包必须是恰好一个子交易及其若干父交易不必包含全部父交易但不允许包含与子交易无直接父关系的其他交易且包已排序、最后一笔为子交易。这对应当前 P2P 中继中最基本的 package 形态更复杂的多代 package 则受 cluster 级限制约束另有 src/policy/ephemeral_policy.h、src/policy/truc_policy.h 等文件处理更细化的包校验策略从文件名可推断分别对应不同阶段的 package 校验规则。策略不作用于区块与挖矿侧参数的边界doc/policy/README.md 的最后一句Policy isnotapplied to transactions in blocks值得对照源码确认其边界。src/policy/policy.h 同时定义了区块创建侧的常量它们属于Block creation options而非中继策略常量值说明DEFAULT_BLOCK_MAX_WEIGHTMAX_BLOCK_WEIGHT-blockmaxweight默认值控制挖矿代码生成的区块 weight 范围DEFAULT_BLOCK_RESERVED_WEIGHT8,000-blockreservedweight默认值MINIMUM_BLOCK_RESERVED_WEIGHT2,000最小预留 weight覆盖区块头、交易数 var_int 与最小可行 coinbase启动时禁止设置更低值DEFAULT_COINBASE_OUTPUT_MAX_ADDITIONAL_SIGOPS400为 coinbase 输出预留的 sigop costDEFAULT_BLOCK_MIN_TX_FEE1 sat/vB-blockmintxfee默认值即本节点自建区块的最低费率即入块交易的下限由区块创建参数决定中继交易的门槛由 Node relay options 决定两者共享 src/policy/ 下的术语与计算函数如GetVirtualTransactionSize但适用面严格分离——这正是policy 本地可配置而不破坏共识一致性的设计保证。延伸阅读路径沿 doc/policy/README.md 的指引可按以下路径继续深入均为仓库内相对路径doc/policy/mempool-design.md聚类、线性化、chunks 与费率图的完整推导以及 RBF 判据的由来doc/policy/mempool-replacements.mdReplace-by-Fee 的具体规则与实现doc/policy/packages.mdPackage 中继的用户视角说明doc/policy/mempool-terminology.md费用与尺寸术语速查源码层src/policy/policy.h全部标准性阈值、src/policy/packages.h包校验、src/init.cppNode relay options 参数注册、src/common/args.cpp-help分组打印逻辑。小结Policy 是 Bitcoin Core 节点在共识之外、针对未确认交易的本地可配置校验集作用于交易本身、交易与链头的关系、交易与 mempool 内容的关系三个层面且不作用于区块内交易标准性检查的所有阈值交易重量 400,000、sigops、脚本尺寸、dust 3,000 sat/kvB、OP_RETURN 上限等集中定义在 src/policy/policy.h配合 Mandatory/Standard 两组脚本验证标志划分必须合规与鼓励合规的边界mempool 以有向图聚类的形式组织线性化后的 chunks 同时驱动区块构建前端选取、驱逐尾部剔除与 RBF 判定费率图比较运维可调项即-help中 Node relay options 分组所列参数注册于 src/init.cpp默认值与 src/policy/policy.h 中的常量一一对应Package 中继允许一子多父原子入池包级上限25 笔 / 404,000 weight由static_assert保证与 cluster 限制自洽。【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考