Polygon zkEVM递归证明技术文档(3)——代码编译及运行

前序博客见:

本文重点关注如何使用 Polygon zkEVM现有代码 编译生成zkEVM proofs。

5. Building zkEVM Proofs

运行proverjs来完成setup phase。在setup phase所生成的电路可根据需要多次使用。
实际生产环境,运行的是C++版本实现的prover程序。该prover程序通过GRPC API来获取特定组合proofs的信息。

5.1 预处理和初始化

5.1.1 必备条件

为验证合约,运行机器配置要求至少为16核256GB。
本文以具有16核、32线程、512GB SSD的r6a.8xlarge AWS实例为例,运行Ubuntu 22.04 LTS操作系统,每小时成本为1.82美金。

5.1.2 配置运行环境

为支持运行验证流程,需安装tmux、git和curl:

sudo apt update
sudo apt install -y tmux git cur

需修改内核配置参数来支持大内存容量:

echo " vm.max_map_count=655300" | sudo tee -a /etc/sysctl.conf
sudo sysctl -w vm.max_map_count=655300
export NODE_OPTIONS = "--max-old-space-size=230000"

需安装Node.js 18.x版本:

curl -sL " https://deb.nodesource.com/setup_18.x" -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo apt install -y nodejs
node -v

为支持编译所需电路,需安装circom:

cd ~
git clone https://github.com/iden3/circom.git
cd circom
git checkout v2.1.4
git log --pretty=format:'%H' -n 1

相应commit hash应为:ca3345681549c859af1f3f42128e53e3e43fe5e2

使用Rust包管理和build工具——cargo,来编译和安装circom:

sudo apt install -y cargo
cargo build --release
cargo install --path circom
export PATH=$PATH:~/.cargo/bin
echo 'PATH=$PATH:~/.cargo/bin' >> ~/.profile
circom --version

proverjs中生成constants tree的代码运行效率低,为此在c++版的prover程序中集成了一个效率更高的名为bctree的工具——仅需要约8分钟即可生成constants tree:

cd ~
git clone https://github.com/0xPolygonHermez/zkevm-prover.git
cd zkevm-prover
git checkout b9179f3b870c2922b11d09462b447d0fc35dd2f9
git submodule init
git submodule update
sudo apt install -y build-essential libomp-dev libgmp-dev nlohmann-json3-dev
libpqxx-dev nasm libgrpc++-dev libprotobuf-dev grpc-proto libsodium-dev
uuid-dev libsecp256k1-dev
make -j bctree

5.1.3 预处理

执行proverjs 中的buildsetup流程,用于生成所有constants和电路。注意其中的bctree工具替换为之前编译的C++版本:

cd ~
git clone https://github.com/0xPolygonHermez/zkevm-proverjs.git
cd zkevm-proverjs
git checkout 59694e4a8a9358772c23e8110f53aee049e2d5bd
npm install
tmux -c "npm run buildsetup --bctree=../zkevm-prover/build/bctree"

整个buildsetup流程用时较长,需要约4.5小时,其中2小时用于下载powersOfTau28_hez_final.ptau文件——该文件约288GB,仅需要下载一次。

5.2 智能合约验证

通过前面预处理中的buildsetup流程,会生成验证proof的智能合约文件final.fflonk.verifier.sol。支持使用源代码 或 字节码 来验证该智能合约。

5.2.1 选项1:使用源代码来验证final.fflonk.verifier.sol合约

为验证final.fflonk.verifier.sol合约的字节码,需采用完全相同的版本、编译器和参数来编译,以确保字节码中所包含的metadata hash完全相同。如下指令使用hardhat工具来生成一个项目:

cd ~
mkdir contract
cd contract
npm init -y
npm install hardhat
mkdir -p contracts/verifiers
echo -e "module.exports={solidity:{compilers:[{version: \"0.8.17\" , settings:{optimizer:{enabled:true,runs:999999}}}]}}" > hardhat.config.js

一旦创建了项目结构,必须将之前buildsetup流程所生成的智能合约文件final.fflonk.verifier.sol(在~/zkevm-proverjs/build/proof目录下),拷贝到contracts/verifiers目录下,且合约文件名必须修改为FflonkVerifier.sol。若文件名或路径改变,则metadata hash也将修改,为此,需保证有完全相同的名字和路径。相应的操作命令为:

cp ~/zkevm-proverjs/build/proof/final.fflonk.verifier.sol contracts/verifiers/FflonkVerifier.sol
sha256sum contracts/verifiers/FflonkVerifier.sol

这样可检查FflonkVerifier.sol的输出哈希摘要准确为:60a850bd73a316d6f85bfdf05bc69ee01f84d889004e98b07847719f59e49761。

一旦检查通过,则可使用如下命令来编译合约:

npx hardhat compile

FflonkVerifier.sol合约的字节码在artifacts/contracts/verifiers/FflonkVerifier.sol/FflonkVerifier.json文件的bytecode字段内:

608060405234801561001057600080fd5b50612a
07806100206000396000f3fe6080604052348015
61001057600080fd5b506004361061002b576000
:
:
017fffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffe0908116603f01
1681019083821181831017156129875761298761
28aa565b81604052828152886020848701011115
6129a057600080fd5b8260208601602083013760
006020848301015280965050505050506129c884
602085016128d9565b9050925092905056fea264
6970667358221220 f7f0438c1c741f762e101c4e
ae732373046d40de3d0f2e0808e1fac1d863c78f
64736f6c63430008110033

可通过如下指令将上面的字节码拷贝到FflonkVerifier.sol.compiled.bytecode文件中:

grep bytecode artifacts/contracts/verifiers/FflonkVerifier.sol/FflonkVerifier.json |sed 's/.*"\(0x.*\)".*/\1/' > FflonkVerifier.sol.compiled.bytecode

也可以手工拷贝artifacts/contracts/verifiers/FflonkVerifier.sol/FflonkVerifier.json文件的bytecode字段到FflonkVerifier.sol.compiled.bytecode文件内。注意拷贝是不需要双引号。
然后使用哈希摘要来验证所编译字节码的完整性:

sha256sum FflonkVerifier.sol.compiled.bytecode

其结果应为:44f70b6a1548f49214027169db477f03e92492f19ac5594c648edb478316cbec。

5.2.2 选项2:通过字节码来验证final.fflonk.verifier.sol合约

下载所部署智能合约的字节码,需知道该合约的地址。本文对应的合约地址为0x4ceB990D2E2ee6d0e163fa80d12bac72C0F28D52。通过该地址,可直接到Etherscan、Blockscout或Beaconcha中获取交易字节码。

在终端上运行某些应用可能会在输入缓存溢出之前,限制其能接受的输入量。为避免该情况,可通过nanovi来创建FflonkVerifier.sol.explorer.bytecode文件:

cd ~/contract
nano FflonkVerifier.sol.explorer.bytecode

然后将获取的交易字节码拷贝到该文件中,并与上面“选项1”中的文件比较是否完全一样,可使用diff指令:

cd ~/contract
diff FflonkVerifier.sol.compiled.bytecode FflonkVerifier.sol.explorer.bytecode

或采用哈希文件完整性验证方法:

cd ~/contract
sha256sum FflonkVerifier.sol.*.bytecode

对应的输出应为:

44f70b6a1548f49214027169db477f03e92492f19ac5594c648edb478316cbec
FflonkVerifier.sol.compiled.bytecode
44f70b6a1548f49214027169db477f03e92492f19ac5594c648edb478316cbec
FflonkVerifier.sol.explorer.bytecode

5.3 zkEVM Proving

5.3.1 Prover JS

src文件夹下的main_executor脚本,基于输入文件input.json和已编译文件rom.json,生成committed多项式commit.bin的execution trace,其中:

  • rom.json文件:为zkASM编译器编译rom.zkasm文件的结果。
  • input.json文件:为特定输入集合文件。
node src/main_executor <input.json> -r <rom.json> -o <commit.bin>

额外的参数还有:

  • -t <test.json>:Test。
  • -l <logs.json>:输出日志。
  • -s:跳过.pil文件编译。
  • -d:debug模式。
  • -p:选择某具体的PIL程序。如pilprogram.pil
  • -P:加载pilConfig.json文件。
  • -u:未签名交易模式。
  • -e:跳过对newStateRootnewLocalExitRoot的断言。
  • -v:Verbose详细模式。

buildall命令用作之前章节提到的所有build setup step的主要entrypoint:

npm run buildall

配套的参数有:

  • --pil=<pil_file.pil>:该选项用于指定编译的特定PIL文件名。如--pil=src/main.pil
  • --pilconfig=<pilconfig.json>:该选项用于指定所使用的PIL配置文件名。PIL配置文件中包含了影响编译过程的各种设置和选项。如--pilconfig=config/pilconfig.json
  • --starkstruct=debug:该选项会适配PIL bits number来自动生成STARK struct。通常用于调试目的。
  • --from=<step>:指定开始build/rebuild流程的step。如--from=c12setup
  • --continue:继续上一次build所剩余的build流程。
  • --step=<step>:指定执行单个特定的build step。如--step=c12setup
  • --build=<build_dir>:指定所使用的build路径名。编译输出文件会存储在该build路径下。如--build=build/basic_proof
  • --input=<input_file>:指定用于build流程的输入文件。如--input=test/myinputfile.json

5.3.2 Prover C++

编译和运行zkEVM Prover的代码和指令见:

zkEVM Prover可提供3个RPC服务:

  • 1)Executor服务:调用zkEVM Prover的Executor模块来为L2交易集生成execution trace。该execution trace可用于执行完所包含的所有交易之后所生成的新状态。但是,Executor服务并不生成proof,仅生成execution trace。该服务可用于快速检查某proposed batch,或batches of transactions,是否构建正确,以及是否适于放入单个execution trace内。换句话说,是检查某batch内的交易,或多个batch,是否适于单个proof。

  • 2)StateDB服务:提供了访问L2状态数据库的结构。该状态以Merkle tree root来简洁表示,且StateDB服务会提供相应的数据及其Merkle proofs。StateDB服务:

    • 供Executor服务和Aggregator服务调用。
    • 代表了当前状态的单一truth源。
    • 从中可获取account balances、nonce values、合约部署字节码、storage等等。
    • 定义在hashdb.proto文件内。
  • 3)Aggregator服务:提供了zkEVM Prover所能提供的最高层服务:

    • 可为单个batch创建proof
    • 可为多个batch创建proof,只要这多个batch适于放入单个execution trace内。
    • 若提供了相邻batches的独立proofs pair,可创建aggregated proof。

    调用Aggregator服务来生成proof,该服务:

    • 使用Executor模块来生成相应的execution trace,
    • 并根据该execution trace生成所关联的committed多项式。
    • 最终根据pre-processed多项式和committed多项式来生成相应的proof。

    当调用Aggregator服务传入了相邻batches的proofs pair时,会生成aggregated proof。
    Aggregator服务的接口定义在:aggregator.proto文件内。

参考资料

[1] Polygon zkEVM技术文档 Recursion, aggregation and composition of proofs v.1.1

附录:Polygon Hermez 2.0 zkEVM系列博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值