支付通道网络(Payment Channel Network, PCN),是由支付通道构建起来的网络,是 Layer-2 扩容解决方案的一种类型。支付通道指的是链(Layer-1)上的两个用户 P_A 和 P_B 之间建立起链下沟通的通道,该通道的建立是基于链上的脚本或者合约的。双方在互相支付的过程中只需要在连下各自本地更新最新状态,关闭通道时再同步到链上即可。双方状态不一致的情况可在争议解决(Dispute)阶段解决,具体细节请自行 Google。
PCN 则是为了解决大规模使用场景,如果只使用两方支付通道,为了保证两两之间可达,那么 100 个用户之间将会建立 9900 个支付通道,这样的开销可以通过路由来大幅缩减。假设用户 P_A 和 P_B 之间, P_B 和 P_C 之间已经建立有支付通道,在 PCN 下, P_A 和 P_C 之间不需要建立通道,只需要以 P_B 为跳转进行支付,这意味着 P_A 需要先把钱打给 P_B , P_B 再把钱打给 P_C 。为了防止 P_B 从中作梗贪掉了这笔钱,我们需要一种机制保证这种多跳(Multi-Hop)支付的原子性(要么都成功,要么都失败,不会出现一个通道成功了但另外一个没有成功),这个机制被称为哈希时间锁合约(Hash Time Lock Contract, HTLC),具体细节请自行 Google。
但是 P_B 并没有任何动力去做这件事,因此我们需要引入手续费。假设手续费为 1 CKB,如果 P_A 想给 P_C 转 10 CKB,那么需要先给 P_B 一个 \mathsf{HTLC}(P_A, P_B, H(s), 11, 2t) ,其中 H(\cdot) 为抗碰撞哈希函数, s 为一个只有 A 知道的随机数, t 是一个单位时间。也就是说, 2t 之前, P_B 可以提供 s^\prime ,如果 H(s^\prime) = H(s) , P_B 获得 P_A 支付的 11 CKB;否则, 2t 之后 P_A 可以取回他的 11 CKB。然后 P_B 向 P_C 提供 \mathsf{HTLC}(P_B, P_C, H(s), 10, t) (注意这里不再是 2t ,至于为什么,请自行 Google)。这样, P_B 就收取了 1 CKB 的佣金。因此,我们通常会有下面这样的多跳 PCN:
图 1*:Alice 向 Edward 支付 10 CKB
*Malavolta, Giulio, et al. “Anonymous multi-hop locks for blockchain scalability and interoperability.” Network and Distributed System Security Symposium (NDSS) . 2019.
可以看到,黑色虚线按照数字标号执行(第一步原图有笔误,应该是 y := H(R) )之后,绿色虚线由右至左依次执行,代表正常流程。当遭遇恶意节点 Bob 和 Dave 之后,绿色虚线变为红色虚线。Edward 将 R 提供给 Dave,获得了 Dave 的 10 CKB,Dave 为了 1 CKB 的收益,理应向 Carol 揭示 R (Carol 还不知道 R ,这是因为 PCN 中不存在广播这样的操作),但是他可以和 Bob 合谋,直接跳过 Carol 把 R 交给 Bob,Bob 可以把 R 给 Alice 然后获得 13 CKB。Dave 由于没有按时向 Carol 揭示 R ,因此 Dave 无法获得 Carol 的 11 CKB。在 Carol 的视角里,她还以为可能是因为 Edward 离线了或者 Dave 钱不够了所以才会超时,她并不会意识到这是攻击。这样,总共算下来,Bob 和 Dave 合谋赚取了 3 CKB,可是他们本应只赚取 2 CKB,他们从中盗取了 Carol 应得的佣金。事实上,合谋的两个节点之间有多少个受害人,他们就能多攫取多少倍的佣金。这样的攻击对很多 PCN 成立,包括闪电网络。同时,在一些比较成熟的网络譬如 Ripple 中,多跳支付是比较常见的,使得这样的攻击的发动条件不是那么难以达成。这样的攻击被叫做虫洞攻击(Wormhole Attack)。
更多细节请参考 NDSS’19 的一篇论文 Anonymous multi-hop locks for blockchain scalability and interoperability。