141 / 736NEUTRINO

Compact Block Filters

BIP 157 与 BIP 158 规定的紧凑区块过滤器

手机钱包怎样才能不下载所有交易,也找到自己的收付款?Compact Block Filters 帮助它挑出值得进一步检查的区块,而不必把关注的地址清单发给服务器。

Compact Block Filters 是比特币区块内容的小型摘要。钱包下载这些摘要,在自己的设备上判断哪些区块可能包含相关交易,然后才索取这些区块的完整数据。这样既节省流量,也少透露一些搜索目标。不过,过滤器匹配不等于付款证明,也不能替代对比特币规则的完整验证。

安娜正在等手机钱包收到一笔付款。钱包是接收和发送比特币的应用程序或设备。区块是一批交易的集合,但手机不必把每一批都完整下载。它可以先检查小型过滤器,就像先查书后索引,再翻到相关页面。对于同一个区块和过滤器类型,所有用户拿到的是同一份摘要;判断什么与安娜有关,则在她的手机上完成。技术文档 BIP 157 和 BIP 158 分工明确:前者规定如何取得和核查过滤器,后者规定其内容和构建方法。钱包先验证区块头,也就是连接区块的基本记录,再取得过滤器的校验数据和过滤器本身。发现匹配后,它才下载完整区块,查找真实交易。名称相近的 Compact Blocks 属于 BIP 152,解决的是另一个问题:如何在节点之间快速转发新区块。节点是验证交易和区块、并与其他网络参与者通信的软件。 [1] [2] [5] [6]

比特币交易会创建输出:一笔金额,以及以后花费它所需满足的条件。表达这些条件的代码叫 scriptPubKey。新交易的输入则指向它要花费的旧输出。因此,编号为 0x00 的 basic 过滤器既包含新输出的脚本,也包含本区块所花费旧输出的脚本。安娜可以据此查找收款和支出。以 OP_RETURN 开头的新输出脚本不纳入其中,这条指令使输出无法被花费。coinbase 交易的特殊输入也被排除:该交易给矿工分配奖励,不花费任何旧输出。空项目会被省略,重复项目只计算一次。这不是所有交易标识符 txid、文本地址或 witness 数据(例如签名)的清单。要正确构建过滤器,除了新区块,还需要其中交易所花费的旧输出数据。 [2]

服务器可能给安娜一份故意漏掉她的付款的摘要。因此钱包还要检查过滤器之间的连接关系。哈希是数据的短数字指纹。对保存的过滤器连续应用两次 SHA-256,就得到它的 double-SHA256 哈希。把这个指纹与前一个过滤器头拼接,再以同样方式计算,就得到下一个过滤器头。修改较早的过滤器,会影响后续校验数据。但由挖矿保护的区块头,并不包含这条辅助过滤器链的哈希。如果所有已连接的服务器都提供同一条假链,指纹仍然可以完全吻合。数学上的自洽,本身不能证明摘要与真实区块相符。 [1]

因此 BIP 157 建议连接多个独立节点,在这种通信中也称 peers。另一种选择是与可信节点(例如自己的节点)建立安全连接。如果收到的过滤器链互相矛盾,钱包会找到首个分歧点,并用对应区块及必要的旧输出重建正确过滤器。识别正确过滤器的保证,以至少存在一个诚实对等节点为前提;连到同一攻击者的多个连接并不满足条件。区块链本身也可能变化:发生重组时,节点把链尾的一部分替换为累计工作量更大的分支。钱包必须改用该分支的过滤器,重新判断受影响的付款。已经找到的确认,仍取决于网络接受哪条链。 [1] [2]

较早的 BIP 37 方法要求钱包向服务器发送自己的过滤器,描述想监控什么。Compact Block Filters 把流程反过来:钱包下载通用数据,在本地做个人选择,从而减少受监控脚本的信息泄露。不过,提供者仍能看到安娜随后请求哪些完整区块,也可能把这些请求与她的 IP 地址,也就是连接的网络地址,联系起来。反复访问还可能暴露更多模式。BIP 157 因此建议,从钱包主动建立连接的节点中随机选择完整区块来源。提供区块的节点可以不同于提供过滤器的节点。这能改善隐私,却不保证匿名。 [1]

过滤器描述的是已经加入链中的区块,不覆盖当前 Mempool,即某个节点为继续传播或挖矿而保存的未确认交易。匹配也不证明安娜拥有花费所发现资金的密钥。私钥是钱包用来生成数字签名、授权花费资金的秘密数值。钱包需要检查真实交易,以及它是否被纳入区块。即便如此,轻客户端也不会像 Full Node(完全验证节点)那样,按所有规则验证所有区块的每一笔交易。节省资源确实伴随着安全取舍。数据可用性是另一个问题:Pruned Node 可以在验证后删除旧区块,但保留过滤器。安娜这时能取得摘要,却要到别处下载完整旧区块。裁剪旧数据本身,不代表节点放弃完整规则验证。 [1] [5]

小体积有代价:即使目标不在区块里,过滤器也可能回答“也许有”。这叫假阳性,即误匹配。安娜因而多下载一个区块,但钱包找不到那笔假想的付款,就不能把它计入余额。正确过滤器不会漏掉按其规则实际纳入的项目;这个性质并不意味着恶意服务器伪造的数据可信。技术上,SipHash-2-4 把项目转换为范围大小为 N × M 的数字,N 是项目数量。数字排序后,相邻差值用 Golomb-Rice 编码紧凑保存。P=19 控制编码,M=784931 影响偶然匹配的概率;对集合外单个项目的查询,误匹配概率约为 1/M。字节是衡量数据大小的常用单位。SipHash 的密钥取区块哈希按 little-endian 顺序表示的前 16 字节,也就是低位字节在前。它不是钱包的秘密密钥。这里的 SipHash 只是把项目转换为过滤器使用的数字,并不对项目进行加密。保存的过滤器以 CompactSize 格式的 N 开头;该格式用来表示非负整数。 [2]

截至复核日期 2026-10-17,两份文档的状态都是 Deployed,表示协议已部署,而不是每种钱包都支持。以下配置示例特指 Bitcoin Core 29.0。-blockfilterindex 建立本地过滤器索引;向其他节点提供服务还需要 -peerblockfilters 和 basic 索引,NODE_COMPACT_FILTERS 用来宣布这项能力。程序接口 RPC 中的 getblockfilter 返回指定区块的 filter 和 header 字段。因此,RPC 查询成功,本身不能证明其他网络节点能够取得过滤器。阅读规范时,getcfilters/cfilter 负责传送过滤器,getcfheaders/cfheaders 传送连接校验数据,getcfcheckpt/cfcheckpt 提供辅助链的检查点。这些是网络消息名称,不是手机钱包用户需要输入的命令。 [3] [4]

要获得更完整的理解,请将本词条与以下词条结合阅读: Neutrino, Full Node, Pruned Node, Bitcoin 隐私, Compact Blocks, Mempool. 反向关联还来自: Compact Block Filters, Neutrino.

DOC · 001BIP 157 — Client Side Block Filtering规范 DOC · 002BIP 158 — Compact Block Filters for Light Clients规范 DOC · 003Bitcoin Core 29.0 — getblockfilter RPC文档 DOC · 004Bitcoin Core 29.0 — Filter service configuration一手来源 DOC · 005Bitcoin Developer Guide — Wallets文档 DOC · 006Bitcoin Developer Guide — Block Chain文档
修订日期: 来源优先 · 非投资建议