五个常量撑起一个拒绝服务防线
打开比特币核心的script.h,一组上限常量排成一列:单个脚本最多一万字节;非推送类操作码每脚本不超过两百零一条;单次压入栈的元素不超过五百二十字节;脚本执行期间栈内条目不超过一千;OP_CHECKMULTISIG单条指令最多二十把公钥。它们不是随手的数字游戏,而是一整套拒绝服务的成本公式:脚本验证发生在每台全节点、每一笔待打包交易上,任何与输入体积不成正比的验证开销都是免费算力攻击的入口。字节上限控制单次解析成本,操作码计数封死循环放大,元素与栈深限制内存驻留,二十把公钥的上限则同时服务于签名聚合的可控性——当年设计者宁可限制多签规模,也不愿脚本在签名逐个匹配的嵌套循环里消耗不封顶的时间。
每个数字在现实里挡住过什么
这些限制不是装饰。五百二十字节的元素上限配合数据推送模板,决定了链上写数据的搬运必须切片——Ordinals一类载数据方案按五百二十字节切块塞脚本,正是撞上这根线的产物。两百零一的非推送操作码上限,堵住了用跳转结构把小脚本炸成大执行路径的解压缩式攻击。千层栈封顶让任何脚本的内存驻留量可预算。多签公钥数的取值还能从演进里读出工程口味:隔离见证版本的OP_CHECKSIGADD路径把上限提到九百九十九把,script.h的注释写明这受BIP342栈限制约束——限制没有消失,只是换成了按栈深度重新推导的形态。
Tapscript拆掉两道红线,靠的是什么
BIP342的Taproot落地时专门声明,Tapscript里一万字节的脚本上限和两百零一条操作码上限都不再适用,脚本体积只受区块权重预算的间接约束。删除的底气来自两处结构性变化。其一,签名哈希不再直接包含脚本正文,只承诺一个预先可计算的叶子哈希,验签的CPU开销不再随脚本长度线性甚至超线性膨胀,一万字节的原始理由被抽掉地基。其二,条件分支的实现换成常数时间逻辑,当年研究者展示过的分支跳转二次方延迟攻击被源码级修复,操作码计数的使命随之到期。两条防线不是被放松,而是被更底层的设计变廉价,这也是比特币脚本演进一贯的思路:先把昂贵的东西做便宜,再撤掉脚手架。
对开发者的三点提醒
第一,跨脚本类型移植策略时必须重算资源账:同一条多签逻辑在OP_CHECKMULTISIG下受二十把钥匙约束,在OP_CHECKSIGADD下可放宽到千把钥匙级别,但钱包的签名收集流程、费率估算与设备显示长度都会随密钥数水涨船高,能容纳不等于该用满。第二,依赖操作码数量做安全假设的审计工具需要针对Tapscript重新校准,计数上限的消失意味着旧模型里不存在的执行形态进入了可行域。第三,资源限制本身是可演进参数而非永恒法则,读任何脚本教程时先确认它写于哪个脚本时代——拿隔离见证时代的二十把钥匙上限去解释今天的九百九十九,会误导读者对多签方案的判断。本文核对于2026年9月,只作机制科普,不构成投资建议。
一笔费用的账
这些常量的存在还解释了一个日常困惑:为什么带长脚本的交易费率更高。资源限制意味着每字节脚本都在竞争节点的处理预算与区块的权重预算,多签解锁需要的签名压栈、脚本正文本身,全部按费率定价计入成本。理解一万字节、五百二十字节与两百零一这些红线后,你会发现钱包设计里大量看似挑剔的细节——优先隔离见证模板、控制多签密钥数量、把复杂条件挪进时间锁而非脚本堆叠——都是在这些预算线内省费钱的工程答案。数字限制最终塑造了使用习惯,这是资源治理在用户体验端最安静的投影。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。