签名操作也要折算体积:bytespersigop 默认 20 权重的那本验证成本账 图 1
签名操作也要折算体积:bytespersigop 默认 20 权重的那本验证成本账 · 图 1

比特币交易的大小可以压缩计价(虚拟字节),但签名验证的工作量没法按字节打折。为了让”花很少字节、逼节点验很多签名”的交易不能白吃节点资源,比特币核心的中继与打包政策给签名操作记了一本独立的账:每个签名操作(sigop)按一个固定的折算率参与体积计价。这本账的比例尺就是 -bytespersigop 参数,v31.0 源码 policy/policy.h 里 DEFAULT_BYTES_PER_SIGOP 为 20。这篇讲清这本账怎么记、这个参数实际能调什么、以及它和单笔交易签名成本上限的关系。

先搭机制骨架。节点处理一笔候选交易时,会先算出它的签名操作成本(sigop cost):脚本里每处检签逻辑按各自形态折算成成本单位,见证与非见证形态口径不同。v31.0 源码 policy/policy.cpp 里的换算函数只有一行逻辑:费率计算用的等效权重,取”交易实际权重”与”签名成本乘以 bytespersigop”两者的较大值——默认参数 20 意味着每一个成本单位折算 20 个权重。换句话说,如果一笔交易字节很少但签名密集,政策会按更大的等效体积来评估它的每单位费率:你想用小交易高费率钻验证成本的空子,费率在排序账上立刻被摊薄,挖矿打包上也排不上去。这个设计最早针对的是早期脚本形态下的验证成本套利,今天的见证结构已经把大多数常见情形纳入更均衡的计价,但记账框架保留着。

bytespersigop 能调什么?它在 init.cpp 里是 ALLOW_ANY 的普通节点参数,含义是”中继与打包时每个签名成本单位折算多少权重”。调低它,意味着签名密集的交易在费率账上更占便宜、更容易中继;调高它,则更严厉地惩罚验证成本重的交易。但要注意一个更硬的天花板独立存在:政策对单笔标准交易的签名成本另有绝对上限,共识层对整块也有总成本上限——那些是结构性拒绝,不是费率折算,超限的交易直接被拒之门外,调 bytespersigop 救不了它。换句话说,bytespersigop 管”同等费率下谁更划算”,绝对上限管”再有钱也不收”。

现实中它值得动吗?绝大多数节点没有任何理由离开默认值 20。它是一个遗留的 DoS 平衡旋钮:只有在你的节点观察到特定脚本形态的交易让 CPU 验证压力异常、并且你确切理解调低或调高对费率排序的连带影响时,才值得实验性调整。对普通用户和运维者,它更常以另一种身份出现——当你在 -help-debug 或别人的配置里看到这一行,能立刻认出这是”签名成本折算率”而不是什么手续费开关。也要澄清常见误读:它不影响你钱包付多少手续费(那是 mintxfee、feerate 估算那些参数的领域),也不改变共识层的块签名总量历史限制,纯粹是本节点的中继政策权重。

把绝对上限的具体数字也算一遍,能看清这套账的量级感。共识层规定每个区块的签名操作成本上限为 80000(内部以”成本”单位计,不同脚本形态折算到成本单位的比例不同);政策层则给单笔标准交易设了更严的门槛——签名成本上限取块上限的五分之一,即 16000 成本。也就是说,即使一个区块整体还有签名预算剩余,任何单笔超过自己份额上限的交易都进不了标准集合。这套两级数字解释了为什么历史上”将验证成本外包”的极端脚本从未成为经济上可行的攻击:字节账、成本账、单笔配额三本账同时收紧,套利空间在协议设计期就被压平了。而 bytespersigop 只是这三本账里唯一留给你调的那颗小螺丝。

最后给版本边界:以上默认值与参数语义核对自 v31.0 源码(常量定义在 policy/policy.h,注册于 init.cpp)。这个参数从 0.11 时代就存在并经历过折算规则调整,历史上各版本对 sigop 计数口径(尤其 witness 版本之间)有过多次修正,引用到具体交易分析时请以上机版本的 RPC 与文档为准。

风险提示:调整节点中继参数可能改变你接收交易的集合,实验前请理解对费率排序的连带影响;本文不构成投资建议。

签名操作也要折算体积:bytespersigop 默认 20 权重的那本验证成本账 图 2
签名操作也要折算体积:bytespersigop 默认 20 权重的那本验证成本账 · 图 2