本文作者: yaning-u2
閃電網絡主要解決了比特幣的可擴展性問題,閃電網絡可以分爲兩部分:雙向支付通道和通道間支付,本文主要介紹如何在 CKB 上實現雙向支付通道。
雙向通道的主要分爲以下幾個流程:通道建立、餘額更新、通道關閉。
其中交易包括以下幾種:
- Funding Transaction,用於通道建立。
- Commit Transaction,用於更新餘額。
- Exercise Settlement Transaction,用於關閉交易通道。
通道建立
通道建立是通過在鏈上廣播 Funding Transaction 完成,Funding Transaction 是一個 2-2 的簽名交易,爲了方便我們將參與雙方命名爲 Alice 和 Bob。通道建立的步驟如下:
- 新建 Funding Transaction
- 新建 Commit Transaction
- 各自對 Commit Transaction 簽名
- 交換 Commit Transaction 簽名
- 各自對 Funding Transaction 簽名
- 交換 Funding Transaction 簽名
- 到鏈上廣播 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 的多籤合約。
合約代碼如下:
https://github.com/u2/lightni...
我們可以看到 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中即可:
https://github.com/nervosnetw...
由於交易hash不包括用戶解鎖參數,
https://github.com/nervosnetw...
這樣就可以是交易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 具體的流程如下:
- 對於 Alice,其創建新的 Commitment Transaction 結構爲,Output-0 爲 400,花費條件爲 Alice 需要在 10 個高度可以花費或者擁有 Alice2(Alice2 的新私鑰)+ Bob 的簽名可以立即花費。Output-1爲 200,需要 Bob 的簽名可以立刻花費。
- 雙方交換籤名。
通過這種機制,可以構造一種交易,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 值:
https://github.com/nervosnetw...
所以可以在不增加任何指令的情況下實現相對時間鎖的作用。
例如代碼
https://github.com/u2/lightni...
表示取出 Input 中的 since,並判斷其是否是使用相對塊高度,且必須在相對塊高度大於 10 是才驗證通過。這裏保證了交易 Input 在當前條件下,只有在 10 個高度以後,才能被消費。
我們現在回到罰沒機制上來,在上面的基礎上,又加入了 Breach Remedy Transaction 機制,用來防止 Alice 或者 Bob 發送歷史交易到鏈上。這樣從建立通道到更新餘額的完整流程爲:
- Alice & Bob 構造完成各自的First commitment Transaction(1a,1b),結構如上所示
- 廣播 Funding Transaction 到鏈上。
- Alice & Bob 更新餘額,構造各自新的 commitment transaction (2a, 2b),並交換籤名
- 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/lightni...
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/nervosnetw...
閃電網絡白皮書:https://lightning.network/lig...