如何在CKB上实现闪电网络(一)

闪电网络主要解决了比特币的可扩展性问题,闪电网络可以分为两部分:双向支付通道和通道间支付,本文主要介绍如何在CKB上实现双向支付通道。

双向通道的主要分为以下几个流程:通道建立、余额更新、通道关闭。

其中交易包括以下几种:

  • Funding Transaction,用于通道建立。
  • Commit Transaction,用于更新余额。
  • Exercise Settlement Transaction,用于关闭交易通道。

通道建立

通道建立是通过在链上广播Funding Transaction完成,Funding Transaction是一个2-2的签名交易,为了方便我们将参与双方命名为Alice和Bob。通道建立的步骤如下:

  1. 新建Funding Transaction
  2. 新建Commit Transaction
  3. 各自对Commit Transaction签名
  4. 交换Commit Transaction签名
  5. 各自对Funding Transaction签名
  6. 交换Funding Transaction 签名
  7. 到链上广播Funding Transaction

这里为什么要首先构造出Commit Transaction呢?因为如果Alice和Bob都对Funding Transaction签名后,任何一方都可以将交易广播到链上,但是花费Funding Transaction的Output需要双方的签名,如果任何一方不合作则会导致资金永远锁在Funding Transaction中,所以这里首先先构造出可以消费Funding Transaction的First commitment Transaction再对Funding Transaction签名,这样任何一方都可以从Funding Transaction中取出自己的资金,而不需要对手方去进行配合。

举例,Alice提供一个300 ckb的Input,Bob提供一个300 ckb的Input,然后Output为600 ckb,锁定脚本为2-2的多签脚本,需要Alice和Bob的签名才能花费Output。

(闪电网络白皮书中的一张图,将就看)

由于Funding Transaction的Output是一个2-2的多签脚本锁定,所以我们可以先部署一个2-2的多签合约。

合约代码如下:

我们可以看到CKB是可以用C语言写合约的。在部署Funding Transaction之前,我们可以先部署2-2的锁定脚本,这样Funding Transaction直接引用2-2多签合约即可。这样如果在CKB中有很多双向支付通道,可以共享一个多签脚本,而不必每个支付通道单独在合约中包含多签合约,减少合约的交易手续费,降低CKB的存储空间的占用。

闪电网络实现的一个前提是,必须要解决交易延展性问题,否则交易的Hash是不确定的,可能导致Funding Transaction的资金无法解锁。比如Alice和Bob构造完成First commitment Transaction(1a, 1b)并广播Signed Funding Transaction,但是这个时候矿工修改了Signed Funding Transaction中Input的签名脚本,Funding Transaction最终上链,但是交易Hash和原来不一致。由于First commitment Transaction通过交易Hash来引用Funding Transaction,此时找不到合法的Funding Transaction,First commitment Transaction将无法被消费,如果Alice或者Bob其中的任何一方采取不合作的方式,另一方将无法取出自己的资金。

比特币通过实现隔离见证解决了交易延展性问题,CKB也实现了自己的隔离见证。在CKB中,用户只需要选择将签名等解锁参数放入交易中的witnesses中即可:

由于交易hash不包括用户解锁参数,

这样就可以是交易hash只包含Inputs和Outputs等交易处理的相关信息而不包含解锁脚本,解决交易延展性问题。

更新余额

Funding Transaction被广播到链上之后,双向支付通道就成功建立了,后续Alice和Bob就可以构造离线的Commitment Transaction来更新双方的金额了。闪电网络的每一笔Commitment Transaction交易都是建立在Funding Transaction之上的。

在构造Commitment Transaction时,需要解决以下两个问题:

  • 追责问题。因为每笔Commitment Transaction都是合法的,而且都是建立在Funding Transaction之上。Alice和Bob都各有一份不同commitment transaction,如果其中任何一方将历史commitment transaction发送到链上,可以对其进行罚没。
  • 罚没机制。如果任何一方不遵循双向通道的机制,将历史交易发送到链上,则需要能将其资金进行罚没。

追责问题。解决追责问题,需要Alice和Bob构造两个不同的交易,我们可以将这两个交易分别命名为2a,2b。假设最新的余额为Alice 400,Bob 200,commitment transaction具体的流程如下:

  1. 对于Alice,其创建新的Commitment Transaction结构为,Output-0为400,花费条件为Alice需要在10个高度可以花费或者拥有Alice2(Alice2的新私钥) + Bob的签名可以立即花费。Output-1为200,需要Bob的签名可以立刻花费。
  2. 双方交换签名。

通过这种机制,可以构造一种交易,Alice如果广播其交易a1交易,则Alice可以在10个高度之后花费Output-0,Bob可以立刻花费其Output-1。

在介绍罚没机制之前,我们先介绍下比特币中的时间锁机制。在比特币中使用nLocktime来对交易进行时间限制,使交易必须在某个绝对高度或者时间之后才可以被记录到链上,CHECKLOCKTIMEVERIFY指令可以配合nLockTime一起使用。交易Inputs中的nSequence可以用来对相对时间进行限制,是某个Input必须在Output上链一定时间后,其所在交易才可以被打包,CHECKSEQUENCEVERIFY可以配合nSequence来使用。

在CKB中使用Transaction Valid Since机制,即可以表示相对时间或者区块,也可以表示绝对值,所以可以起到Bitcoin中的nSequence和nLocktime作用,设计上更简洁。由于CKB VM可以通过syscall获取到交易Input中的since值:

所以可以在不增加任何指令的情况下实现相对时间锁的作用。

例如代码

表示取出Input中的since,并判断其是否是使用相对块高度,且必须在相对块高度大于10是才验证通过。这里保证了交易Input在当前条件下,只有在10个高度以后,才能被消费。

我们现在回到罚没机制上来,在上面的基础上,又加入了Breach Remedy Transaction机制,用来防止Alice或者Bob发送历史交易到链上。这样从建立通道到更新余额的完整流程为:

  1. Alice & Bob 构造完成各自的First commitment Transaction(1a,1b),结构如上所示

  2. 广播Funding Transaction到链上。

  3. Alice & Bob 更新余额,构造各自新的 commitment transaction (2a, 2b),并交换签名

  4. Alice & Bob 分别向对方揭示Alice2,Bob2私钥(上一个commitment transaction中所用解锁output的私钥)。

在这种情况下,因为Alice拥有Bob的Bob2私钥,而Bob拥有Alice的Alice2私钥。如果Alice广播历史交易a1,其交易Output-0可以被Alice2 + Bob的签名理解花费,或者可以被Alice在10个高度后消费。在这种情况下,因为Bob已经拥有Alice2的私钥,所以Alice没有动机去广播历史交易a1。同理对于Bob也适用。我们称这种commitment transaction为可以撤销的commitment transaction(Revocable commitment transaction)。其commitment transaction的锁定脚本可以称为 revocable maturity script,代码:https://github.com/u2/lightning/blob/master/revocable_maturity.c

Alice和Bob每次更新余额,都会构造一个新的可以撤销的commitment transaction,并向对方揭示自己上一个commitment transaction的output-0的私钥,这样自己的历史commitment transaction不需要保存,只需要保存对方揭示的私钥即可。双方都有检测链上对方是否有广播历史交易,如果对方有广播历史交易,可以使用自己的私钥和对方揭示的私钥构造Breach Remedy Transaction立即花费对方的Output,这样可以将罚没对方的资金。

(闪电网络白皮书中的图,可以将就看)

关闭通道

Alice和Bob可以选择合作构造Exercise Settlement Transaction(ES transaction)来选择关闭通道。ES transaction是没有任何时间锁的交易,这样Alice和bob可以选择直接广播交易来花费Funding transaciton。

总结

在作者第一次实现的时候,和以上方案略有不同,并没有 revocable maturity脚本,而是在构造每个commitment transaction时,双方各自事先构造好其上一个交易的Breach Remedy Transaction并互相交换签名。这种情况下,Alice 和 Bob不需要生成很多私钥,但是缺点是Alice和bob需要保留历史的Breach Remedy Transaction,因为交易比私钥更占空间,相对而言这种方案并不够合理。

在CKB中,实现了隔离见证以及灵活的时间锁机制,且用户可以通过提前部署闪电网络的相关合约,用更低成本来建立双向支付通道。对实现细节感兴趣的读者可以阅读下面项目中的代码。另外CKB中可以通过定义Type Script而实现User defined Token的闪电网络,这里不再赘述。

项目地址:https://github.com/u2/lightning

相关文章:漫谈闪电网络

比特币时间锁机制相关Bips:

CKB的时间锁机制:https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0017-tx-valid-since/0017-tx-valid-since.md

闪电网络白皮书:https://lightning.network/lightning-network-paper.pdf

7 Likes

图片都是。 微信的

已经好了,本地电脑看是正常的,可能是浏览器有缓存之类的。

这个很有意思,赞