协议演进 / BIP/比特币改进提案 / BIP-330
BIP-330
为两个节点之间的交易公告对账定义 P2P 扩展,用短 ID 草图求出双方交易集合的差集,支撑 Erlay 等高效中继协议。本 BIP 目前处于草案状态。
一、档案卡
| 编号 | BIP-330 |
|---|---|
| 标题 | Transaction announcements reconciliation |
| 作者 | Gleb Naumenko <[email protected]>, Pieter Wuille <[email protected]> |
| 指定日期 | 2019-09-25 |
| 层级 | Peer Services(对等服务) |
| 类型 | Specification(规范类) |
| 状态 | Draft(草案) |
| 阅读版 | https://bips.dev/330 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0330.mediawiki |
二、放在哪一族
P2P 交易中继族,定位是“积木块”,不是完整的中继协议本身。它要支撑的上层协议是 Erlay:Erlay 同时使用泛洪(向所有对等节点发 INV 公告)与对账两条路,泛洪只用在需要快速传播的少数连接上,其余连接靠高效集合对账来补齐与同步。
它与交易公告既有机制的关系包括:
BIP-339:基于 WTXID 的交易中继,本篇的草图建立在 WTXID 之上,协商与启用 Erlay 以双方都信号支持 BIP-339 为前提
此外,它借用 BIP-340 定义的 TaggedHash 来计算短 ID 的盐值哈希。理解本篇,关键在分清“对账协议本身”与“使用对账的高层中继协议”两层:本篇只定前者的消息与算法。
三、它要解决什么
现行做法中,每一对相连的节点之间,每个 32 字节的交易 ID 至少要单向公告一次(通过 INV 消息)。这使公告交易的成本呈“节点数 × 每节点连接数”的量级,带宽开销很高。
基于对账的协议可以有更好的扩展性。若交易中继的带宽扩展性能改善到接近 O(nodes) 且常数开销不高,就能以几乎不增加带宽的代价提高网络连接度(connectivity),让网络更能抵抗分区攻击(partitioning attacks);同时降低运行比特币节点的带宽需求,潜在地让更多人能运行全节点。
Erlay 设想的工作方式是:每个节点为每个对等节点维护一个对账集,原本要用 INV 公告的交易先放进对账集;每隔一段时间选一个对等节点做一轮对账,双方互相学到对方已知的交易;每轮对账后清空对应集合。这样既省带宽,又基本保持交易传播延迟不变。
本篇就是为这类对账式中继提供 P2P 层的扩展规范。
四、规则本身
4.1 32 位短交易 ID
对账不用完整的 32 字节 WTXID,而用 32 位短 ID:双方各贡献一份盐(salt),排序后按 BIP-340 的 TaggedHash(标签 “Tx Relay Salting”)哈希,取出密钥对 WTXID 做 SipHash-2-4,再映射到 [1..0xFFFFFFFF] 区间。短 ID 近似均匀分布,这是把它们当作 32 位草图元素的前提。每条连接使用独立盐,可把非对抗模型下的碰撞率控制在低水平。
4.2 短 ID 草图(sketch)
对账用的是 PinSketch(BCH 安全草图):草图有预定容量,集合元素数不超过容量时,总能从草图完整恢复出集合;两个集合各自草图的合并,就是两集合对称差(只属于一方的元素)的草图。
本篇的草图元素取自有限域 GF(2^32):容量为 c 的草图由 c 个域元素组成,依次是集合中所有短 ID 的和、三次幂之和、五次幂之和,直到 (2c-1) 次幂之和,每个元素按 32 位小端编码,总长 4c 字节。原文给出构造草图的 Python 代码,并指出 minisketch 库可高效实现草图的构造、合并与解码。
选 PinSketch 的理由是:它比 IBLT 更省带宽(尤其在预期的差集很小的场景下),带宽效率与 CPISync 相当,但解码复杂度是平方级而非立方级,速度明显更快。
4.3 协议流程与草图扩展
一轮对账主要是:应请求传一幅草图并解码。若节点无法从收到的草图重建差集,可请求草图扩展:对方发来更高容量的草图,但只发新增部分(原草图已发的部分不必重发),发起方把扩展与本地存下的初始草图拼接后再解码。为此,发起方要本地保存初始草图,双方也要在发或收初始草图时把当前对账集做快照并清空原集,快照保留至本轮结束,以保证扩展是对同一批交易计算的。
原文还选择了“扩展”而非“二分(bisection)”:扩展实现简单得多、容量调整灵活;二分唯一的优势是不必算高容量草图,但预期容量通常不超过 20,这点效率不关键。
4.4 五种新消息
sendtxrcncl:公告支持对账协议,只发一次,应在verack之前发送,并与wtxidrelay伴随(顺序不限);载荷含协议版本(当前必须为 1)与本方盐。对等方在version中声明不中继交易(fRelay=0)时不得发送。双方都发过后,连接发起方担任对账发起者,另一方担任响应者,reqrecon只能由发起者发。reqrecon:发起一轮对账,载荷含本方对账集大小set_size与用于估计差集的系数q。sketch:传送对账集快照的草图,既可是初始草图,也可是应扩展请求发来的扩展草图。收到后,节点把对方草图与本地草图合并成差集草图并尝试解码:成功则发 success 的reconcildiff;初始解码失败可先发reqsketchext请求扩展,也可直接以失败结束;扩展后仍失败则以失败结束。失败时还要把对账集(或快照)中的交易改走泛洪公告作兜底。reqsketchext:请求草图扩展,载荷为空。收到方回一幅sketch,内容是同一批交易的高容量草图的增量部分。reconcildiff:发起者向对方公告对账结果,载荷含是否解码成功的标志与“我方缺失的短 ID 列表”。对方收到 success 后,按短 ID 用inv发出被请求的那些交易(以 WTXID 标识、父交易在前);收到失败标志则把对账集全部交易用inv公告。发送方同时也要发自己的inv,公告对方缺失的交易。本轮快照随之清除;在收到reconcildiff之前不得再发新的reqrecon。
4.5 本地状态与容量估计
除盐与对账集、快照外,响应方收到 reqrecon 时要按公式估计应发草图的容量:capacity = |set_size − local_set_size| + q × min(set_size, local_set_size) + c,其中建议 c=1 以避免空草图、降低低估的开销。系数 q 反映两集合的差异程度,应按上一轮与该对等节点的实际差集反推最优值,并随每次对账请求发送,以便未来兼容更复杂的取值方式。
五、谁必须动
普通持币人:无直接操作。节点软件实现后,受益的是带宽占用与网络整体连接度。
全节点与矿工:本篇的行动者就是节点实现者。需要实现短 ID 与草图、五种新消息、对账集与快照等本地状态,并正确处理协商顺序与兜底泛洪。原文给出的参考实现指向 Bitcoin Core 的相关合并请求。
钱包开发者:不涉及。钱包不直接参与节点间对账。
共识层:不涉及。这是 P2P 协议扩展,只在双方协商支持时启用;旧客户端按原有协议完全互通,不受影响。
六、现在算不算数,以及一个常见误读
状态为 Draft(草案)。它定义的是一个可供 Erlay 等高层协议调用的对账原语,尚处草案阶段;原文没有声称它已成为全网默认的交易公告方式,本页也不臆测实际部署范围。
常见误读:
“BIP-330 就是 Erlay,上了它 INV 泛洪就废除了。”
不对。原文说得很清楚:本篇是对账这一“积木块”的 P2P 扩展,Erlay 是使用它的高层协议的例子;而即便在 Erlay 里,泛洪也仍然保留——只用在需要快速中继的少数连接上,对账负责把其余连接补齐同步。对账解码失败时,兜底动作同样是回到用 inv 公告全部交易。
七、延伸
- 阅读版:https://bips.dev/330
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0330.mediawiki
- 相关:BIP-339 基于 WTXID 的交易中继、BIP-340 Schnorr 签名(TaggedHash 定义)
- 仓库总目录:https://github.com/bitcoin/bips
