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 所需的所有必要参数加载到验证器合约中,以便该证明最终可以返回 true
或 false
响应,这与是否已验证相对应。
动机
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 标准的验证器合约都必须实现 ERCXXXX
和 ERC165
接口(但须遵守以下“注意事项”):
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 可以通过 pk 或 vk 中的任何一个来明确地表示。在 zk-SNARK 构造中,vk 比 pk 的尺寸小得多,以便在链上实现简洁的验证。因此,vk 是合约“已知”的 C 的代表。因此,我们可以通过某个 verificationKeyId
唯一地标识每个电路,其中 verificationKeyId
用作到 vk 的更简洁的映射。
w - 一个“私有见证”字符串。电路 C 的一个只有证明者知道的私有参数,当与 inputs
参数 x 结合时,构成一个满足电路 C 的知识论证。
x 或 inputs
- ‘公共输入’的向量。电路 C 的一个公共参数,当与私有见证字符串 w 结合时,构成一个满足电路 C 的知识论证。
pi 或 proof
- 值的编码向量,表示“证明者”对满足电路 C 的值 w 和 x 的“知识论证”。
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:更新参考文献并确认每个参考文献都在文本中引用(不需要括号文档)。
标准
-
ERC-20 代币标准。./eip-20.md
- ERC-165 标准接口检测。./eip-165.md
- ERC-173 合约所有权标准(草案)。./eip-173.md
- ERC-196 用于 alt_bn128 上的椭圆曲线的加法和标量乘法的预编译合约。./eip-196.md
- ERC-197 用于 alt_bn128 上的椭圆曲线的最佳 ate 配对检查的预编译合约。./eip-197.md
- 以太坊名称服务 (ENS)。https://ens.domains
- RFC 2119 用于指示需求级别的 RFC 中的关键词。https://www.ietf.org/rfc/rfc2119.txt
教育材料:zk-SNARK
- Zcash。什么是 zk-SNARK?https://z.cash/technology/zksnarks.html
- Vitalik Buterin。zk-SNARK:深入了解。https://medium.com/@VitalikButerin/zk-snarks-under-the-hood-b33151a013f6
- Christian Reitweissner。zk-SNARK 简而言之。https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/
- Ben-Sasson、Chiesa、Tromer 等人。用于冯·诺依曼架构的简洁非交互式零知识。https://eprint.iacr.org/2013/879.pdf
zk-SNARK 的著名应用
- EY。通过以太坊主网上的 Token Commitment 交易实施业务协议。https://github.com/EYBlockchain/ZKPChallenge
- Zcash。https://z.cash
- Zcash。屏蔽地址之间的交易如何运作。https://blog.z.cash/zcash-private-transactions/
与 zk-SNARK 相关的著名项目
- libsnark:用于 zk-SNARK 的 C++ 库(“项目 README”)。https://github.com/scipr-lab/libsnark
- ZoKrates:可扩展的保护隐私的链下计算。https://www.ise.tu-berlin.de/fileadmin/fg308/publications/2018/2018_eberhardt_ZoKrates.pdf
- ZoKrates 项目存储库。https://github.com/JacobEberhardt/ZoKrates
- Joseph Stockermans。zkSNARK:驾驶员教育。https://github.com/jstoxrocky/zksnarks_example
- Christian Reitweissner - snarktest.solidity。https://gist.github.com/chriseth/f9be9d9391efc5beb9704255a8e2989d
zk-SNARK 的著名“替代方案” - 正在进行的零知识证明研究领域
- Vitalik Buterin。STARK。https://web.archive.org/web/20230425101334/https://vitalik.ca/general/2017/11/09/starks_part_1.html
- Bu ̈nz、Bootle、Boneh 等人。防弹证明。https://eprint.iacr.org/2017/1066.pdf
- 范围证明。https://www.cosic.esat.kuleuven.be/ecrypt/provpriv2012/abstracts/canard.pdf
- 苹果。安全区域。https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_in_the_secure_enclave
- 英特尔软件保护扩展。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.