Skip to content
Permalink
Browse files

Update README.md

  • Loading branch information...
akosba committed Apr 7, 2019
1 parent d12b6d9 commit 363b22baa1fa90d369e26a4d89cf3c982dbd176e
Showing with 20 additions and 11 deletions.
  1. +20 −11 README.md
@@ -4,7 +4,9 @@ This is a Java library for building circuits for preprocessing zk-SNARKs. The li
- `JsnarkCircuitBuilder`: A Java project that has a Gadget library for building/augmenting circuits. (Check the `src/examples` package)
- `libsnark/jsnark_interface`: A C++ interface to libsnark which accepts circuits produced by either the circuit builder or by Pinocchio's compiler directly.

__Update__: The library now has several cryptographic gadgets used in earlier work ([Hawk](https://eprint.iacr.org/2015/675.pdf) and [C0C0](https://eprint.iacr.org/2015/1093.pdf)). Some of the gadgets like RSA and AES were improved by techniques from xjsnark (to appear). The gadgets can be found in [src/examples/gadgets](https://github.com/akosba/jsnark/tree/master/JsnarkCircuitBuilder/src/examples/gadgets).
__Updates__:
- The jsnark library now has several cryptographic gadgets used in earlier work ([Hawk](https://eprint.iacr.org/2015/675.pdf) and [C0C0](https://eprint.iacr.org/2015/1093.pdf)). Some of the gadgets like RSA and AES were improved by techniques from xJsnark. The gadgets can be found in [src/examples/gadgets](https://github.com/akosba/jsnark/tree/master/JsnarkCircuitBuilder/src/examples/gadgets).
- xJsnark, a high-level programming framework for zk-SNARKs is available [here](https://github.com/akosba/xjsnark). xJsnark uses an enhancd version of jsnark in its back end, and aims at reducing the background/effort required by low-level libraries, while generating efficient circuits from the high-level code. Sample examples can be found in this [page](https://github.com/akosba/xjsnark#examples-included).

### Prerequisites

@@ -83,13 +85,22 @@ Note: An IDE, e.g. Eclipse, or possibly the ant tool can be used instead to buil

### Examples included

#### Simple Examples

- __Basic Circuit Example__: `SimpleCircuitGenerator.java`. This shows a circuit that computes very simple expressions.
- __Basic Gadget Example__: `DotProductGadget.java`. This is a gadget for computing the dot product of two vectors. The gadget is used in `DotProductCircuitGenerator.java`.
- __Gadgets with witness computations done outside the circuit__: `FieldDivisonGadget.java`, `ModGadget.java`. This way of writing circuits is useful when verification is more efficient than computation, and when the prover witness value can be inferred automatically in the circuit. Note the usage of `specifyProverWitnessComputation(..)`. This must be positioned before the steps where the witness is used.
- __SHA256 Gadget__: This is a manually-optimized SHA256 Gadget for variable-length input with a padding option. The code is written to be similar to how SHA256 is written in C, except for three main things: keeping track of bitwidth, manual optimizations for computation of ch and maj, and the explicit handling of overflows. Making use of jsnark's optimizations, our implementation for the SHA256 gadget costs __26196 constraints for one block__. If padding is applied within the block, the cost can be even lower.
- __Pinocchio Integration__: `PinocchioGadget.java` and `AugmentedAuctionCircuitGenerator.java`. The Pinocchio gadget can be used to use compiled circuits by the Pinocchio compiler as gagdets. `AugmentedAuctionCircuitGenerator.java` shows how to use a compiled Auction circuit by Pinocchio, and augment it with other manually-developed gadgets. This can help in the cases where the programmer needs to take care only of the bottleneck parts of the circuits.

#### Cryptographic Primtives

Several cryptographic gadgets spanning hashes, block ciphers, key exchange, public key encryption and signatures can be found in [src/examples/gadgets](https://github.com/akosba/jsnark/tree/master/JsnarkCircuitBuilder/src/examples/gadgets). We list some notes regarding few gadgets below:

- __SHA256 gadget__: This is a manually-optimized SHA256 Gadget for variable-length input with a padding option. The code is written to be similar to how SHA256 is written in C or Java, except for three main things: keeping track of bitwidth, manual optimizations for computation of ch and maj, and the explicit handling of overflows (A more recent work ([xJsnark](https://github.com/akosba/xjsnark)) reduces/eliminates the need for such differences, while still generating optimized outputs). The current SHA256 gadget implementation in jsnark costs about 25650 constraints for one block depending on the number and the bitwidth of the input wires (Further minor optimizations to the existing implementation in jsnark are possible).
- __RSA gadgets__: This includes public key encryption gadgets based on both PKCS #1 V2.2 (OAEP) and PKCS #1 v1.5, and also a signature gadget using PKCS #1 v1.5. Internally, these gadgets used the long integer optimizations used in xJsnark.
- __Block cipher gadgets__: This includes optimized implementations for AES, Speck and Chaskey ciphers.
- __Hybrid Encryption Example__: The circuit main file is in `HybridEncryptionCircuitGenerator.java`. The circuit uses the gadgets defined in `examples/gadgets/diffieHellmanKeyExchange` and `examples/gadgets/blockciphers`, which are for key exchange (using field extension) and symmetric encryption using the speck cipher. Other variants will be added in the future.
- __JUnit Tests__: Some JUnit tests are included for primitive operations, SHA-256 and the encryption gadgets. This can illustrate how to write gadgets and test them.


### Writing Circuits using jsnark

@@ -104,19 +115,17 @@ To summarize the steps needed:
- `runLibsnark()`: This runs the libsnark interface with the two files produced in the last step. This can also be done manually outside the circuit if needed.
- Note: In the executing thread, use one CircuitGenerator per thread at a time. If multiple generators are used in parallel, each needs to be in a separate thread, and the corresponding property value in config.properties need to be adapted.

### Running circuits compiled by Pinocchio on libsnark

- To use Pinocchio directly with libsark, run the interface executable `run_ppzksnark` on the `<circuit name>.arith` and `<circuit name>.in` files. The `<circuit name>.in` should specify the hexadecimal value for each input and nizkinput wire ids, in the following format: `id value`, each on a separate line.
- It is important to assign 1 to the wire denoted as the one wire input in the arithmetic file.

### Comparison with libsnark's gadget libraries

The gadget library of jsnark shares some similarities with the C++ Gadget library of libsnark, but it has some options that could possibly help for writing optimized circuits quickly without specifying all details. If the reader is familiar with the gadget libraries of libsnark, and would like to try jsnark, here are some key points to minimize confusion:
The gadget library of jsnark shares some similarities with the C++ Gadget library of libsnark, but it has some options that could possibly help with writing optimized circuits quickly without specifying all the details. If the reader is familiar with the gadget libraries of libsnark, here are some key points to minimize confusion:
- No need to maintain a distinction between Variables, LinearCombinations, ... etc. The type Wire can be used to represent Variables, LinearCombinations, Constants, .. etc. The library handles the mapping in a later stage.
- Instead of having the notion of primary input and auxiliary input for representing variables, wires in jsnark can be labeled anywhere as either input, output, prover witness wires. Both the input and output wires are public and seen by the verifier (this corresponds to the primary input in libsnark). The prover witness wires refer to the *free* input variables provided by the prover. This is in some sense similar to the way Pinocchio's compiler classifies wires.
- Each Gadget in libsnark requires writing and calling two methods: generateConstraints() to specify the r1cs constraints, and generateWitness() to invoke the witness computation. In jsnark's builder, applying primitive operations on wires generates constraints automatically. Additionally, the witness computation is done automatically for primitive operations, and does not need to be explicitly invoked, except in the case of prover witness computation that has to be done outside the circuit, e.g. the FieldDivisionGadget example.
- Jsnark applies caching and other techniques during circuit construction to cancel unneeded constraints. This helps in code reusability when changing input variables wires to carry constant values instead. This also helps in reducing the complexity when writing optimized circuits. One example is the ``maj`` calculation in the SHA256 gadget, in which jsnark detects similar operations across the loop iterations with little effort from the programmer, resulting in more than 1000 gates savings. ``CachingTest.java`` also illustrates what the caching approach can help with.

### Running circuits compiled by Pinocchio on libsnark

- To use Pinocchio directly with libsark, run the interface executable `run_ppzksnark` on the `<circuit name>.arith` and `<circuit name>.in` files. The `<circuit name>.in` should specify the hexadecimal value for each input and nizkinput wire ids, in the following format: `id value`, each on a separate line.
- It is important to assign 1 to the wire denoted as the one wire input in the arithmetic file.

### Disclaimer

The code is undergoing more testing and integration of other features. The future versions of this library will include more documentation, examples and optimizations.

0 comments on commit 363b22b

Please sign in to comment.
You can’t perform that action at this time.