在本文中,我们介绍了一种叫作虚拟通道(virtual channel)的新型状态通道结构。虚拟通道不仅使得付费文件流(点击此处,查看 demo!)等新型应用场景成为可能,还可以简化去中心化的 Graph 查询支付、Filecoin 内容检索、带有经济激励机制的状态提供者网络等有趣的应用场景。
动机
让我们来设计一个免信任的付费文件流支付系统。这个系统中有 seeder(上传文件者)和 leecher(下载文件者)。leecher 从多个 seeder 那里付费下载一份文件的不同部分。使用
通过虚拟通道连接各方
总的来说,只要 Alice和Bob之间有经过中间方的路径,无论网络拓扑结构是什么样的,虚拟通道都可以让 Alice 开设与 Bob之间的私密通道。
背景知识
上图显示了 Alice 和 Bob 是如何根据 这一结果从通道 C 中取走代币的。根据链上裁决者的记录,通道中共有 10 枚代币。Alice 或 Bob 将通道结果记录到链上。这个结果记录下来后,Alice 和 Bob 就可以取走代币。于是,Alice 的外部账户中增加了 7 枚代币,Bob 的外部账户增加了 3 枚代币。
虽然上述结果暗示目标是用户账户(EOA),但是在 Nitro 中,通道本身也可以是目标。这样一来,通道 L 也可以充当 “私密账本”,因为 Nitro 可以让一次性一次性将资金存入账本通道,然后为多条子通道提供资金。Nitro 避免了回到 Layer1 的需求,以及由此产生的延迟和成本!例如:
假设 C2
是一条 Nitro 通道, 命令裁决者向 Alice 支付 4 枚代币,再向 Bob 支付 1 枚代币,然后将
C2
的代币持有量增加 5 。
C1 是账本通道,C2 是从账本通道获取资金的通道
以上是一个简短的介绍。如果你想要深入了解Nitro,请查看我们的相关博客文章!
如何利用保证来实现免信任架构
接下来,我们将介绍当两位参与者没有链上关系时,如何通过一个安全的架构来创建三方通道。这个架构不仅能让账本通道为其它通道提供资金,还能实现虚拟通道。两位参与者分别是 Alice(A)和 Bob(B),中间方是 Irene(I)。
我们首次尝试使用一个通道来连接 A、B 和 I。请注意,这不是免信任型架构。
初始设置:三条独立通道。
首先要有一对账本通道 L
(位于 Alice 和 Irene 之间)和 L'
(位于 Bob和 Irene之间)。通常情况下,L
和 L'
是早就创建好的。这是因为 Irene 存在的目的就是在人们之间建立连接 —— Alice 可以使用 L 来同时连接 Bob、Cheryl、David 和 Eve。如果 L
和 L'
不存在,L
可以使用结果 创建,
L'
可以使用结果 创建。
L
和 L'
各自在链上存储10枚代币。
另外还有一条独立通道 J
是使用结果 创建的。请注意,在向通道存入资金之前,参与者必须先就这一结果达成共识。一旦
J
有了资金之后,这条通道就可以用来为 Alice 和 Bob 之间创建的任意一条私密应用通道提供资金。
步骤 1 和 2:账本通道转变为向 J
提供资金。
Alice 和 Irene 将 L
的结果转变为 。Bob 和 Irene 将
L'
的结果转换成 。
这个设计够好了吗?
Alice 必须考虑以下几点:
Bob 和 Irene 是不是可信的?
Alice 无法控制 L'
上发生的事。
我们来思考一下步骤 2 之后如何取走 J
的资金。
L
和 L'
的结果被记录到链上。
L
和 L'
的资金都被转移到 J
。代币经由转账操作从一条通道转移到另一条通道。J
现在有了 20 枚代币,可谓资金充足。
Alice 可以从 J
中取走 4 枚代币,Bob 可以从 J
中取走 6 枚代币。Irene 可以从 J
中取走 10 枚代币。
漂亮!现在每个人都取走了自己应得的代币。但是,我们来设想一个场景:Alice 和 Bob 串谋起来欺骗 Irene。假设步骤 1 发生后,Bob 拒绝参与步骤 2。然后就会发生以下情况:
L
的结果被记录在链上。现在,J
有了10 个代币,记录在链上的结果是 。
Alice 和 Bob 分别取走 4 枚和 6 枚代币。
请注意,Bob 从 J
那里获得了 6 枚代币,尽管他自己根本没有向 J
转过代币。结果变成了:Alice 获得了 4 枚代币,Bob 获得了 6 枚代币,Irene 什么也没有。Irene 被坑惨了!
你可能会想,如果调换一下结果 中目标的顺序,就可以创建出一个安全的架构。然而,无论怎么调换顺序,总会有人蒙受损失!
保证是如何发挥作用的
在上述场景中,我们使用了转账操作在通道之间转移资金。通过转账操作,资金可以从一个通道转移到目标通道。在本小节中,我们将引入索取(claim)操作来将资金从目标通道转移至特定的目标地址1。为了实现索取操作,我们需要保证。
我们先来介绍一个新的数据结构。保证是指定以下的结果:
目标,即,一条通道;
数量;
优先级,即,目标的优先级列表。优先级的作用是指示裁决者如何改变目标通道的结果项的优先级。
我们第二次尝试使用一个通道来连接 A、B和 I。这次已经是免信任架构了
我们来看一下 J
是如何获得资金的:
初始设置:创建三个独立的通道。
通道 J
是使用结果 创建的。
L
是使用结果 创建的。
L'
是使用结果 创建的。
步骤 1 和 2:账本通道转变为向 J
提供资金(没有先后顺序之分):
L
的结果更新为 。请注意,我们使用了一种新的符号来表明
L
的结果只有一项,即,包含目标 J
、数量和地址优先级列表的保证。
L'
的结果是 。
L
和 L'
的结果各自包含一个保证。由于转账操作不支持这些保证,我们代之以索取操作。索取操作接受保证以及保证的目标通道作为输入。
我们来看一下索取操作是如何运作的。假设
J
的结果 被记录到了链上。
L
的结果 }
被记录到了链上。
如果有人请求执行 L
的结果中的保证,则会触发三个效果:
将 4 枚代币发送给 A
,6枚代币发送给 I
。
因为(1),A
和 I
的余额在 J
的结果中被调整为 。
L
的结果被调整为 {}
—— 保证被删除。
在这个操作中,优先级的目的是告诉裁决者跳过 带有 B
的结果项,这样 Irene 就可以拿回她在创建 L
时出的那部分资金。因此,裁决者会先看到保证中优先级最高的目标 A
,并将 4 枚代币转给 A
,J
的结果会相应更新。然后,裁决者才会看到目标 I
。在 J
的结果中,Irene 应该获得 10 枚代币,但这时(L 的结果中)只剩下 6 枚代币。因此,这 6 枚代币被发送给了 Irene,J
的结果再次更新。请注意,优先级一定要是 [A, I]
而非 [I, A]
。如果优先级是 [I, A]
,Irene 就会通过索取操作获得 10 枚代币,Alice 就失去了原本属于她的 4 枚代币!
有了索取操作,Alice 和 Bob 再也不能串谋起来骗取 Irene 的资金了。
?最理想的情况
你可能已经注意到了,为了让 Alice 他们取回资金,总共需要 3 个链上操作:将联合通道和转账结果记录到链上,并调用索取 操作。请注意,这是最糟糕的情况。假设 Bob 将 4 枚代币转给 Alice 后,Alice 和 Bob 想要关闭 J
。如果 Bob 和 Irene 配合的话,则:
Alice、Bob 和 Irene 同意以结果 敲定
J
。
Alice 和 Irene 可以更新 L
,安全地删除为 J
提供资金的保证。L
的结果变成了 。
现在,Alice 可以使用 L
里的代币为其它通道提供资金了。Alice 也可以选择取走资金。
总而言之,在协作式案例中,Alice 可以使用 L
内的资金为多条不同的应用通道提供资金,也可以从这些取走资金,无需进行任何链上交易。
虚拟通道
在上一节中,我们已经介绍了如何在两个参与方不存在链上关系的情况下创建三方通道。细心的读者应该注意到了,更新 J
必须经过中间方签字。在本文的开头,我们打算在 A
和 B
之间创建一条私密通道。幸运的是,Nitro 的可组合性让我们可以创建一条由 J
提供资金的私密应用通道 X
。具体架构如下图所示。你已经掌握理解这个架构所需的一切概念了。不过,如果你有任何问题,欢迎向我们提问!
X 是一条虚拟通道
未来计划
本文介绍的虚拟通道架构是 Nitro 协议论文中介绍的架构的进化版。最值得一提的是,这个架构不需要创建专门的保证者通道。
Nitro 虚拟通道即将引入另一个更新,免去对联合通道的需求。有了这个更新,账本通道 L
和 L'
就可以为应用通道 X
提供资金。
本文由 Mike Kerzhner 和 Andrew Stewart 基于 Tom Close 所著论文《Nitro 协议》撰写,感谢 Robert Drost、Joseph Chow、George Knee 和 Colin Kennedy 的反馈。
注
我们还可以将索取操作理解成:
将资金从 L 转入 J,改变 J 的结果。
将资金从 J 转入目标地址。
如果账本通道的结果是 且
J
的结果是 ,索取 可以描述成:
将 10枚代币从 L
转入 J
。
J
的结果变成
然后在 J
上调用面向 A
和 I
的转账。