Layer2 - zkSync原始碼導讀

買賣虛擬貨幣
Layer2是一個大方向。最近一段時間,會圍繞L2寫一些文章。區塊鏈技術有趣的地方就是一種技術的發展開啟了一扇窗。零知識證明的發展拓寬了區塊鏈L2的視角,提供了L2的另外一種實現可能,即zk Rollup。從另外一個角度看,區塊鏈的進步是緩慢的,需要很多優秀的人才跨界把不同的技術揉雜在一起,讓不可能成為可能。matter labs在zk Rollup方向的積累比較深,有一系列的開源專案可以學習。讓我們從zkSync開始吧。zkSync的原始碼地址,所有的邏輯使用rust語言開發:https://github.com/matter-labs/zksync.git特別注意的是,檢視完整原始碼需要檢視dev分支,並不是master分支。master分支提供編譯後的各種執行程式。本文采用的程式碼的最後一個提交資訊如下:commit dcdddeda4d6eb1dace5ec56cf9fe091ed5e062fd
Merge: 37c5976bd aab5608c3Author: Vitaly Drogan <[email protected]>Date:   Thu Sep 17 17:07:05 2020 +0300    Merge pull request #948 from matter-labs/popzxc-minor-sdk-bugfix    Minor SDK bugfix1. 原始碼目錄結構

zkSync專案實現了L2相關的方方面面。檢視zkSync的提交記錄,這個專案建立於2018年的11月份,已經有兩年的開發時間。從matter labs公開的各種專案,matter labs在zk rollup想的很遠,也已經走的蠻遠。細想想,踏踏實實地思考區塊鏈技術,認認真真地把一小點積累做好。整個原始碼目錄結構如下:

bin - 一些二進位制程式和腳步
contracts - 智慧合約邏輯
core - L2的核心邏輯
docker - docker相關的配置
docs - 文件,比較詳細的解釋了zkSync的協議設計,電路實現,智慧合約,K8如何配置,以及如何啟動等等。
etc - 配置資訊
js - zkSync客戶端以及瀏覽器(explorer)

zkSync的內容比較多,這篇文章主要給大家講講zkSync的大體邏輯結構,重點介紹智慧合約以及core的相關邏輯。所有zkSync的核心邏輯都實現在core的目錄下:

core/circuit - 零知識證明電路實現
core/crypto_exports - 零知識證明底層庫封裝
core/data_restore - 狀態恢復的相關邏輯
core/eth_client - eth客戶端的封裝
core/loadtest - 壓力測試相關邏輯
core/models - zkSync的模型定義
core/plasma - zkSync的狀態實現
core/prover - 零知識證明的證明生成引擎
core/server - 各種server的實現,包括eth的監測(watch)和交易傳送(sender),交易費用的計算(fee_ticker),零知識證明的伺服器(prover server)以及API服務等等
core/storage - 所有狀態的儲存以及持久化邏輯

2. 整體架構

zkSync目前主要實現了L2的轉賬功能。L2有自己的賬戶系統以及狀態。zkSync總體的功能模組以及相互之間的關係如下:

Eth Watch以及Eth Sender負責監控和傳送zkSync智慧合約的交易。Mem Pool負責收集交易。交易分為兩種兩種:L1交易和L2交易。Block Proposer將交易打包,並更改世界狀態(Plasma State)。在世界狀態更改後,透過Block Committer生成證明需要的資訊。零知識的證明透過Plonk證明系統生成,其中包括Prover Server和Proving Client。API提供介面實現UI的資訊展示和L2的交易提交。

3. L2賬戶系統和世界狀態

zkSync並不需要獨立生成新賬戶。zkSync的L2賬戶和L1賬戶一一對應,“共享”一份私鑰。

簡單的說,L1的私鑰的ECDSA簽名的結果作為L2賬戶的私鑰。L2賬戶的秘鑰是JubJub曲線上的Scalar值,對應的公鑰是對應橢圓曲線上的點。L2的狀態包括兩部分:賬戶以及賬戶下所有Token的餘額。

賬戶以及支援的Token個數定義在etc/env/dev.env檔案中:

ACCOUNT_TREE_DEPTH=32
BALANCE_TREE_DEPTH=11

目前支援2^32個L2賬戶,2^11個Token。每個L2賬戶都有一個唯一的編號,從零開始。編號0,預設為Validator的賬戶。Account節點包括如下資訊(其中PubKeyHash就是L2賬戶的公鑰資訊):

每個Token也都有唯一編號。Token節點包括如下資訊:

zkSync支援的Token資訊由L1智慧合約維護,具體邏輯可以檢視contracts/contracts/Governance.sol的addToken函式。

4. 交易型別和區塊

zkSync目前支援如下交易型別(操作型別):
Noop - 空操作(L2)
Transfer - 轉賬(L2)
Transfer to new - 轉賬給新賬戶(L2)
Withdraw (Partial Exit)- 轉出資金(L2)
Deposit -轉入資金(L1)
Change pubkey - 更改L2的公鑰資訊(L2)
Full exit - 退出,從Layer1發起的交易,退出L2(L1)
close操作 - 退出,從Layer2發起的交易(新版本已經廢除,L2)

L2的區塊資訊相對簡單,總體的結構如下:

L2的區塊資訊包括:新的世界狀態的樹根(new root hash),區塊交易費用接收賬戶以及多個交易資訊。交易資訊分為兩種:一種是L2的交易,從L2的角度看,這些才是“正常”交易(transaction);另外一種是從L1發起的交易(Deposit以及Full exit)。

從L1發起的交易,在程式碼中常常被標記為"Priority"交易。相對來說,從L1發起的交易,相對L2的交易優先順序確實更高一些。

以Deposit交易為例,介紹一下L2賬戶建立的流程:

在L2建立賬戶,其實涉及到兩個交易型別。Deposit是L1的Priority的交易。在Eth Watch監測到交易後,發起L2的交易,並在世界狀態新增狀態。在賬戶建立後,再透過Change pubkey更新L2的公鑰資訊。

5. 基本流程

在明確了賬戶系統以及狀態後,整個L2的打包以及更改世界狀態的流程還是比較清晰的:

一切從NewTx開始。透過API,建立好的Transaction新增到Mem Pool。詳細邏輯可以檢視core/server/src/mempool.rs的add_tx函式。Block Proposer每隔一段時間,檢視Mem Pool中的有效交易,並打包。詳細邏輯可以檢視core/server/src/block_proposer.rs的run_block_proposer_task函式。

區塊打包成功後,更新世界狀態,詳細邏輯可以檢視core/server/src/state_keeper.rs的execute_tx_batch。

更新了世界狀態後,要將最新的世界狀態進行證明,詳細邏輯可以檢視core/server/src/committer.rs的commit_block函式。

證明透過Eth Sender傳送給L1。

6. Plonk證明系統

zkSync採用Plonk零知識證明的演算法,證明L2的交易和狀態的正確性。Plonk零知識證明的演算法,和Groth26演算法不一樣,是Universal的零知識演算法。Plonk演算法的技術細節後面會單獨寫文章詳細介紹。zkSync設計了相對獨立的Plonk證明系統,示意如下:

Plonk證明系統涉及到三個功能模組:Block Committer,Prover Server以及Prover。這三個模組之間的資料傳輸透過Storage儲存模組。Block Committer將Block資訊存入Storage,Prover Server從Storage提取Block並生成證明需要的資訊,並再次存入Storage,Prover從儲存中檢視需要證明的資訊,生成零知識證明。

Prover Server和Prover之間的呼叫關係,示意如下:

詳細邏輯可以檢視core/server/src/prover_server以及core/prover目錄。

7. zkSync電路實現

zkSync在bellman的基礎上增加了Plonk零知識證明系統。zkSync的電路設計非常有趣,由於篇幅原因,後面會單獨介紹zkSync的電路實現原理。簡單的說,zkSync採用Chunk設計,將交易切分為多個Chunk,支援不同的區塊大小。看zkSync原始碼的小夥伴,在理解電路邏輯前,先理解好Chunk的邏輯。

8. 狀態確定以及L1智慧合約

zkSync的交易可以由Layer1或者Layer2的操作發起。簡單的說,zkSync的交易經歷三個狀態:1/Request 2/ Committed 3/ Verified。只有Verified的操作才是確定性狀態。從狀態的角度看,交易的流程如下圖所示:

某個交易在打包後,會將交易對應的Pub Data資訊提交到鏈上,交易進入Committed狀態。在交易對應的區塊提交證明後,改交易進入Verified的狀態,也就是確定性狀態。

L1智慧合約提供了commitBlock和verifyBlock介面實現Pub Data資訊以及證明資訊的提交:

    function commitBlock(
        uint32 _blockNumber,
        uint32 _feeAccount,
        bytes32[] calldata _newBlockInfo,
        bytes calldata _publicData,
        bytes calldata _ethWitness,
        uint32[] calldata _ethWitnessSizes
    ) 

    function verifyBlock(uint32 _blockNumber, uint256[] calldata _proof, bytes calldata _withdrawalsData)
        external nonReentrant

具體的邏輯,感興趣的小夥伴可以檢視contracts/contracts/ZkSync.sol原始碼。

總結:

zkSync透過zk Rollup協議,實現了L2的轉賬。zkSync專案非常完整,是學習L2非常好的參考專案。zkSync採用Plonk零知識證明演算法向L1證明狀態的正確性。Plonk演算法是Universal的零知識證明演算法,只需要一次可信設定。zkSync電路設計採用Chunk設計,支援不同的區塊大小。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;