2018年 Jacob Eberhardt和Stefan Tai兩位德國(guó)柏林工業(yè)大學(xué)博士生坤塞,提出了鏈下計(jì)算/鏈上驗(yàn)證的處理框架匆瓜,并提供了在以太坊上的整個(gè)框架的工具鏈砂豌。鏈下計(jì)算/鏈上驗(yàn)證的思想很早就有饲窿,但是能提供比較完善的工具鏈的實(shí)屬難得泵肄。目前ZoKrates使用zk-SNARK算法實(shí)現(xiàn)零知識(shí)證明捆交。
https://www.ise.tu-berlin.de/fileadmin/fg308/publications/2018/2018_eberhardt_ZoKrates.pdf
本文介紹ZoKrates的思想,工具鏈的使用以及源代碼導(dǎo)讀腐巢。
1. 鏈下計(jì)算/鏈上驗(yàn)證
傳統(tǒng)區(qū)塊鏈整個(gè)交易或者計(jì)算(Tx)的內(nèi)容都是存儲(chǔ)在區(qū)塊鏈上品追,并且每個(gè)節(jié)點(diǎn)都需要執(zhí)行整個(gè)交易或者計(jì)算。ZoKrates將計(jì)算移到鏈下系忙,并生成證明诵盼,鏈上只需要驗(yàn)證證明是否正確,從而確認(rèn)相應(yīng)的計(jì)算银还。鏈下計(jì)算/鏈上驗(yàn)證的方式有一些好處:1)提供隱私的能力 2)降低鏈上數(shù)據(jù)存儲(chǔ) 3)減少鏈上的計(jì)算量风宁。
傳統(tǒng)的區(qū)塊鏈和ZoKrates的區(qū)別如下圖所示:
2. ZoKrates工具鏈
使用ZoKrates工具鏈可以很方面地提供某種計(jì)算的證明,整個(gè)流程由如下的步驟(命令)組成:
1/ compile - 編譯電路蛹疯。對(duì)于想證明的計(jì)算戒财,需要設(shè)計(jì)和開發(fā)電路。ZoKrates采用DSL(Domain Specific Language)描述電路捺弦。ZoKrates也提供了一些常用的電路庫(kù)(SHA256饮寞,橢圓曲線的計(jì)算等等)孝扛。
2/ setup - 設(shè)置。對(duì)于每個(gè)電路幽崩,在生成證明之前苦始,必須setup一次,生成CRS慌申。
3/ compute-witness - 生成witness陌选。在提供了private/public輸入的情況下,ZoKrates自動(dòng)根據(jù)電路計(jì)算出對(duì)應(yīng)的witness蹄溉。
4/ generate-proof - 生成證明信息咨油。
5/ export-verifier - 導(dǎo)出驗(yàn)證工具。比如在以太坊上柒爵,export-verifier可以導(dǎo)出可在以太坊上部署的證明驗(yàn)證合約役电。
從電路的DSL描述,最后到生成以太坊上的智能合約的流程棉胀,如下圖:
3. DSL電路示例
ZoKrates給出了詳細(xì)的電路描述和編譯的說(shuō)明:
如下的電路是最簡(jiǎn)單的DSL電路描述法瑟,判斷a的平方是否等于b,等于返回1膏蚓,不等于返回0:
def main(private field a, field b) -> (field):
field result = if a * a == b then 1 else 0 fi
return result
field是DSL電路的基本數(shù)據(jù)類型瓢谢。一個(gè)field代表一個(gè)整數(shù),范圍[0, p-1]驮瞧,其中p為大的質(zhì)數(shù)氓扛。比如p為21888242871839275222246405745257275088548364400416034343698204186575808495617。field前面加上關(guān)鍵詞private论笔,說(shuō)明這個(gè)field的數(shù)據(jù)是private的采郎,屬于“witness”。電路的描述文件以.code為后綴狂魔。
4. ZoKrates源代碼導(dǎo)讀
本文中使用的ZoKrates源代碼的最后一個(gè)commit信息如下:
commit 87312a55e94055f14f95afeaa2790783d79a1ee5 Author: schaeff thibaut@schaeff.fr Date: Sun Jun 23 13:35:03 2019 +0200
remove invalid test case
整個(gè)ZoKrates的源代碼的目錄如下圖:
zokrates_cli:命令行接口實(shí)現(xiàn)蒜埋。
zokrates_fs_resolver: 文件系統(tǒng)解析。
zokrates_parser: .code電路代碼解析最楷。
zokrates_pest_ast: 解析電路為AST(Abstract Syntax Tree)整份。
zokrates_stdlib: 一些預(yù)實(shí)現(xiàn)的電路(比如,sha256函數(shù)籽孙,pedersen hash函數(shù)烈评,ecc相關(guān)計(jì)算)。
zokrates_core: zokrates的核心邏輯代碼犯建。解析.code電路讲冠,調(diào)用bellman相關(guān)接口,實(shí)現(xiàn)電路的生成适瓦,proof的生成和驗(yàn)證竿开。
簡(jiǎn)單的說(shuō)谱仪,ZoKrates的邏輯分為三部分:CLI代碼,電路的解析(pest/ast)以及調(diào)用bellman生成電路/證明否彩。以下從CLI命令行為起點(diǎn)疯攒,解析邏輯相關(guān)的代碼。
4.1 compile命令
compile命令編譯.code描述的電路:
./zokrates compile -i sample.code
編譯的邏輯在zokrates_core/src/compile.rs模塊的compile_aux函數(shù)中列荔。
通過(guò)zokrates_parser模塊解析.code電路卸例。電路程序的語(yǔ)法定義在zokrates_parser/src/zokrates.pest文件中。也就是說(shuō)肌毅,電路程序使用pest庫(kù)進(jìn)行語(yǔ)法解析。進(jìn)行語(yǔ)法解析后姑原,通過(guò)zokrates_pest_ast模塊生成ast(語(yǔ)法樹)悬而。最后再通過(guò)flatten模塊,將電路“拍平”锭汛。最后編譯后的程序笨奠,用FlatProg表示(定義在zokrates_core/src/flat_absy/mod.rs):
pub struct FlatProg<T: Field> {
/// FlatFunctions of the program
pub functions: Vec<FlatFunction<T>>,
}
pub struct FlatFunction<T: Field> {
/// Name of the program
pub id: String,
/// Arguments of the function
pub arguments: Vec<FlatParameter>,
/// Vector of statements that are executed when running the function
pub statements: Vec<FlatStatement<T>>,
/// Typed signature
pub signature: Signature,
}
也就是說(shuō),一個(gè)電路程序由一個(gè)個(gè)的FlatFunction構(gòu)成唤殴,每個(gè)FlatFunction中包含參數(shù)以及一系列的FlatStatement(R1CS表達(dá)式)般婆。解析完成的電路程序會(huì)存放在臨時(shí)文件中(當(dāng)前目錄下的output文件中)。
4.2 setup命令
setup命令生成CRS朵逝。
./zokrates setup
ZoKrates提供幾種零知識(shí)證明的方案:PGHR13, G16和GM17蔚袍。默認(rèn)采用G16的方案。
核心邏輯在zokrates_core/src/proof_system/bn128/g16.rs的setup函數(shù)中配名。
通過(guò)zokrates_core/proof_system/utils/bellman模塊啤咽,調(diào)用bellman庫(kù)中的generate_random_parameters函數(shù)生成隨機(jī)數(shù),并算出對(duì)應(yīng)的CRS數(shù)據(jù)渠脉。注意宇整,在生成CRS數(shù)據(jù)之前,需要synthesize電路生成R1CS芋膘。
4.3 compute-witness命令 compute-witness命令鳞青,指定輸入?yún)?shù),生成滿足電路R1CS限制的所有變量對(duì)應(yīng)的值为朋。如下是示例電路對(duì)應(yīng)的compute-witness的命令臂拓,示例電路對(duì)應(yīng)的a為337,b為113569:
./zokrates compute-witness -a 337 113569
核心邏輯在zokrates_core/src/ir/interpreter.rs的execute函數(shù)中潜腻。獲得滿足電路的所有變量的值埃儿,就是“執(zhí)行”一下電路邏輯,記錄相應(yīng)變量的值即可融涣。
4.4 generate-proof命令
generate-proof命令童番,使用compute-witness生成的witness信息精钮,以及setup生成的CRS數(shù)據(jù),生成proof證明剃斧。
./zokrates generate-proof
核心邏輯在zokrates_core/src/proof_system/bn128/g16.rs的generate_proof函數(shù)中轨香。調(diào)用bellman庫(kù)的create_random_proof生成證明。
4.5 export-verifier命令
export-verifier命令幼东,導(dǎo)出以太坊上可以部署的驗(yàn)證證明的智能合約臂容。
./zokrates export-verifier
核心邏輯在zokrates_core/src/proof_system/bn128/g16.rs的export_solidity_verifier函數(shù)中。在g16.rs中根蟹,定義了一個(gè)Groth16證明驗(yàn)證的模版程序(其中一部分如下):
function verifyingKey() pure internal returns (VerifyingKey memory vk) {
vk.a = Pairing.G1Point(<%vk_a%>);
vk.b = Pairing.G2Point(<%vk_b%>);
vk.gamma = Pairing.G2Point(<%vk_gamma%>);
vk.delta = Pairing.G2Point(<%vk_delta%>);
vk.gammaABC = new Pairing.G1Point;
<%vk_gammaABC_pts%>
}
這個(gè)模版程序定義了一些“宏變量”(vk_a, vk_b, vk_gamma, vk_delta等等)脓杉。export-verifier函數(shù),針對(duì)當(dāng)前的電路以及CRS信息简逮,替換相應(yīng)“宏變量”球散,生成真實(shí)的驗(yàn)證電路的智能合約。
總結(jié):
ZoKrates提出了鏈下計(jì)算/鏈上驗(yàn)證的處理框架散庶,并提供了在以太坊上的整個(gè)框架的工具鏈蕉堰。ZoKrates使用zk-SNARK算法實(shí)現(xiàn)零知識(shí)證明。ZoKrates的工具鏈悲龟,極大地降低了在以太坊上實(shí)現(xiàn)鏈下計(jì)算/鏈上驗(yàn)證的邏輯的門檻屋讶。只需要使用DSL語(yǔ)言編寫電路,就能使用ZoKrates工具庫(kù)實(shí)現(xiàn)鏈下計(jì)算须教,同時(shí)可以導(dǎo)出以太坊上對(duì)應(yīng)的智能合約皿渗,實(shí)現(xiàn)對(duì)應(yīng)電路的證明驗(yàn)證。