布隆过滤器收款:老式轻钱包怎样少收数据,又为此付出什么 图 1
布隆过滤器收款:老式轻钱包怎样少收数据,又为此付出什么 · 图 1

轻客户端的根本困境

全节点把整条链搬回本地,用完整验证换隐私:你查询什么,没人知道。轻客户端(SPV)相反,它只下载区块头,交易是否与自己有关,得让全节点帮忙筛选。麻烦在于“告诉节点我在找什么”这一步——把公钥列表原样发过去,等于把整本户口本摊给一个匿名陌生人。布隆过滤器是这场交易能谈成的数学妥协。

布隆过滤器收款:老式轻钱包怎样少收数据,又为此付出什么 图 2
布隆过滤器收款:老式轻钱包怎样少收数据,又为此付出什么 · 图 2

概率筛子:宁可错发,绝不漏发

BIP37 在每条对等连接上挂一个过滤器,本质是布隆过滤器:一段字节数组加若干哈希函数。节点把交易的各部分(公钥哈希、输出脚本、出点等)逐项哈希进位,查询时只需检查对应位是否全为一。布隆过滤器的性质决定了一切:位图上命中不代表真属于集合(误报),但只要真属于集合,位图必然命中(不会漏报)。轻钱包用它筛自己收款的交易,误报意味着多下载一些无关交易,漏报在定义上不存在——这正是“宁可错发”的由来。误报率由客户端自己选:调高则过滤器小、带宽省,节点也更难猜出哪些命中真的与你有关;调低则相反。协议给过滤器尺寸设了硬上限 36000 字节,约等于两万个元素配千分之一误报率的容量。

过滤器会变脏:三种更新模式

钱包不仅要收到付给自己的新输出,还得盯住自己旧输出被花掉的情况——花费交易的输入里未必直接包含地址,过滤器却必须命中。BIP37 因此提供三种自动更新模式:全量更新把每笔花费交易的出点也塞进过滤器;只在出点为公钥形态时更新,兼顾效率与常见场景;不更新则把责任丢回客户端自行刷新。规范坦率地指出,选择前两种模式的过滤器会随扫描越来越脏、误报率持续上升,钱包应当监测实际误报率并定期重建。

隐私:精确本身就是裂缝

布隆过滤器不是匿名工具。一个只装着三五个地址的精确过滤器,在节点看来几乎等于实名:“这些交易是同一位客人”。协议因此建议带宽充裕的客户端故意调高误报率,用噪声稀释命中与身份的关联——过滤器精度与隐私强度是一根绳子的两端。这条边界也催生了后续更聪明的方案:不再让节点看懂过滤器,改为下载紧凑区块过滤器后本地匹配(这一路线已有专文,此处不赘)。

常见误区

  • 误区一:“轻钱包没隐私可言。”误报率调高后单连接相关性会显著变难,但确实弱于全节点模型。
  • 误区二:“过滤器漏抓了钱。”布隆结构在定义上不漏,若出现异常漏失,应核查过滤器是否过期未重建。

本文是历史协议的机制解读,不构成投资建议。

从布隆过滤器到紧凑过滤器:一次安静的换代

布隆过滤器的隐私困境在规范作者那里早已坦诚:精度与匿名不可兼得,于是后续路线换掉了问题本身——不再让节点解读“你在找什么”,而是把每个区块里与“脚本命中”相关的位图压缩成一份紧凑过滤器交给客户端,匹配逻辑整个搬回本地。过滤器由谁生成、怎么压缩、如何用少量交互核对漏报,属于另一条协议线(BIP157/158),已有专门文章展开。站在历史坐标上,BIP37 的定位很清晰:它是第一代在“验证外包”与“最小披露”之间的工程妥协,撑起了早期轻客户端生态,也用自己的不足指出了正确的抽象边界——判断“与我有关”的权力,最终要留在用户设备上。对今天还在跑旧轻客户端模式工具链的开发者,务实的建议是:新钱包不应再基于布隆过滤器做隐私设计,但理解它仍然重要,因为不少服务接口的历史行为、误报率调参讨论与带宽权衡,都还活在这套语义里。