协议演进 / BIP/比特币改进提案 / BIP-64
BIP-64
给 P2P 协议加 getutxos / utxos 两条消息,让轻客户端向全节点查询一组 outpoint 是否还在 UTXO 集合中。本 BIP 目前处于已关闭状态。
一、档案卡
| 编号 | BIP-64 |
|---|---|
| 标题 | getutxo message |
| 作者 | Mike Hearn <[email protected]> |
| 指定日期 | 2014-06-10 |
| 层级 | Peer Services(对等服务) |
| 类型 | Specification(规范类) |
| 状态 | Closed(已关闭) |
| 阅读版 | https://bips.dev/64 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0064.mediawiki |
二、放在哪一族
BIP-64 属于对等服务层(Peer Services)的 P2P 协议扩展族:它不改共识规则、不改交易格式,只给节点之间增加一种“代查”问答——由没有完整 UTXO 集合的轻客户端发问,由全节点代为查询后回覆。
它与布隆过滤(Bloom filtering)同属轻客户端依赖全节点的路线,原文也明确说:两者的安全模型相同,远程节点都可能以“遗漏”的方式撒谎。
三、它要解决什么
所有全节点都维护一个未花费交易输出集合(UTXO set)。一笔交易是否双花,要看它引用的输出是否还在这个集合里;输出的标识叫 outpoint,就是“包含该输出的交易的哈希 + 序号”。
轻客户端 / SPV 客户端手里没有完整的 UTXO 集合,有时却很想快速查一下某个输出还在不在。原文举了两个例子:
- 担保合约(assurance contracts):新的认捐(pledge)出现时,快速检查这笔认捐是否已经被双花撤销;
- 浮动手续费计算:SPV 钱包做手续费估算时可能用到这类数据——不过原文说这一用途还需要协议的其他改动,不在此展开。
原文也承认:这类应用并非非它不可,完整下载并保存整条区块链也能做;这条消息的价值在于性能可接受、界面上的各种情形好处理。
四、规则本身
4.1 请求消息 getutxos
包含两个字段:
- check mempool(1 字节 bool):计算时是否把内存池交易算进去——算进去,就会暴露内存池交易新产生的 UTXO,并把被内存池交易花掉的输出排除;
- outpoints(vector<COutPoint>):要查询的 outpoint 列表,每个 outpoint 按 tx 消息里相同的方式序列化。
4.2 回覆消息 utxos
包含四个部分:
- chain height(uint32):算出结果那一刻的链高度;
- chain tip hash(uint256):那一刻链顶区块的哈希;
- hit bitmap(byte[]):每个被查询的 outpoint 占一位,标明它在 UTXO 集合里找到没有;
- result utxos:只为“未花费”(位图里置位)的 outpoint 各给一个结果对象。
结果对象包含:定义该输出的交易版本号(uint32)、该交易所在区块的高度(uint32;在内存池里则为 0x7FFFFFFF)、以及输出本身(CTxOut,按 tx 消息里相同的方式序列化)。
4.3 如何宣告支持
节点以两种方式表明自己支持这项扩展:宣告协议版本高于 70003,并在 nServices 字段里设置新的 NODE_GETUTXO 标志——其值为 2,即该字段的第二个位。
4.4 认证上的先天不足
原文专设一节讲 Authentication,要点是:
- UTXO 集合目前不被任何东西认证。原文提到有提案想用新的共识规则在区块里承诺 UTXO 集合的根哈希,但当时并不可用;若将来有了,utxos 消息可以升级为附带默克尔分支,证明输出确实在被承诺的集合里;
- 若请求方手里有为某个已签名交易查输出,可以用该输出实际跑一遍输入脚本,部分验证回覆——但这只能证明脚本对不对,不能证明该输出真的未花费、甚至真的在区块链里被创建过;执行前还应检查 scriptPubKey 的形式,防止远程节点干脆把脚本设成 OP_TRUE;
- 若请求方有“高度 → 区块哈希”的映射(例如由 getheaders 得到),可以再索要对应区块、从中找该输出,证明它至少曾经存在过;与布隆过滤结合,效率可以做到合理。
即便做了这些检查,远程节点仍可“以遗漏撒谎”:声称某个 UTXO 不存在——而“不存在”与“已被花掉”从全节点的视角看是同一句话。向多个节点查询、合并答案只是部分解法;比特币 P2P 网络本身无人认证,中间人仍可能给出错误结果。
五、谁必须动
普通持币人:无直接变化。不改变交易、地址或共识规则。
轻客户端 / SPV 钱包开发者:想用这项能力,就要能构造 getutxos 查询、解析 utxos 回覆,并按原文的认证一节正视回覆不可全信的问题。
全节点:完全自愿。愿意提供查询服务的节点,才设置 NODE_GETUTXO 标志并回覆查询;不设置的节点不受影响。
矿工与共识层:不必动。这是对等服务层的可选扩展,区块有效性规则没有任何改变。
六、现在算不算数,以及一个常见误读
状态为 Closed(已关闭)。原文给出了规范与一个参考实现的链接,但它没有成为 Deployed 的网络服务;今天不能假定主网节点提供 getutxos 查询。它的档案价值在于记录了轻客户端“代查 UTXO”这条路线及其安全边界:查询结果快,但没有密码学认证。
常见误读:
“节点回覆说某个 UTXO 不存在,就等于证明了它已经被花掉。”
不对。原文明确说 UTXO 集合当时不被任何东西认证,节点可以以遗漏的方式撒谎,“不存在”与“已花费”在其回覆里无法区分。把这种回覆当作双花的密码学证据,超出了这份规范自己承认的保证范围。
