科普丨zk-SNARK在以太坊上的案例示范

数字门徒
数字门徒 得得号

Jan 01, 2019 寻找熊市中的价值币。

摘要: 我们将把数学看成一个黑盒子,试着建立一些关于如何使用的感官,并给出一个简单的应用案例,以太坊最近集成zk-SNARK的工作。

本文中,我们将从实际的角度对zk-SNARK进行概述。

我们将把数学看成一个黑盒子,试着建立一些关于如何使用的感官,并给出一个简单的应用案例,以太坊最近集成zk-SNARK的工作。

零知识证明

零知识证明的目的是验证者能说服自己,证明者拥有一个秘密参数的知识,这个过程称为见证,它满足某种关系,而不用向验证者或任何人透露证物。

我们可以把它更具体地理解为一个程序,记作C,有两个输入:C(x, w)。输入x是公共输入,w是秘密见证输入。程序的输出是布尔值boolean,即true或false。然后给出一个特定的公共输入x,证明验证者知道一个秘密输入w,使得C(x,w) ==true。

【补充知识点:boolean 数据类型 boolean 变量存储为 8 位(1 个字节)的数值形式,但只能是 True 或是 False。当作为一个构造函数(带有运算符new)调用时,Boolean() 将把它的参数转换成一个布尔值,并且返回一个包含该值的 Boolean 对象。如果作为一个函数(不带有运算符 new)调用时,Boolean() 只将把它的参数转换成一个原始的布尔值,并且最终返回这个值。】

我们将重点讨论非交互式零知识证明non-interactive zero knowledge proofs,这意味着证明本身是一组数据,无需验证者交互即可验证。

示例程序

假设Bob给出了某个值的哈希值H,并且他希望Alice证明知道哈希值为H的某值s。通常,Alice会通过向Bob提供s来证明这一点,之后Bob会哈希计算并检查等于H。

然而,假设Alice不想向Bob透露某数值s,而只是想证明她知道。她可以使用zk-SNARK。

使用以下程序来描述Alice的场景,这里编写为Javascript函数:

换句话说:程序接受公共哈希值x和秘密值w,如果w的SHA-256哈希等于x,则返回true。

使用函数C(x,w)解决Alice的问题,Alice需要创建一个证据,证明她拥有s,使得C(H,s)== true,而不必显示s。 这是zk-SNARKs解决的一般问题。

zk-SNARK的定义
zk-SNARK算法由G、P、V三种算法组成,定义如下:

密钥生成器G接受一个秘密参数lambda和一个程序C,并生成两个公开可用的密钥、一个验证密钥pk和一个验证密钥vk。这些值是一次生成的公共参数,只需要为给定程序C。

验证者P以验证密钥pk、公共输入x和私有见证w作为输入,算法生成prf = P(pk, x, w),证明验证者知道私有见证w,满足程序要求。

验证者V计算V(vk, x, prf),如果证明正确则返回true,否则返回false。因此,如果证明程序知道见证w满足C(x,w) == true,则该函数返回true。

注意生成器中使用的秘密参数lambda。这个参数有时会使zk- SNAEK的实际应用变得很棘手。这样是原因,任何知道这个参数的人都能生成伪证明。具体来说,给定任何程序C和公共输入x,知道lambda的人可以生成一个证明伪prf,使V(vk, x, fake_prf)在不知道秘密w的情况下计算为真。

因此,生成器的运行需要一个非常安全的规则,以确保无人知晓以及参数无从保存。这就是为什么Zcash团队为了生成证明密钥和验证密钥而进行了极其复杂的仪式,同时确保在此过程中销毁了“有毒废物toxic waste”参数lambda。

zk-SNARK的示例程序

为了让Alice证明她知道上述例子的秘密值,Alice和Bob将如何在实际中使用zk-SNARK?

首先,如上所述,我们将使用以下函数定义的程序:

第一步是让Bob运行生成器G,以便创建证明密钥pk和验证密钥vk。第一次随机产生lambda,并使用它作为输入:

如上所述,小心处理参数lambda,因为如果Alice知道lambda值,她能够创建伪证明。Bob将与Alice共享pk和vk。

Alice现在将扮演证明者的角色。她需要证明自己知道散列哈希H的值s,输入pk, H, s运行证明算法P生成证明prf:

接下来Alice将prf证明提供给Bob, Bob运行验证函数V(vk, H, prf),返回true,证明Alice正确地知道了秘密s。Bob确信Alice知道秘密,但是Alice不需要向Bob透露秘密。

可重复使用的证明和验证密钥

上述例子,如果Bob想向Alice证明他知道一个秘密,就不能使用zk-SNARK。这是因为Alice不知道Bob有没有保存参数lambda,所以Bob有可能伪造证明。

如果一个程序对许多人都有用(例如Zcash的例子),那么一个独立于Alice和Bob的所托第三方可以运行生成器并创建证明密钥pk和验证密钥vk,这样就不会有人知道lambda。

任何信任第三方没有作弊的人都可以在未来交互中使用这些密钥。

zk-SNARK的以太坊应用

开发者已经开始将zk-SNARK整合到以太坊中。这是怎么样的? 具体来说,验证算法构建的区块以预先编译合约的形式添加到以太坊。做法如下:生成器在链外运行以生成证明密钥和验证密钥。然后,任何证明者都可以使用证明密钥来创建证明,这也是链外操作。然后使用证明、验证密钥和公共输入作为输入参数,在智能合约中运行通用验证算法。然后,验证算法的结果可用于触发其他链上活动。

示例:匿名交易

以下是zk-SNARK如何实现以太坊隐私的简单示例。假设我们有一个简单的代币合约。 通常,代币合约的核心是从地址到余额的映射:

我们保留相同的基本核心,除了采用余额哈希值替换余额:

我们不会隐藏交易的发件人或收件人,但我们将能够隐藏余额和发送金额。此属性有时称为机密事务。

将使用两个zk-SNARK将代币从一个帐户发送到另一个帐户,一个由发件人创建,另一个由接收者创建。

通常情况下,在一个代币合约中,一个交易大小Value是有效的,需要验证以下几点:

因此,zk-SNARK需要证明的是,哈希值的更新匹配余额变动,这是成立的。

这个意思是发送方将自己的初始余额和交易值作为私有输入,而初始余额、结束余额和Value的哈希值作为公共输入。同样的,接收者也会使用自己的初始余额和Value作为秘密输入,初始余额、期末余额和Value的哈希值作为公共输入。

下面是我们将用于发送方zk-SNARK的程序,其中x表示公共输入,w表示私有输入。
接收方使用的程序如下:

程序检查发送余额是否大于发送的值,并检查所有哈希值是否匹配。一组受信任的人员将为用zk-SNARK生成证明和验证密钥,它们称为confTxSenderPk、confTxSenderVk、confTxReceiverPk和confTxReceiverVk。

在代币合约中使用zk-SNARK看起来是这样的:

因此,区块链唯一更新是余额的哈希值,而不是余额本身。但是,我们可以知道所有余额都已正确更新,因为我们可以检查自己是否已经通过验证。

注意事项

上述匿名交易方案主要是提供一个如何在以太坊上使用zk-SNARK的实际例子。为了在此基础上创建强大的保密交易方案,我们需要解决许多问题:

  • 用户需要在客户端查询余额,如果你失去了余额,那么这些代币将无法恢复。余额可能使用从签名密钥派生的密钥在链上加密存储。
  • 余额需使用32字节数据,并将熵编码为余额的一部分,以防止反向散列哈希计算余额的能力。
  • 需要处理发送到未使用地址的Edge Case。
  • 发送者与接收者需要交互才能发送。可能有一个系统,其中发送者使用他们的证据来启动交易,且接收者在区块链上会看到“待处理的接收交易”并且最终确认。

(作者:数字门徒,内容来自链得得内容开放平台“得得号”;本文仅代表作者观点,不代表链得得官方立场)

链得得仅提供相关信息展示,不构成任何投资建议
本文系作者 数字门徒 授权链得得发表,并经链得得编辑,转载请注明出处、作者和本文链接

更多精彩内容,关注链得得微信号(ID:ChainDD),或者下载链得得App

分享到:

相关推荐

    评论(0

    Oh! no

    您是否确认要删除该条评论吗?

    分享到微信