作者:Vlad Stan

来源:https://motorina0.medium.com/updating-the-balance-of-a-payment-channel-944a713a8408

在本文中,我们会深入地探究,闪电网络通道是如何做到既能更新余额、又无需任何一方承担资金丢失风险的。

闪电网络是一个对抗性的网络,参与者们并不信任自己的对手。实际上,他们的 假设 是对方如有可能就会欺诈他们。参与者只有在知晓其操作的安全性时才会签名。而且,需要保证任何时候参与者都有拿着资金退出合约(离开通道)的选择。

在这篇文章中,我们假设支付通道已经开好了,当前的 Alice 有 0.10 BTC 的通道余额,Bob 只有 0.00 BTC 的余额。

承诺事务

在支付通道打开之后,Alice 希望给 Bob 支付 0.02 BTC。双方之间的支付是使用一种特殊类型的交易来达成的,它叫做 “承诺事务(commitment transactions)”。

这种事务的特殊之处在于:

  • 它是可以撤销的,如果双方都同意的话
  • 总是花费充值交易的那个 2-2 多签名输出

承诺事务的初衷是放在支付通道里使用,而不是放到主链上,不过,它们是完全有效的比特币交易,任何一方,只要想的话,都可以将它广播到主链上。

img

- 一个支付通道内部的多笔承诺事务 -

为了给 Bob 支付,Alice 必须创建两笔交易,两笔都会给 Bob 支付 0.02 BTC,但这两笔交易的输出有不同的花费条件。下文我们会管这两笔交易叫 “先给自己支付” 交易和 “先给对方支付” 交易。记住,两笔交易都由 Alice 来创建,无需使用来自 Bob 的输入。在 Bob 发送 accept_channel 消息时,Alice 就已经获得了所有的信息。

“先给自己支付”

在 “先给自己支付” 交易中,Alice 可以立即花用自己的输出,而 Bob 必须遵守 RSM 合约。RSM 合约(Revocable Sequence Maturity Contract,可撤销的相对时间锁合约)对输出的花费作了以下限制:

  • 资金的受益者只能在一段时间的 “成熟期” 之后花费这些资金(不能立即花费)
  • 合约可以(被受益者)撤销
  • 如果受益者已经撤销了这个合约,但仍尝试花费这些资金,则有可能遭遇惩罚(丧失所有资金)

更多关于 RSM 合约的细节可见此处

这笔交易对 Alice 更有利,你可以在这里看到这种交易的一个例子。

img

- Alice 创建的 “先给自己支付” 的交易 -

“先给对方支付”

在 “先给对方支付” 交易中,Bob 可以立即花费属于他的输出,但 Alice 受到 RSM Contract 的约束。这种交易对 Bob 更有好处。你可以在这里看到这种交易的一个例子。

The Pay-Other-First transaction created by Alice

- Alice 创建的 “先给对方支付” 的交易 -

注意:交易的输出按数额大小的升序排列

Alice 只会给 Bob 发送 “先给自己(Alice)支付” 交易的签名,但不会给 Bob 提供 “先给对方支付” 交易的签名。

Alice 会给 “先给对方支付” 交易签名的唯一可能性,就是她自己想把这笔交易广播到比特币网络中(而不是发送给 Bob)。

img

“给对方支付” 交易的两个输出也叫 “to_local(发给本地)”(即发回给 Alice 的) 和 “to_remote(发给远端)”(即发给 Bob 的)。

类似地,Bob 也会创建一笔 “先给自己支付” 交易和一笔 “先给对方支付” 交易。

通道状态更新 —— 逐步分解

现在我们来仔细看看在 Alice 要通过闪电网络支付通道给 Bob 支付 0.02 BTC 时,整个过程是什么样的。

下面就是 Alice 和 Bob 把余额状态从(Alice:0.10 BTC,Bob:0.0 BTC)转变成(Alice:0.08 BTC,Bob:0.02 BTC)的步骤。

由发起支付的一方先启动整个流程,在我们这个案例中就是 Alice。

Alice 构建和签名

Alice builds and signs her Pay-Me-First transaction

- Alice 创建和签名她的 “先给自己支付” 交易 -

  1. BuildPayMeFirstTx( alice) —— Alice 构建一笔交易,不加任何限制地给自己支付 0.08 BTC、同时使用 RSM 合约 给 Bob 支付 0.02 BTC。我们将这笔交易命名为 payAliceFirstTx

  2. Sign(payAliceFirstTx) —— Alice 签名 payAliceFirstTx 并创建一个相应的签名,我们把这个签名命名为 payAliceFirstSignature

  3. Send(payAliceFirstSignature) —— Alice 发送 payAliceFirstSignature 给 Bob。发送这个签名不会带来任何风险。最坏的情形也只是 Bob 会广播 payAliceFirstTx并关闭这个通道,这对 Alice 来说也没啥问题,因为她立即就能花费自己的输出,而 Bob 还必须等待。

    在广播 payAliceFirstTx 的同时,Bob 也暴露了他从 Alice 处收到了 0.02 BTC 的事实。如果 Bob 并不把 payAliceFirstTx 广播出去,只是没有响应,那么 Alice 可以安全地把前一笔承诺事务广播(表示状态 01)(译者注:即通道原来的余额状态)出去,在那个状态中她拥有更多的余额,而且因为她还没有撤销那笔承诺交易,也没有被惩罚的风险。(译者注:如此操作即是不给 Bob 支付,以当前的状态退出合约)

Bob 检查和撤销

Bob checks the signature from Alice and revokes the previous state

  1. Receive(payAliceFirstSignature) —— Bob 收到了 payAliceFirstSignature 消息。注意,Alice 只发送了签名,没有发送完整的交易,因为 Bob 可以自己重构出完全相同的交易。

  2. BuildPayOtherFirstTx(alice) —— Bob 构建了使用 RSM Contract 给自己支付 0.02 BTC 以及不加限制给 Alice 支付 0.08 BTC 的交易。对 Bob 来说,这是 “先给对方支付” 交易,它跟 Alice 构建的 payAliceFirstTx 其实一模一样。

  3. CheckSignature(payOtherFirstTx, payAliceFirstSignature) —— Bob 检查从 Alice 处收到的签名( payAliceFirstSignature )对他刚刚构建的交易(也即 payAliceFirstTx)确实有效。如果来自 Alice 的签名是有效的,那就意味着 Bob 收到了一笔有效的承诺事务(表示状态 02)。他可以继续使用通道,也可以加上自己的签名并广播出去,从而关闭通道。

  4. Store(payAliceFirstSignature) —— Bob 将签名和让他能够重构 payAliceFirstTx 的数据一起持久化保存。如果 Alice 离线没有响应,Bob 可能会用上这些数据。

  5. BuildRevokeCommitmentMsg() —— Bob 不需要存储更旧的状态(因为在更旧的状态中他的余额更少)所以他希望让状态 02payAliceFirstTx )变成当前的状态,并撤销(作废)旧的状态(状态 01)。他构建了一条 revokeMessage 来作废状态 01

  6. Send(revokeMessage) —— Bob 发送 revokeMessage 给 Alice,这对他来说没有风险,因为他作废的是旧的状态(状态 01)。最糟糕的情况是 Alice 变得没有响应,而 Bob 不得不广播 payAliceFirstTx 交易。

    通过作废旧的状态(状态 01),Bob 向 Alice 保证了做接下来的操作是没有问题的。

Alice receives the revocation message for State01

- Alice 收到了状态 01 的作废消息 -

  1. ReceiveRevokeMsg(revokeMessage) —— Alice 收到了来自 Bob 的撤销消息。Alice 现在有了惩罚 Bob 的能力,如果 Bob 把旧的承诺事务(代表状态 01)广播出去的话。

    她尚未作废自己的当前状态,因为她还没有收到 Bob 对状态 02 的签名。

Bob 构建和签名

Bob builds and signs the Pay-Me-First transaction

- Bob 构建和签名 “先给自己支付” 交易 -

  1. BuildPayMeFirstTx(bob) —— Bob 不会签名 payAliceFirstTx 交易并发送给 Alice,这笔交易对他是不利的,因为他必须遵守 RSM 合约但 Alice 可以立即把属于自己的钱拿走。更重要的是,如果签名了这笔交易,他就没有了惩罚 Alice 的能力,即使 Alice 在未来趁着 payAliceFirstTx 对自己有利(余额更多)的时候把它广播出去,Bob 也无能为力。因此,Bob 构建了一笔不设任何限制给自己支付,但使用 RSM 合约来给 Alice 支付的交易。这笔交易我们叫 payBobFirstTx 交易。
  2. Sign(payBobFirstTx) —— Bob 创建 payBobFirstTx 交易的签名,即 payBobFirstSignature
  3. Send(payBobFirstSignature) —— Bob 把 payBobFirstSignature消息发送给 Alice。

Alice 检查和作废

img

  1. Receive(signatureBob) —— Alice 收到 payBobFirstSignature 消息。注意 Bob 只需发送签名,无需发送完整的交易,因为 Alice 可以重构出完全相同的交易。
  2. BuildPayOtherFirstTx(bob) —— Alice 构建出使用 RSM 合约给自己支付 0.08 BTC、不设限制给 Bob 支付 0.02 BTC 的交易。对 Alice 来说,这是 “先给对方支付” 交易,它跟 Bob 构建的 payBobFirstTx 其实一模一样。
  3. CheckSignature(payOtherFirstTx, signatureBob) —— Alice 检查从 Bob 处收到的签名( payBobFirstSignature )对她刚刚构建的交易(也即 payBobFirstTx)确实有效。如果来自 Bob 的签名是有效的,那就意味着 Alice 收到了一笔有效的承诺事务(表示状态 02)。她可以继续使用通道,也可以加上自己的签名并广播出去,从而关闭通道。如果 Alice 选择广播出这笔交易,Bob 可以立即拿走属于自己的资金,而她只能等待 RSM 合约过时。
  4. Store(signatureBob) —— Alice 将签名和让她能够重构 payBobFirstTx 的数据一起持久化保存。如果 Bob 离线没有响应,Alice 可能会用上这些数据。
  5. BuildRevokeCommitmentMsg() —— Alice 构建 revokeMessage,如果她尝试广播旧状态(状态 01,也就是她还有 0.10 BTC 的状态),她就会受到惩罚。
  6. Send(revokeMessage) —— Alice 发送 revokeMessage 给 Bob。她现在可以认为支付已经完成了,支付通道的状态已经更新成状态 02 了。

img

  1. Receive(revokeMessage) —— Bob 收到来自 Alice 的 revocationMessage。现在他可以认为支付已经完成了,支付通道的状态已经更新成状态 02 了。

(完)