8

L2 - zkSync源代码导读

 3 years ago
source link: https://learnblockchain.cn/article/1642
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

zkSync通过zk Rollup协议,实现了L2的转账。zkSync项目非常完整,是学习L2非常好的参考项目。zkSync采用Plonk零知识证明算法向L1证明状态的正确性。Plonk算法是Universal的零知识证明算法,只需要一次可信设置。zkSync电路设计采用Chunk设计,支持不同的区块大小。

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 aab5608c3
Author: 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 bugfix

1 源代码目录结构

zkSync项目实现了L2相关的方方面面。查看zkSync的提交记录,这个项目创建于2018年的11月份,已经有两年的开发时间。从matter labs公开的各种项目,matter labs在zk rollup想的很远,也已经走的蛮远。细想想,踏踏实实地思考区块链技术,认认真真地把一小点积累做好。整个源代码目录结构如下:

uMRzauB.jpg!mobile

bin - 一些二进制程序和脚步

contracts - 智能合约逻辑

core - L2的核心逻辑

docker - docker相关的配置

docs - 文档,比较详细的解释了zkSync的协议设计,电路实现,智能合约,K8如何配置,以及如何启动等等。

etc - 配置信息

js - zkSync客户端以及浏览器(explorer)

zkSync的内容比较多,这篇文章主要给大家讲讲zkSync的大体逻辑结构,重点介绍智能合约以及core的相关逻辑。所有zkSync的核心逻辑都实现在core的目录下:

7BJ7feV.jpg!mobile

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总体的功能模块以及相互之间的关系如下:

A3qmQvB.jpg!mobile

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账户一一对应,“共享”一份私钥。

32m2am7.jpg!mobile

简单的说,L1的私钥的ECDSA签名的结果作为L2账户的私钥。L2账户的秘钥是JubJub曲线上的Scalar值,对应的公钥是对应椭圆曲线上的点。L2的状态包括两部分:账户以及账户下所有Token的余额。

MFVfay.jpg!mobile

账户以及支持的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账户的公钥信息):

NzANJzr.jpg!mobile

每个Token也都有唯一编号。Token节点包括如下信息:

f6jUrmi.jpg!mobile

zkSync支持的Token信息由L1智能合约维护,具体逻辑可以查看contracts/contracts/Governance.sol的addToken函数。

4 交易类型和区块

zkSync目前支持如下交易类型(操作类型):

  1. Noop - 空操作(L2)

  2. Transfer - 转账(L2)

  3. Transfer to new - 转账给新账户(L2)

  4. Withdraw (Partial Exit)- 转出资金(L2)

  5. Deposit -转入资金(L1)

  6. Change pubkey - 更改L2的公钥信息(L2)

  7. Full exit - 退出,从Layer1发起的交易,退出L2(L1)

  8. close操作 - 退出,从Layer2发起的交易(新版本已经废除,L2)

L2的区块信息相对简单,总体的结构如下:

6Jnumy.jpg!mobile

L2的区块信息包括:新的世界状态的树根(new root hash),区块交易费用接收账户以及多个交易信息。交易信息分为两种:一种是L2的交易,从L2的角度看,这些才是“正常”交易(transaction);另外一种是从L1发起的交易(Deposit以及Full exit)。

从L1发起的交易,在代码中常常被标记为"Priority"交易。相对来说,从L1发起的交易,相对L2的交易优先级确实更高一些。

以Deposit交易为例,介绍一下L2账户创建的流程:

yQZjuiM.jpg!mobile

在L2创建账户,其实涉及到两个交易类型。Deposit是L1的Priority的交易。在Eth Watch监测到交易后,发起L2的交易,并在世界状态添加状态。在账户创建后,再通过Change pubkey更新L2的公钥信息。

5 基本流程

在明确了账户系统以及状态后,整个L2的打包以及更改世界状态的流程还是比较清晰的:

UFJb22u.jpg!mobile

一切从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零知识证明的算法,和Groth16算法不一样,是Universal的零知识算法。Plonk算法的技术细节后面会单独写文章详细介绍。zkSync设计了相对独立的Plonk证明系统,示意如下:

Q3qEVj.jpg!mobile

Plonk证明系统涉及到三个功能模块:Block Committer,Prover Server以及Prover。这三个模块之间的数据传输通过Storage存储模块。Block Committer将Block信息存入Storage,Prover Server从Storage提取Block并生成证明需要的信息,并再次存入Storage,Prover从存储中查看需要证明的信息,生成零知识证明。

Prover Server和Prover之间的调用关系,示意如下:

f6fUrif.jpg!mobile

详细逻辑可以查看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的操作才是确定性状态。从状态的角度看,交易的流程如下图所示:

aa2I7v3.jpg!mobile

某个交易在打包后,会将交易对应的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设计,支持不同的区块大小。

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 aab5608c3
Author: 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 bugfix

1 源代码目录结构

zkSync项目实现了L2相关的方方面面。查看zkSync的提交记录,这个项目创建于2018年的11月份,已经有两年的开发时间。从matter labs公开的各种项目,matter labs在zk rollup想的很远,也已经走的蛮远。细想想,踏踏实实地思考区块链技术,认认真真地把一小点积累做好。整个源代码目录结构如下:

uMRzauB.jpg!mobile

bin - 一些二进制程序和脚步

contracts - 智能合约逻辑

core - L2的核心逻辑

docker - docker相关的配置

docs - 文档,比较详细的解释了zkSync的协议设计,电路实现,智能合约,K8如何配置,以及如何启动等等。

etc - 配置信息

js - zkSync客户端以及浏览器(explorer)

zkSync的内容比较多,这篇文章主要给大家讲讲zkSync的大体逻辑结构,重点介绍智能合约以及core的相关逻辑。所有zkSync的核心逻辑都实现在core的目录下:

7BJ7feV.jpg!mobile

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总体的功能模块以及相互之间的关系如下:

A3qmQvB.jpg!mobile

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账户一一对应,“共享”一份私钥。

32m2am7.jpg!mobile

简单的说,L1的私钥的ECDSA签名的结果作为L2账户的私钥。L2账户的秘钥是JubJub曲线上的Scalar值,对应的公钥是对应椭圆曲线上的点。L2的状态包括两部分:账户以及账户下所有Token的余额。

MFVfay.jpg!mobile

账户以及支持的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账户的公钥信息):

NzANJzr.jpg!mobile

每个Token也都有唯一编号。Token节点包括如下信息:

f6jUrmi.jpg!mobile

zkSync支持的Token信息由L1智能合约维护,具体逻辑可以查看contracts/contracts/Governance.sol的addToken函数。

4 交易类型和区块

zkSync目前支持如下交易类型(操作类型):

  1. Noop - 空操作(L2)

  2. Transfer - 转账(L2)

  3. Transfer to new - 转账给新账户(L2)

  4. Withdraw (Partial Exit)- 转出资金(L2)

  5. Deposit -转入资金(L1)

  6. Change pubkey - 更改L2的公钥信息(L2)

  7. Full exit - 退出,从Layer1发起的交易,退出L2(L1)

  8. close操作 - 退出,从Layer2发起的交易(新版本已经废除,L2)

L2的区块信息相对简单,总体的结构如下:

6Jnumy.jpg!mobile

L2的区块信息包括:新的世界状态的树根(new root hash),区块交易费用接收账户以及多个交易信息。交易信息分为两种:一种是L2的交易,从L2的角度看,这些才是“正常”交易(transaction);另外一种是从L1发起的交易(Deposit以及Full exit)。

从L1发起的交易,在代码中常常被标记为"Priority"交易。相对来说,从L1发起的交易,相对L2的交易优先级确实更高一些。

以Deposit交易为例,介绍一下L2账户创建的流程:

yQZjuiM.jpg!mobile

在L2创建账户,其实涉及到两个交易类型。Deposit是L1的Priority的交易。在Eth Watch监测到交易后,发起L2的交易,并在世界状态添加状态。在账户创建后,再通过Change pubkey更新L2的公钥信息。

5 基本流程

在明确了账户系统以及状态后,整个L2的打包以及更改世界状态的流程还是比较清晰的:

UFJb22u.jpg!mobile

一切从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零知识证明的算法,和Groth16算法不一样,是Universal的零知识算法。Plonk算法的技术细节后面会单独写文章详细介绍。zkSync设计了相对独立的Plonk证明系统,示意如下:

Q3qEVj.jpg!mobile

Plonk证明系统涉及到三个功能模块:Block Committer,Prover Server以及Prover。这三个模块之间的数据传输通过Storage存储模块。Block Committer将Block信息存入Storage,Prover Server从Storage提取Block并生成证明需要的信息,并再次存入Storage,Prover从存储中查看需要证明的信息,生成零知识证明。

Prover Server和Prover之间的调用关系,示意如下:

f6fUrif.jpg!mobile

详细逻辑可以查看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的操作才是确定性状态。从状态的角度看,交易的流程如下图所示:

aa2I7v3.jpg!mobile

某个交易在打包后,会将交易对应的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设计,支持不同的区块大小。

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2分钟前
  • 阅读 ( 3 )
  • 学分 ( 0 )
  • 分类:Rollup

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK