一个手机钱包想确认”有一笔钱到过我的地址”,传统做法有两个极端:自己下载并验证整个账本,或者把地址交给一台服务器去问。前者重、后者信不过。比特币的 BIP 157 和配套的 BIP 158 提供第三条路:让全节点为每个区块生成一份极小的”这块里有哪些人”的清单,轻客户端先买清单、再按需买整块,全程不需要信任任何一台服务器说”没有你的交易”。两份 BIP 的文本状态都是 Deployed,早在 2017 年 5 月被分配编号。
旧办法为什么被淘汰
过去的主流轻客户端协议是 BIP 37 的布隆过滤器:客户端把自己关注的地址编成过滤器发给节点,节点把匹配的推送回来。BIP 157 的动机部分直接点名了这条路的两个毛病:过滤器本身向节点泄露了客户端在看什么,多项研究表明主流实现对钱包几乎没有隐私;同时这种过滤器给了攻击者对全节点发动拒绝服务的杠杆。问题根源在于方向反了——是客户端把自己感兴趣的东西出示给节点。
反转方向:先清单,后区块

BIP 158 的做法是反过来:节点对每个区块里的脚本公共键等条目,用 Golomb-Rice 编码压出一份确定性的紧凑过滤器(初始类型叫 basic)。客户端不透露任何地址,先把每个区块的过滤器成批拉下来,在本地拿自己的数据去试。过滤器是概率结构,会有假阳性——试出”可能命中”就必须下载完整区块做真实验证;而假阴性被构造规则排除:命中率的错误方向只错在不该命中时命中,不会错过真实存在的交易。代价是明确的:每个区块都要多拉一份几 KB 的过滤器,误报会诱发一些无用的整块下载。
过滤器头:防的是说谎的节点
只拉过滤器还不够,恶意节点可以递一份”恰好不含你地址”的假清单。BIP 157 为此定义了过滤器头(filter header):每个区块的过滤器头是对此前所有过滤器链式承诺的一部分,客户端只需验证过滤器头串接的哈希链,就能锁定某区块过滤器的唯一正确版本。协议给出的保证是:只要有一个诚实的节点,客户端就能识别其他节点在过滤器上作恶。客户端因此可以安全地从一个便宜但不完全可信的数据源批量同步。
构造细节上,BIP 158 把每个条目先经 SipHash 映射为 64 位整数,再用 Golomb-Rice 编码压缩排序后的差值序列,假阳性率由参数 M 控制(查询命中概率约 M 的倒数),basic 过滤器类型选定了这套参数与条目集合的约定。相比同样假阳性率下的布隆过滤器,这种集合编码的体积明显更小——这正是它取代 BIP 37 的直接原因。条目选取也有讲究:过滤器收录的是脚本里的公钥等标准化元素,而不是任意字节串,避免攻击者构造超大脚本撑爆过滤器。
和默克尔证明怎么配合
发现疑似命中后,客户端下载对应区块,自己做工作量证明与链验证,再定位到具体交易——此时它验证的是完整区块而不是片段,安全性与全节点对这笔交易的判断一致。整条链路里,轻节点始终自己验证区块头链,这延续了中本聪轻客户端”信最长工作量证明链”的传统,BIP 157 只是把”去哪里找相关交易”从询问制改成了清单制。
用户视角与边界
对个人用户,这套机制的实际受益者是钱包的隐私和流量账单:无需第三方索引服务也能离线扫描可疑区块范围。它是发现机制而不是加速机制——真到账仍以节点验证完整区块为准;同名资产、其他链上的交易也不在这份清单的覆盖范围内,不能跨链混查。运行或调试这类钱包时,一个可核对的观察点是过滤器头的高度是否与区块头高度一一对应,若两边高度错位,多半是同步实现的缺陷。机制细节以两份 BIP 的规范文本为准。本文只讨论技术,不构成投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。