Zksnark--终极原理(二)

在这里插入图片描述
首先,zk-SNARK不能直接应用于任何计算问题;相反,您必须将问题转换为操作的正确“形式”。这种形式被称为“二次算术程序”(QAP),将函数的代码转换成这些代码本身就非常重要。与将函数代码转换为QAP的过程一起运行的还有另一个过程,这样,如果对代码有输入,就可以创建相应的解决方案(有时称为QAP的“见证”)。
首先第一步将所要求的等式转化为电路如上图。转化成电路的方法可以手动操作,也可以学习最近新出的XJsnark,其可以将你所需的代码转化为电路。
这样原始等式(以后称作等式F)就转化为4个式子如上图右侧。
在这里插入图片描述
R1CS是由三个向量(a, b, c)组成的序列,R1CS的解是一个向量s,其中s必须满足方程

s . a * s . b - s . c = 0(s.a表示内积运算,相应相应位置相乘再相加)

在这里插入图片描述
接下来需要进行的是如何将电路的4个式子变成以上图中的式子。
拿第一个式子举例:
我们假设此多项式的解表示为[1,x,y,y1,y2,y3],(未知数的顺序可以换)图中表示为s。
第一个多项式是:x*x-y1 = 0
对比s . a * s . b - s . c = 0可以得出:
s . a =x ----->a=[0,1,0,0,0,0]
s . b=x ------>b=[0,1,0,0,0,0]
s . c =y1 ------>c=[0,0,0,1,0,0]

其他三个式子同道理。
这里需要点明一下,回归到问题本身,我们想证明原多项式的解x,但是经过变换后,该解变成了向量s
在这里插入图片描述

我们在求完4个式子的R1CS后,这四个结果其实表示的意义是解向量s的约束,也就是说s必须满足这四个式子。
接下来进行最后一步将R1CS转化为QAP,这里用到了拉格朗日插值的方法。
首先介绍一下上图的意思:
上图是我们算的4个等式的R1CS转化后的a向量的值。我们把其组合为A矩阵,分别表示为A(1)……,
A(n)表示拉格朗插值后的值,例如:
在这里插入图片描述
看上图右边的A1(n)的y值取自A矩阵的第一列,A2(n)同理,算完6列后组成最终的A(n),如上图左边6个式子就是算完后A的结果。
接下来介绍为什么那么取点。
介绍一下拉格朗日插值:

*它的提出是对于某一个未知函数的一组观测或者实验数据,寻找一个多项式函数,使这个多项式函数能够过这些点。*

这两者的区别是 QAP 使用多项式来代替点积运算,他们所实现的逻辑完全相同。在介绍这种转化之前,我们需要学习拉格朗日差值公式,这个公式的作用是构造一个穿过指定点的多项式,Vitalik 的文章中用了很大的篇幅介绍这个公式的使用,在这里我直接给出拉格朗日插值公式:

在这里插入图片描述

好了,学会使用这个公式后可以继续我们的步骤了。现在我们要将四个长度为六的三向量组转化为六组多项式,每组多项式包括三个三阶多项式,我们在每个x点处来评估不同的约束,在这里,我们共有四个约束**,因此我们分别用多项式在 x = 1,2,3,4 处来评估这四个向量组。现在我们使用拉格朗日差值公式来将 R1CS 转化为 QAP 形式。**

我们先求出四个约束所对应的每个 a 向量的第一个值的多项式,也就是说使用拉格朗日插值定理求过点 (1,0), (2,0), (3,0), (4,0) 的多项式,类似的我们可以求出其余的四个约束所对应的每个向量的第i个值的多项式
在这里插入图片描述
我们算完后一共有18个式子,将n=1带入18个式子后,可以恢复到第一个约束的三个向量(a,b,c),也就是说我们通过x=1 ,2,3,4 就可以恢复到相应的约束的三个向量。
这时再看一次这个图可能会清晰一些!!
这样的话我们就完成了QAP的转化。
稍微总结一下整个过程:
在这里插入图片描述
回归问题:我们用ZKSNARK来解决问题但是必须符合其数据的格式,也就是需要进行QAP的转化。(也就是使用浮点数计算则必须把整数先转化为浮点数的格式才可以)
数学是计算机的基础啊!!
最后一步发现原式子提取出一个Z(n),因为原来式子有1,2,3,4解,所以可以提取出Z(n),Z(n)是公开的,两者都知道,所以可以用以下方式进行简单验证:
在这里插入图片描述

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我理解到您需要一个代码实现来模拟zk-SNARK协议的过程。请注意,zk-SNARK是一种复杂的加密协议,需要深入的数学和计算机科学知识来理解和实现。在此,我将为您提供一个基本的实现框架,但这只是一个简化版本,没有进行实际的加密处理。 首先,让我们来了解一下zk-SNARK协议的基本流程: 1. 生成公私钥对 2. 生成证明 3. 验证证明 我们将按照这个流程来实现这个协议。 1. 生成公私钥对 我们首先需要一个密钥对,用于加密和解密。在zk-SNARK中,这个密钥对由一个大素数p和一个随机数g生成。我们可以使用Java的`java.util.Random`类来生成随机数,并使用`java.math.BigInteger`类来进行大数运算。 ```java import java.math.BigInteger; import java.util.Random; public class Zksnark { private BigInteger p, g, privateKey, publicKey; public Zksnark() { // Generate a random prime p and a random number g Random rand = new Random(); p = BigInteger.probablePrime(512, rand); g = new BigInteger(512, rand); // Generate a random private key and corresponding public key privateKey = new BigInteger(512, rand).mod(p); publicKey = g.modPow(privateKey, p); } public void printKeys() { System.out.println("Private key: " + privateKey.toString()); System.out.println("Public key: " + publicKey.toString()); } } ``` 2. 生成证明 下一步是生成证明。在zk-SNARK中,证明包含两个部分:一个公共部分和一个私有部分。公共部分可以由任何人验证,而私有部分只能由拥有私钥的人生成。我们将使用Java的`MessageDigest`类来生成哈希值,并使用`java.security.Signature`类来生成签名。 ```java import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Signature; import java.security.SignatureException; public class Zksnark { private BigInteger p, g, privateKey, publicKey; public Zksnark() { // ... } public void printKeys() { // ... } public String generateProof(String message) { // Generate a public hash of the message String publicHash = generateHash(message); // Sign the message using the private key byte[] signature = signMessage(publicHash); // Combine the public hash and signature to generate the proof return publicHash + ":" + new BigInteger(signature).toString(); } private String generateHash(String message) { try { MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] hash = md.digest(message.getBytes()); return new BigInteger(hash).toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } private byte[] signMessage(String message) { try { Signature sig = Signature.getInstance("SHA256withRSA"); sig.initSign(privateKey); sig.update(message.getBytes()); return sig.sign(); } catch (Exception e) { e.printStackTrace(); } return null; } } ``` 3. 验证证明 最后一步是验证证明。在zk-SNARK中,验证者可以通过公共证明来验证证明的正确性。我们将使用Java的`java.security.Signature`类来验证签名,并使用`java.math.BigInteger`类来进行大数运算。 ```java import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Signature; import java.security.SignatureException; import java.util.Arrays; public class Zksnark { private BigInteger p, g, privateKey, publicKey; public Zksnark() { // ... } public void printKeys() { // ... } public String generateProof(String message) { // ... } public boolean verifyProof(String proof, String message) { // Split the proof into public hash and signature String[] parts = proof.split(":"); String publicHash = parts[0]; byte[] signature = new BigInteger(parts[1]).toByteArray(); // Generate the public hash of the message String expectedHash = generateHash(message); // Verify the signature using the public key boolean signatureValid = verifySignature(signature, publicHash); // Verify that the public hash matches the expected hash boolean hashValid = publicHash.equals(expectedHash); // Return true if the signature and hash are both valid return signatureValid && hashValid; } private boolean verifySignature(byte[] signature, String message) { try { Signature sig = Signature.getInstance("SHA256withRSA"); sig.initVerify(publicKey); sig.update(message.getBytes()); return sig.verify(signature); } catch (Exception e) { e.printStackTrace(); } return false; } private String generateHash(String message) { try { MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] hash = md.digest(message.getBytes()); return new BigInteger(hash).toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } } ``` 这就是一个简单的zk-SNARK协议的Java实现。请注意,这只是一个基本的实现框架,没有进行实际的加密处理。如果您需要更高级的实现,请参考相关的文献和代码库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值