zkSNARK Verifier Standard
Simple Summary
A standard interface for “Verifier” contracts which verify zkSNARKs.
Abstract
The following standard allows for the implementation of a standard contract API for the verification of zkSNARKs (“ZeroKnowledge Succinct NonInteractive Arguments of Knowledge”), also known as “proofs”, “arguments”, or “commitments”.
This standard provides basic functionality to load all necessary parameters for the verification of any zkSNARK into a verifier contract, so that the proof may ultimately return a true
or false
response; corresponding to whether it has been verified or not verified.
Motivation
zkSNARKs are a promising area of interest for the Ethereum community. Key applications of zkSNARKs include:
 Private transactions
 Private computations
 Improved transaction scaling through proofs of “bundled” transactions
A standard interface for verifying all zkSNARKs will allow applications to more easily implement private transactions, private contracts, and scaling solutions; and to extract and interpret the limited information which gets emitted during zkSNARK verifications.
This standard was initially proposed by EY, and was inspired in particular by the requirements of businesses wishing to keep their agreements, transactions, and supply chain activities confidential—all whilst still benefiting from the commonly cited strengths of blockchains and smart contracts.
:warning: TODO: Explain the benefits to and perspective of a consumer of information. I.e. the thing that interfaces with the standard verifier.
Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
Terminology in this specification is used consistently with libsnark, as provided in that project’s README.
 Adhering Contract — A Verifier contract which adheres to this specification.
 Arithmetic circuit: An abstraction of logical statements into addition and multiplication gates.
 Public Inputs: often denoted as a vector ‘x’ in zkSNARKs literature, and denoted
inputs
in this interface. An arithmetic circuit can be thought of as taking two parameters; the Public Inputs, ‘x’, and a secret ‘witness’, ‘w’. This interface standardises functions which can load theinputs
into an Adhering Contract.  Proof: A ‘prover’ who wants to ‘prove’ knowledge of some secret witness ‘w’ (which satisfies an arithmetic circuit), generates a
proof
from: the circuit’s Proving Key; their secret witness ‘w’; and its corresponding Public Inputs ‘x’. Together, a pair(proof, inputs)
of satisfyinginputs
and their correspondingproof
forms a zkSNARK.  Verification Key: A ‘trusted setup’ calculation creates both a public ‘Proving Key’ and a public ‘Verification Key’ from an arithmetic circuit. This interface does not provide a method for loading a Verification Key onto the blockchain. An Adhering Contract SHALL be able to accept arguments of knowledge (
(proof, inputs)
pairs) for at least one Verification Key. We shall call such Verification Keys ‘inscope’ Verification Keys. An Adhering Contract MUST be able to interpret unambiguously a uniqueverificationKeyId
for each of its ‘inscope’ Verification Keys.
Every ERCXXXX compliant verifier contract must implement the ERCXXXX
and ERC165
interfaces (subject to “caveats” below):
pragma solidity ^0.5.6;
/// @title EIPXXXX zkSNARK Verifier Standard
/// @dev See https://github.com/EYBlockchain/zksnarkverifierstandard
/// Note: the ERC165 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 zkSNARK.
/// @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
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC165
/// @dev Interface identification is specified in ERC165. 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);
}
Rationale
Taxonomy
⚠️ TODO: Add a specific reference to libsnark here, explaining the choice of variable names.
:warning: TODO: Explain how C may not necessarily be a satisfiable arithmetic circuit of logical statements. As current, this is a limitation to certain kinds of SNARKS. Whereas the source references also mention polynomials, and other applications.
C — A satisfiable arithmetic circuit abstraction of logical statements.
lambda  A random number, generated at the ‘setup’ phase  commonly referred to as ‘toxic waste’, because knowledge of lambda would allow an untrustworthy party to create ‘false’ proofs which would verify as ‘true’. lambda must be destroyed.
pk  The proving key for a particular circuit C.
vk  The verification key for a particular circuit C.
Both pk and vk are generated as a pair by some function G: (pk, vk) = G(lambda, C)
Note: C can be represented unambiguously by either of pk or vk. In zkSNARK constructions, vk is much smaller in size than pk, so as to enable succinct verification onchain. Hence, vk is the representative of C that is ‘known’ to the contract. Therefore, we can identify each circuit uniquely through some verificationKeyId
, where verificationKeyId
serves as a more succinct mapping to vk.
w  A ‘private witness’ string. A private argument to the circuit C known only to the prover, which, when combined with the inputs
argument x, comprises an argument of knowledge which satisfies the circuit C.
x or inputs
 A vector of ‘Public Inputs’. A public argument to the circuit C which, when combined with the private witness string w, comprises an argument of knowledge which satisfies the circuit C.
pi or proof
 an encoded vector of values which represents the ‘prover’s’ ‘argument of knowledge’ of values w and x which satisfy the circuit C.
pi = P(pk, x, w).
The ultimate purpose of a Verifier contract, as specified in this EIP, is to verify a proof (of the form pi) through some verification function V.
V(vk, x, pi) = 1, if there exists a w s.t. C(x,w)=1. V(vk, x, pi) = 0, otherwise.
The verify()
function of this specification serves the purpose of V; returning either true
(the proof has been verified to satisfy the arithmetic circuit) or false
(the proof has not been verified).
Functions
verify
The verify
function forms the crux this standard. The parameters are intended to be as generic as possible, to allow for verification of any zkSNARK:
proof
Specified asuint256[]
.uint256
is the most appropriate type for elliptic curve operations over a finite field. Indeed, this type is used in the predominant ‘Pairing library’ implementation of zkSNARKs by Christian Reitweissner. A onedimensional dynamic array has been chosen for several reasons: Dynamic: There are several possible methods for producing a zkSNARK proof, including PGHR13, G16, GM17, and future methods might be developed in future. Although each method may produce differently sized proof objects, a dynamic array allows for these differing sizes.
 Array: An array has been chosen over a ‘struct’ object, because it is currently easier to pass dynamic arrays between functions in Solidity. Any proof ‘struct’ can be ‘flattened’ to an array and passed to the
verify
function. Interpretation of that flattened array is the responsibility of the implemented body of the function. Example implementations demonstrate that this can be achieved.  Onedimensional: A onedimensional array has been chosen over multidimensional array, because it is currently easier to work with onedimensional arrays in Solidity. Any proof can be ‘flattened’ to a onedimensional array and passed to the
verify
function. Interpretation of that flattened array is the responsibility of the implemented body of the Adhering Contract. Example implementations demonstrate that this can be achieved.

inputs
Specified asuint256[]
.uint256
is the most appropriate type for elliptic curve operations over a finite field. Indeed, this type is used in the predominant ‘Pairing library’ implementation of zkSNARKs by Christian Reitweissner. The number of inputs will vary in size, depending on the number of ‘public inputs’ of the arithmetic circuit being verified against. In a similar vein to theproof
parameter, a onedimensional dynamic array is general enough to cope with any set of inputs to a zkSNARK. verificationKeyId
A verification key (referencing a particular arithmetic circuit) only needs to be stored onchain once. Any proof (relating to the underlying arithmetic circuit) can then be verified against that verification key. Given this, it would be unnecessary (from a ‘gas cost’ point of view) to pass a duplicate of the full verification key to theverify
function every time a new(proof, inputs)
pair is passed in. We do however need to tell the Adhering Verifier Contract which verification key corresponds to the(proof, inputs)
pair being passed in. AverificationKeyId
serves this purpose  it uniquely represents a verification key as abytes32
id. A method for uniquely assigning averificationKeyId
to a verification key is the responsibility of the implemented body of the Adhering Contract.
Backwards Compatibility
 At the time this EIP was first proposed, there was one implementation on the Ethereum main net  deployed by EY. This was compiled with Solidity 0.4.24 for compatibility with Truffle but otherwise compatible with this standard, which is presented at the latest current version of Solidity.
 Dr Christian Reitwiessner’s excellent example of a Verifier contract and elliptic curve pairing library has been instrumental in the Ethereum community’s experimentation and development of zkSNARK protocols. Many of the naming conventions of this EIP have been kept consistent with his example.
 Existing zkSNARK compilers such as ZoKrates, which produce ‘Verifier.sol’ contracts, do not currently produce Verifier contracts which adhere to this EIP specification.
 :warning: TODO: Provide a converter contract or technique which allows ZoKrates verifier.sol contracts to adhere with this EIP.
Test Cases
Truffle tests of example implementations are included in the test case repository.
⚠️ TODO: Reference specific test cases because there are many currently in the repository.
Implementations
Detailed example implementations and Truffle tests of these example implementations are included in this repository.
:warning: TODO: Update referenced verifier implementations so that they are readytodeploy or reference deployed versions of those implementations. At current, the referenced code specifically states “DO NOT USE THIS IN PRODUCTION”.
:warning: TODO: Provide reference to an implementation which interrogates a standard verifier contract that implements this standard.
References
:warning: TODO: Update references and confirm that each reference is cited (parenthetical documentation not necessary) in the text.
Standards

ERC20 Token Standard. ./eip20.md
 ERC165 Standard Interface Detection. ./eip165.md
 ERC173 Contract Ownership Standard (DRAFT). ./eip173.md
 ERC196 Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128. ./eip196.md
 ERC197 Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128. ./eip197.md
 Ethereum Name Service (ENS). https://ens.domains
 RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt
Educational material: zkSNARKs
 Zcash. What are zkSNARKs? https://z.cash/technology/zksnarks.html
 Vitalik Buterin. zkSNARKs: Under the Hood. https://medium.com/@VitalikButerin/zksnarksunderthehoodb33151a013f6
 Christian Reitweissner. zkSNARKs in a Nutshell. https://blog.ethereum.org/2016/12/05/zksnarksinanutshell/
 BenSasson, Chiesa, Tromer, et. al. Succinct NonInteractive Zero Knowledge for a von Neumann Architecture. https://eprint.iacr.org/2013/879.pdf
Notable applications of zkSNARKs
 EY. Implementation of a business agreement through Token Commitment transactions on the Ethereum mainnet. https://github.com/EYBlockchain/ZKPChallenge
 Zcash. https://z.cash
 Zcash. How Transactions Between Shielded Addresses Work. https://blog.z.cash/zcashprivatetransactions/
Notable projects relating to zkSNARKs
 libsnark: A C++ Library for zkSNARKs (“project README)”. https://github.com/sciprlab/libsnark
 ZoKrates: Scalable PrivacyPreserving OffChain Computations. https://www.ise.tuberlin.de/fileadmin/fg308/publications/2018/2018_eberhardt_ZoKrates.pdf
 ZoKrates Project Repository. https://github.com/JacobEberhardt/ZoKrates
 Joseph Stockermans. zkSNARKs: Driver’s Ed. https://github.com/jstoxrocky/zksnarks_example
 Christian Reitweissner  snarktest.solidity. https://gist.github.com/chriseth/f9be9d9391efc5beb9704255a8e2989d
Notable ‘alternatives’ to zkSNARKs  areas of ongoing zeroknowledge proof research
 Vitalik Buterin. STARKs. https://vitalik.ca/general/2017/11/09/starks_part_1.html
 Bu ̈nz, Bootle, Boneh, et. al. Bulletproofs. https://eprint.iacr.org/2017/1066.pdf
 Range Proofs. https://www.cosic.esat.kuleuven.be/ecrypt/provpriv2012/abstracts/canard.pdf
 Apple. Secure Enclaves. https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_in_the_secure_enclave
 Intel Software Guard Extensions. https://software.intel.com/enus/sgx
Copyright
Copyright and related rights waived via CC0.