一、节点为什么要”记住验过的签名”
比特币的共识规则要求每个输入的解锁脚本里的签名,必须能被那笔钱锁定的条件验证通过。这一步叫脚本验证,是全节点最耗 CPU 的环节之一:椭圆曲线上的签名运算没有捷径,每笔交易都要实打实地算。验证结果只有两种,且完全确定——只要区块内容、共识参数不变,同一笔交易的签名要么永远通过,要么永远不通过,今天算和一年后算结果一模一样。
正是”确定且昂贵”这两个性质,让缓存变得合算。节点在一轮同步里会反复遇到同一批交易:接收时验一次,进内存池验一次,打包或重组时可能又验,重启后重新扫链还会再验。把”某段数据对应的这个签名已经验过且通过了”这个事实记进内存,下次直接查表放行,就能省掉大量重复运算。Bitcoin Core 的签名缓存放得很明白:它缓存的是”验证通过的证明”,缓存命中即视为通过,未命中才真正去算。

二、两个缓存共用一个预算
现代版本把这套机制拆成了两块:签名缓存,记纯签名的验证结果;脚本执行缓存,记带脚本哈希的执行结果(对多签、时间锁这类复杂脚本更划算)。两块各自独立,但共用一份总内存预算。官方常量把这个预算设为三十二兆字节,签名缓存与脚本执行缓存各拿一半,源码里有断言保证两者之和恰好等于总额。
暴露给用户的开关是 -maxsigcachesize,单位是兆字节,含义是”这两个缓存加起来的体积上限”。它被标注为仅调试类参数,意思是不建议普通用户去动,默认值针对常见硬件调过。想把它调大,通常是为了同步时的脚本验证提速;想调小,多半是在内存极小的设备上给链状态数据库腾地方。无论调高调低,它不改变任何共识判定,只改变命中率。
三、缓存会不会把”坏消息”也缓存下来
这是隐私与安全上最该讲清楚的一点。签名缓存只在签名验证成功之后写入,一个永远不通过的坏签名不会因为试过就被记住——它也不值得记,验不过直接拒收,根本不会反复触发重算。所以缓存里存的全是”确实花得动这笔钱”的证据,没有一笔是攻击载荷。
那攻击者能不能靠伪造数据把缓存灌满、逼节点疯狂换页?答案藏在缓存的键设计里:缓存条目要占用内存,写入前会按交易数据做哈希,超预算时按最久未用淘汰。灌满缓存的成本远高于命中带来的收益,攻击面被压到可以忽略。换句话说,这个参数不是安全边界,调它既不会让节点更容易被骗,也不会让节点更防骗——它纯粹是一台机器的内存与速度之间的旋钮。
四、低内存机器上的实际手感
在一台四吉字节内存的服务器上跑全节点,脚本执行阶段最容易顶到内存墙。此时有一组相关联的取舍:链状态数据库缓存、内存池上限、验证线程数,以及这里的签名缓存预算。官方文档和参数说明都提示,未使用的内存池空间会和数据库缓存共享,而验证线程数会影响同时需要缓存的签名量。合理的顺序是先按机器物理内存给链状态和内存池定盘子,再决定要不要动签名缓存——多数时候不需要动,默认值就是为”别占太多也别太小”设的。
判断有没有必要调,有两条线索。一是同步阶段日志里脚本验证耗时是否明显拖住整体进度;二是内存是否长期吃紧到触发换页。只有同时出现”验证很慢”和”内存还很宽裕”,把签名预算上调才有净收益;如果是内存本身见底,正确的动作是压缩别的部分,而不是给缓存加量。
五、缓存与重启、与修剪
签名缓存不写盘。节点关闭它就消失,重启后一切从头验起,这也是为什么冷启动同步比运行中的增量同步更费时间。它是纯运行期加速结构,不属于需要备份的数据——你从不需要为它做任何持久化操作,它也从不影响恢复流程。
对修剪模式也没有特殊影响:无论节点保留完整历史还是只留最近一段,验证一笔新交易时该算的签名一样要算,缓存同样只是临时省算力。把它记成”一块随进程生灭的算力的便利贴”最准确:贴得下多少由预算决定,内容永远只是”这个已经算对过”,仅此而已。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。