This library implements __zkSNARK__ schemes, which are a cryptographic method
for proving/verifying, in zero knowledge, the integrity of computations.
A computation can be expressed as an NP statement, in forms such as the following:
- "The C program _foo_, when executed, returns exit code 0 if given the input _bar_ and some additional input _qux_."
- "The Boolean circuit _foo_ is satisfiable by some input _qux_."
- "The arithmetic circuit _foo_ accepts the partial assignment _bar_, when extended into some full assignment _qux_."
- "The set of constraints _foo_ is satisfiable by the partial assignment _bar_, when extended into some full assignment _qux_."
A prover who knows the witness for the NP statement (i.e., a satisfying input/assignment) can produce a short proof attesting to the truth of the NP statement. This proof can be verified by anyone, and offers the following properties.
-__Zero knowledge:__
the verifier learns nothing from the proof beside the truth of the statement (i.e., the value _qux_, in the above examples, remains secret).
-__Succinctness:__
the proof is short and easy to verify.
-__Non-interactivity:__
the proof is a string (i.e. it does not require back-and-forth interaction between the prover and the verifier).
-__Soundness:__
the proof is computationally sound (i.e., it is infeasible to fake a proof of a false NP statement). Such a proof system is also called an _argument_.
-__Proof of knowledge:__
the proof attests not just that the NP statement is true, but also that the
prover knows why (e.g., knows a valid _qux_).
These properties are summarized by the _zkSNARK_ acronym, which stands for _Zero-Knowledge Succinct Non-interactive ARgument of Knowledge_ (though zkSNARKs are also knows as
_succinct non-interactive computationally-sound zero-knowledge proofs of knowledge_).
For formal definitions and theoretical discussions about these, see
\[BCCT12], \[BCIOP13], and the references therein.
The libsnark library currently provides a C++ implementation of:
1. General-purpose proof systems:
1. A preprocessing zkSNARK for the NP-complete language "R1CS"
(_Rank-1 Constraint Systems_), which is a language that is similar to arithmetic
circuit satisfiability.
2. A preprocessing SNARK for a language of arithmetic circuits, "BACS"
(_Bilinear Arithmetic Circuit Satisfiability_). This simplifies the writing
of NP statements when the additional flexibility of R1CS is not needed.
Internally, it reduces to R1CS.
3. A preprocessing SNARK for the language "USCS"
(_Unitary-Square Constraint Systems_). This abstracts and implements the core
contribution of \[DFGK14]
4. A preprocessing SNARK for a language of Boolean circuits, "TBCS"
(_Two-input Boolean Circuit Satisfiability_). Internally, it reduces to USCS.
This is much more efficient than going through R1CS.
5. ADSNARK, a preprocessing SNARKs for proving statements on authenticated
data, as described in \[BBFR15].
6. Proof-Carrying Data (PCD). This uses recursive composition of SNARKs, as
explained in \[BCCT13] and optimized in \[BCTV14b].
2. Gadget libraries (gadgetlib1 and gadgetlib2) for constructing R1CS
instances out of modular "gadget" classes.
3. Examples of applications that use the above proof systems to prove
statements about:
1. Several toy examples.
2. Execution of TinyRAM machine code, as explained in \[BCTV14a] and
\[BCGTV13]. (Such machine code can be obtained, e.g., by compiling from C.)
This is easily adapted to any other Random Access Machine that satisfies a
simple load-store interface.
3. A scalable for TinyRAM using Proof-Carrying Data, as explained in \[BCTV14b]
Run the following, to fetch dependencies from their GitHub repos and compile them.
(Not required if you set `CURVE` to other than the default `BN128` and also set `NO_SUPERCOP=1`.)
$ ./prepare-depends.sh
Then, to compile the library, tests, profiling harness and documentation, run:
$ make
To create just the HTML documentation, run
$ make doc
and then view the resulting `README.html` (which contains the very text you are reading now).
To create Doxygen documentation summarizing all files, classes and functions,
with some (currently sparse) comments, install the `doxygen` and `graphviz` packages, then run
$ make doxy
(this may take a few minutes). Then view the resulting [`doxygen/index.html`](doxygen/index.html).
### Using libsnark as a library
To develop an application that uses libsnark, you could add it within the libsnark directory tree and adjust the Makefile, but it is far better to build libsnark as a (shared or static) library. You can then write your code in a separate directory tree, and link it against libsnark.
To build just the shared object library `libsnark.so`, run:
$ make lib
To build just the static library `libsnark.a`, run:
$ make lib STATIC=1
Note that static compilation requires static versions of all libraries it depends on.
This will install `libsnark.so` into `/install/path/lib`; so your application should be linked using `-L/install/path/lib -lsnark`. It also installs the requisite headers into `/install/path/include`; so your application should be compiled using `-I/install/path/include`.
In addition, unless you use `NO_SUPERCOP=1`, `libsupercop.a` will be installed and should be linked in using `-lsupercop`.
### Building on Windows using Cygwin
Install Cygwin using the graphical installer, including the `g++`, `libgmp`
and `git` packages. Then disable the dependencies not easily supported under CygWin,
using:
$ make NO_PROCPS=1 NO_GTEST=1 NO_DOCS=1
### Building on Mac OS X
On Mac OS X, install GMP from MacPorts (`port install gmp`). Then disable the
dependencies not easily supported under CygWin, using:
$ make NO_PROCPS=1 NO_GTEST=1 NO_DOCS=1
MacPorts does not write its libraries into standard system folders, so you
might need to explicitly provide the paths to the header files and libraries by
appending `CXXFLAGS=-I/opt/local/include LDFLAGS=-L/opt/local/lib` to the line
above. Similarly, to pass the paths to ate-pairing you would run
Collect counts for field and curve operations inside static variables
of the corresponding algebraic objects. This option works for all
curves except bn128.
* define `USE_ASM` (on by default)
Use unrolled assembly routines for F[p] arithmetic and faster heap in
multi-exponentiation. (When not set, use GMP's `mpn_*` routines instead.)
* define `USE_MIXED_ADDITION`
Convert each element of the proving key and verification key to
affine coordinates. This allows using mixed addition formulas in
multiexponentiation and results in slightly faster prover and
verifier runtime at expense of increased proving time.
*`make PERFORMANCE=1`
Enables compiler optimizations such as link-time optimization, and disables debugging aids.
(On some distributions this causes a `plugin needed to handle lto object` link error and `undefined reference`s, which can be remedied by `AR=gcc-ar make ...`.)
Not all combinations are tested together or supported by every part of the codebase.