Alert Source Discuss
🚧 Stagnant Standards Track: ERC

ERC-1922: zk-SNARK 验证器标准

Authors Michael Connor <michael.connor@uk.ey.com>, Chaitanya Konda <chaitanya.konda@uk.ey.com>, Duncan Westland <duncan.westland@uk.ey.com>
Created 2018-09-14
Discussion Link https://github.com/ethereum/EIPs/issues/1922
Requires EIP-165, EIP-196, EIP-197

简单总结

用于验证 zk-SNARK 的 “Verifier” 合约的标准接口。

摘要

以下标准允许为 zk-SNARK(“零知识简洁非交互式知识论证”),也称为“证明”、“论证”或“承诺”的验证实现标准合约 API。

此标准提供了基本功能,可将验证任何 zk-SNARK 所需的所有必要参数加载到验证器合约中,以便该证明最终可以返回 truefalse 响应,这与是否已验证相对应。

动机

zk-SNARK 是以太坊社区中一个很有前景的领域。zk-SNARK 的主要应用包括:

  • 私有交易
  • 私有计算
  • 通过“捆绑”交易证明来改进交易扩展

用于验证所有 zk-SNARK 的标准接口将使应用程序能够更轻松地实现私有交易、私有合约和扩展解决方案;并提取和解释在 zk-SNARK 验证期间发出的有限信息。

此标准最初由 EY 提出,其灵感尤其来自希望对其协议、交易和供应链活动保密,同时仍然受益于区块链和智能合约的常见优势的企业的要求。

:warning: TODO: 解释信息消费者(即与标准验证器交互的事物)的利益和视角。

规范

本文档中的关键词“必须”、“禁止”、“必需”、“应”、“不应”、“应该”、“不应该”、“推荐”、“可以”和“可选”应按照 RFC 2119 中的描述进行解释。

本规范中的术语与 libsnark 一致,如该项目的 README 中所提供。

  • 遵循合约 — 遵循本规范的 Verifier 合约。
  • 算术电路:将逻辑语句抽象为加法和乘法门。
  • 公共输入:通常在 zk-SNARK 文献中表示为向量“x”,在本接口中表示为 inputs。算术电路可以被认为采用两个参数;公共输入“x”和一个秘密“见证”“w”。此接口标准化了可以将 inputs 加载到 Adhering Contract 中的函数。
  • 证明:想要“证明”某些秘密见证“w”(满足算术电路)的“证明者”从以下内容生成 proof:电路的 Proving Key;他们的秘密见证“w”;及其对应的公共输入“x”。总而言之,满足 inputs(proof, inputs) 对及其对应的 proof 构成 zk-SNARK。
  • 验证密钥:“受信任的设置”计算从算术电路创建公共“Proving Key”和公共“Verification Key”。此接口不提供将 Verification Key 加载到区块链上的方法。Adhering Contract SHALL 能够接受至少一个 Verification Key 的知识论证((proof, inputs) 对)。我们将此类 Verification Key 称为“范围内”Verification Key。对于其每个“范围内”Verification Key,Adhering Contract MUST 能够明确地解释唯一的 verificationKeyId

每个符合 ERC-XXXX 标准的验证器合约都必须实现 ERCXXXXERC165 接口(但须遵守以下“注意事项”):

pragma solidity ^0.5.6;

/// @title EIP-XXXX zk-SNARK 验证器标准
/// @dev See https://github.com/EYBlockchain/zksnark-verifier-standard
///  Note: the ERC-165 identifier for this interface is 0xXXXXXXXX.
/// ⚠️ TODO: Calculate interface identifier
interface EIPXXXX /* is ERC165 */ {
    /// @notice Checks the arguments of Proof, through elliptic curve
    ///  pairing functions.
    /// @dev
    ///  MUST return `true` if Proof passes all checks (i.e. the Proof is
    ///  valid).
    ///  MUST return `false` if the Proof does not pass all checks (i.e. if the
    ///  Proof is invalid).
    /// @param proof A zk-SNARK.
    /// @param inputs Public inputs which accompany Proof.
    /// @param verificationKeyId A unique identifier (known to this verifier
    ///  contract) for the Verification Key to which Proof corresponds.
    /// @return result The result of the verification calculation. True
    ///  if Proof is valid; false otherwise.
    function verify(uint256[] calldata proof, uint256[] calldata inputs, bytes32 verificationKeyId) external returns (bool result);
}

接口

interface ERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

原理

分类法

⚠️ TODO: 在此处添加对 libsnark 的具体引用,以解释变量名称的选择。

:warning: TODO: 解释 C 可能不一定是逻辑语句的可满足算术电路。目前,这是对某些 SNARK 的限制。而源引用也提到了多项式和其他应用。

C — 逻辑语句的可满足算术电路抽象。

lambda​ - 在‘设置’阶段生成的随机数 - 通常称为“有毒废物”,因为知道 lambda​ 会使不值得信任的一方创建验证为“真”的“假”证明。 lambda​ 必须被销毁。

pk​ - 特定电路 C​ 的证明密钥。

vk - 特定电路 C 的验证密钥。

pk​vk​ 都是由某个函数 G​ 作为一对生成的: (pk, vk) = G(lambda, C)​

注意:C 可以通过 pkvk 中的任何一个来明确地表示。在 zk-SNARK 构造中,vkpk 的尺寸小得多,以便在链上实现简洁的验证。因此,vk 是合约“已知”的 C 的代表。因此,我们可以通过某个 verificationKeyId 唯一地标识每个电路,其中 verificationKeyId 用作到 vk 的更简洁的映射。

w - 一个“私有见证”字符串。电路 C 的一个只有证明者知道的私有参数,当与 inputs 参数 x 结合时,构成一个满足电路 C 的知识论证。

xinputs - ‘公共输入’的向量。电路 C 的一个公共参数,当与私有见证字符串 w 结合时,构成一个满足电路 C 的知识论证。

piproof - 值的编码向量,表示“证明者”对满足电路 C 的值 wx 的“知识论证”。 pi = P(pk, x, w).

本 EIP 中规定的 Verifier 合约的最终目的是通过某个验证函数 V​ 验证证明(形式为 pi​)。

如果存在 w st C(x,w)=1,则 V(vk, x, pi) = 1。 否则,V(vk, x, pi) = 0

本规范的 verify() 函数用于 V​ 的目的;返回 true(已验证证明满足算术电路)或 false(尚未验证证明)。

功能

verify

verify 函数构成了此标准的核心。这些参数旨在尽可能通用,以允许验证任何 zk-SNARK:

  • proof 指定为 uint256[]uint256 是在有限域上进行椭圆曲线运算的最合适的类型。实际上,这种类型被 Christian Reitweissner 的 zk-SNARK 的主要“Pairing library”实现中使用。 选择一维动态数组的原因有以下几个:
    • 动态:有几种可能的方法可以生成 zk-SNARK 证明,包括 PGHR13、G16、GM17,并且将来可能会开发更多方法。虽然每种方法可能会产生不同大小的证明对象,但动态数组允许这些不同的大小。
    • 数组:选择数组而不是“struct”对象,因为目前在 Solidity 中更容易在函数之间传递动态数组。任何证明“struct”都可以“展平”为数组并传递给 verify 函数。对该展平数组的解释是该函数已实现主体的责任。示例实现证明了可以实现这一点。
    • 一维:选择一维数组而不是多维数组,因为目前在 Solidity 中更容易使用一维数组。任何证明都可以“展平”为一维数组并传递给 verify 函数。对该展平数组的解释是 Adhering Contract 已实现主体的责任。示例实现证明了可以实现这一点。
  • inputs 指定为 uint256[]uint256 是在有限域上进行椭圆曲线运算的最合适的类型。实际上,这种类型被 Christian Reitweissner 的 zk-SNARK 的主要“Pairing library”实现中使用。 输入的数量会因要验证的算术电路的“公共输入”的数量而异。与 proof 参数类似,一维动态数组对于处理 zk-SNARK 的任何输入集来说都足够通用。

  • verificationKeyId 验证密钥(引用特定的算术电路)只需要在链上存储一次。然后,可以针对该验证密钥验证任何证明(与基础算术电路相关)。鉴于此,每次传入新的 (proof, inputs) 对时,将完整验证密钥的副本传递给 verify 函数是不必要的(从“gas 成本”的角度来看)。但是,我们需要告诉 Adhering Verifier Contract 哪个验证密钥对应于传入的 (proof, inputs) 对。verificationKeyId 实现了此目的 - 它将验证密钥唯一地表示为 bytes32 id。将 verificationKeyId 唯一分配给验证密钥的方法是 Adhering Contract 已实现主体的责任。

向后兼容性

  • 在首次提出此 EIP 时,以太坊主网上有一个由 EY 部署的实现。这是使用 Solidity 0.4.24 编译的,以便与 Truffle 兼容,但在其他方面与此标准兼容,该标准以最新的 Solidity 版本的形式呈现。
  • Christian Reitwiessner 博士的 示例(Verifier 合约和椭圆曲线配对库)对于以太坊社区对 zk-SNARK 协议的实验和开发起到了重要作用。此 EIP 的许多命名约定与他的示例保持一致。
  • 现有的 zk-SNARK 编译器(如 ZoKrates)生成的“Verifier.sol”合约目前不会生成符合此 EIP 规范的 Verifier 合约。
    • :warning: TODO: 提供一种转换器合约或技术,使 ZoKrates verifier.sol 合约符合此 EIP。

测试用例

示例实现的 Truffle 测试包含在测试用例存储库中。

⚠️ TODO:引用特定的测试用例,因为当前存储库中有很多。

实现

详细的示例实现以及这些示例实现的 Truffle 测试包含在此存储库中。

:warning: TODO:更新引用的验证器实现,使其可以部署或引用这些实现的已部署版本。目前,引用的代码明确声明“请勿在生产环境中使用”。

:warning: TODO:提供对查询实现此标准的标准验证器合约的实现的引用。

参考文献

:warning: TODO:更新参考文献并确认每个参考文献都在文本中引用(不需要括号文档)。

标准

  1. ERC-20 代币标准。./eip-20.md

  2. ERC-165 标准接口检测。./eip-165.md
  3. ERC-173 合约所有权标准(草案)。./eip-173.md
  4. ERC-196 用于 alt_bn128 上的椭圆曲线的加法和标量乘法的预编译合约。./eip-196.md
  5. ERC-197 用于 alt_bn128 上的椭圆曲线的最佳 ate 配对检查的预编译合约。./eip-197.md
  6. 以太坊名称服务 (ENS)。https://ens.domains
  7. RFC 2119 用于指示需求级别的 RFC 中的关键词。https://www.ietf.org/rfc/rfc2119.txt
教育材料:zk-SNARK
  1. Zcash。什么是 zk-SNARK?https://z.cash/technology/zksnarks.html
  2. Vitalik Buterin。zk-SNARK:深入了解。https://medium.com/@VitalikButerin/zk-snarks-under-the-hood-b33151a013f6
  3. Christian Reitweissner。zk-SNARK 简而言之。https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/
  4. Ben-Sasson、Chiesa、Tromer 等人。用于冯·诺依曼架构的简洁非交互式零知识。https://eprint.iacr.org/2013/879.pdf
zk-SNARK 的著名应用
  1. EY。通过以太坊主网上的 Token Commitment 交易实施业务协议。https://github.com/EYBlockchain/ZKPChallenge
  2. Zcash。https://z.cash
  3. Zcash。屏蔽地址之间的交易如何运作。https://blog.z.cash/zcash-private-transactions/
与 zk-SNARK 相关的著名项目
  1. libsnark:用于 zk-SNARK 的 C++ 库(“项目 README”)。https://github.com/scipr-lab/libsnark
  2. ZoKrates:可扩展的保护隐私的链下计算。https://www.ise.tu-berlin.de/fileadmin/fg308/publications/2018/2018_eberhardt_ZoKrates.pdf
  3. ZoKrates 项目存储库。https://github.com/JacobEberhardt/ZoKrates
  4. Joseph Stockermans。zkSNARK:驾驶员教育。https://github.com/jstoxrocky/zksnarks_example
  5. Christian Reitweissner - snarktest.solidity。https://gist.github.com/chriseth/f9be9d9391efc5beb9704255a8e2989d
zk-SNARK 的著名“替代方案” - 正在进行的零知识证明研究领域
  1. Vitalik Buterin。STARK。https://web.archive.org/web/20230425101334/https://vitalik.ca/general/2017/11/09/starks_part_1.html
  2. Bu ̈nz、Bootle、Boneh 等人。防弹证明。https://eprint.iacr.org/2017/1066.pdf
  3. 范围证明。https://www.cosic.esat.kuleuven.be/ecrypt/provpriv2012/abstracts/canard.pdf
  4. 苹果。安全区域。https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_in_the_secure_enclave
  5. 英特尔软件保护扩展。https://software.intel.com/en-us/sgx

版权

通过 CC0 免除版权和相关权利。

Citation

Please cite this document as:

Michael Connor <michael.connor@uk.ey.com>, Chaitanya Konda <chaitanya.konda@uk.ey.com>, Duncan Westland <duncan.westland@uk.ey.com>, "ERC-1922: zk-SNARK 验证器标准 [DRAFT]," Ethereum Improvement Proposals, no. 1922, September 2018. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1922.