You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

243 lines
9.7 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. # Spartan: High-speed zkSNARKs without trusted setup
  2. ![Rust](https://github.com/microsoft/Spartan/workflows/Rust/badge.svg)
  3. Spartan is a high-speed zero-knowledge proof system, a cryptographic primitive that enables a prover to prove a mathematical statement to a verifier without revealing anything besides the validity of the statement. This repository provides `libspartan`, a Rust library that implements a zero-knowledge succinct non-interactive argument of knowledge (zkSNARK), which is a type of zero-knowledge proof system with short proofs and fast verification times. The details of the Spartan proof system are described in our [paper](https://eprint.iacr.org/2019/550) published at [CRYPTO 2020](https://crypto.iacr.org/2020/).
  4. A simple example application is proving the knowledge of a secret s such that H(s) == d for a public d, where H is a cryptographic hash function (e.g., SHA-256, Keccak). A more complex application is a stateful cloud service that produces proofs of correct state machine transitions for auditability. See this [paper](https://eprint.iacr.org/2020/758.pdf) for details.
  5. Note that this library has *not* received a security review or audit.
  6. ## Highlights
  7. We now highlight Spartan's distinctive features.
  8. * **No "toxic" waste:** Spartan is a *transparent* zkSNARK and does not require a trusted setup. So, it does not involve any trapdoors that must be kept secret or require a multi-party ceremony to produce public parameters.
  9. * **General-purpose:** Spartan produces proofs for arbitrary NP statements. `libspartan` supports NP statements expressed as rank-1 constraint satisfiability (R1CS) instances, a popular language for which there exists efficient transformations and compiler toolchains from high-level programs of interest.
  10. * **Sub-linear verification costs and linear-time proving costs:** Spartan is the first transparent proof system with sub-linear verification costs for arbitrary NP statements (e.g., R1CS). Spartan also features a time-optimal prover, a property that has remained elusive for nearly all zkSNARKs in the literature.
  11. * **Standardized security:** Spartan's security relies on the hardness of computing discrete logarithms (a standard cryptographic assumption) in the random oracle model. `libspartan` uses `ristretto255`, a prime-order group abstraction atop `curve25519` (a high-speed elliptic curve). We use [`curve25519-dalek`](https://docs.rs/curve25519-dalek) for arithmetic over `ristretto255`.
  12. * **State-of-the-art performance:**
  13. Among transparent SNARKs, Spartan
  14. offers the fastest prover with speedups of 36–152× depending on the baseline,
  15. produces proofs that are shorter by 1.2–416×, and incurs the lowest verification
  16. times with speedups of 3.6–1326×. When compared to the state-of-the-art zkSNARK
  17. with trusted setup, Spartan’s prover is 2× faster for arbitrary R1CS instances and
  18. 16× faster for data-parallel workloads.
  19. ### Status
  20. Development is ongoing (PRs are welcome!). For example, the library does not yet offer APIs to specify an NP statement, but we will in the future offer standardized APIs and also integrate with a compiler that produces R1CS instances from high level programs.
  21. ### Implementation details
  22. `libspartan` uses [`merlin`](https://docs.rs/merlin/) to automate the Fiat-Shamir transform. We also introduce a new type called `RandomTape` that extends a `Transcript` in `merlin` to allow the prover's internal methods to produce private randomness using its private transcript without having to create `OsRng` objects throughout the code. An object of type `RandomTape` is initialized with a new random seed from `OsRng` for each proof produced by the library.
  23. ## Examples
  24. The following example shows how to use `libspartan` to create and verify a SNARK proof.
  25. Some of our public APIs' style is inspired by the underlying crates we use.
  26. ```rust
  27. # extern crate libspartan;
  28. # extern crate merlin;
  29. # use libspartan::{Instance, SNARKGens, SNARK};
  30. # use merlin::Transcript;
  31. # fn main() {
  32. // specify the size of an R1CS instance
  33. let num_vars = 1024;
  34. let num_cons = 1024;
  35. let num_inputs = 10;
  36. let num_non_zero_entries = 1024;
  37. // produce public parameters
  38. let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_non_zero_entries);
  39. // ask the library to produce a synthentic R1CS instance
  40. let (inst, vars, inputs) = Instance::new(num_cons, num_vars, num_inputs);
  41. // create a commitment to the R1CS instance
  42. let (comm, decomm) = SNARK::encode(&inst, &gens);
  43. // produce a proof of satisfiability
  44. let mut prover_transcript = Transcript::new(b"snark_example");
  45. let proof = SNARK::prove(&inst, &decomm, vars, &inputs, &gens, &mut prover_transcript);
  46. // verify the proof of satisfiability
  47. let mut verifier_transcript = Transcript::new(b"snark_example");
  48. assert!(proof
  49. .verify(&comm, &inputs, &mut verifier_transcript, &gens)
  50. .is_ok());
  51. # }
  52. ```
  53. Here is another example to use the NIZK variant of the Spartan proof system:
  54. ```rust
  55. # extern crate libspartan;
  56. # extern crate merlin;
  57. # use libspartan::{Instance, NIZKGens, NIZK};
  58. # use merlin::Transcript;
  59. # fn main() {
  60. // specify the size of an R1CS instance
  61. let num_vars = 1024;
  62. let num_cons = 1024;
  63. let num_inputs = 10;
  64. // produce public parameters
  65. let gens = NIZKGens::new(num_cons, num_vars);
  66. // ask the library to produce a synthentic R1CS instance
  67. let (inst, vars, inputs) = Instance::new(num_cons, num_vars, num_inputs);
  68. // produce a proof of satisfiability
  69. let mut prover_transcript = Transcript::new(b"nizk_example");
  70. let proof = NIZK::prove(&inst, vars, &inputs, &gens, &mut prover_transcript);
  71. // verify the proof of satisfiability
  72. let mut verifier_transcript = Transcript::new(b"nizk_example");
  73. assert!(proof
  74. .verify(&inst, &inputs, &mut verifier_transcript, &gens)
  75. .is_ok());
  76. # }
  77. ```
  78. ## Building `libspartan`
  79. Install [`rustup`](https://rustup.rs/)
  80. Switch to nightly Rust using `rustup`:
  81. ```text
  82. rustup default nightly
  83. ```
  84. Clone the repository:
  85. ```text
  86. git clone https://github.com/Microsoft/Spartan
  87. cd Spartan
  88. ```
  89. To build docs for public APIs of `libspartan`:
  90. ```text
  91. cargo doc
  92. ```
  93. To run tests:
  94. ```text
  95. RUSTFLAGS="-C target_cpu=native" cargo test
  96. ```
  97. To build `libspartan`:
  98. ```text
  99. RUSTFLAGS="-C target_cpu=native" cargo build --release
  100. ```
  101. > NOTE: We enable SIMD instructions in `curve25519-dalek` by default, so if it fails to build remove the "simd_backend" feature argument in `Cargo.toml`.
  102. ### Supported features
  103. * `profile`: enables fine-grained profiling information (see below for its use)
  104. ## Performance
  105. ### End-to-end benchmarks
  106. `libspartan` includes two benches: `benches/nizk.rs` and `benches/snark.rs`. If you report the performance of Spartan in a research paper, we recommend using these benches for higher accuracy instead of fine-grained profiling (listed below).
  107. To run end-to-end benchmarks:
  108. ```text
  109. RUSTFLAGS="-C target_cpu=native" cargo bench
  110. ```
  111. ### Fine-grained profiling
  112. Build `libspartan` with `profile` feature enabled. It creates two profilers: `./target/release/snark` and `./target/release/nizk`.
  113. These profilers report performance as depicted below (for varying R1CS instance sizes). The reported
  114. performance is from running the profilers on a Microsoft Surface Laptop 3 on a single CPU core of Intel Core i7-1065G7 running Ubuntu 20.04 (atop WSL2 on Windows 10).
  115. See Section 8 in our [paper](https://eprint.iacr.org/2019/550) to see how this compares with other zkSNARKs in the literature.
  116. ```text
  117. $ ./target/release/snark
  118. Profiler:: SNARK
  119. * number_of_constraints 1048576
  120. * number_of_variables 1048576
  121. * number_of_inputs 10
  122. * number_non-zero_entries_A 1048576
  123. * number_non-zero_entries_B 1048576
  124. * number_non-zero_entries_C 1048576
  125. * SNARK::encode
  126. * SNARK::encode 14.2644201s
  127. * SNARK::prove
  128. * R1CSProof::prove
  129. * polycommit
  130. * polycommit 2.7175848s
  131. * prove_sc_phase_one
  132. * prove_sc_phase_one 683.7481ms
  133. * prove_sc_phase_two
  134. * prove_sc_phase_two 846.1056ms
  135. * polyeval
  136. * polyeval 193.4216ms
  137. * R1CSProof::prove 4.4416193s
  138. * len_r1cs_sat_proof 47024
  139. * eval_sparse_polys
  140. * eval_sparse_polys 377.357ms
  141. * R1CSEvalProof::prove
  142. * commit_nondet_witness
  143. * commit_nondet_witness 14.4507331s
  144. * build_layered_network
  145. * build_layered_network 3.4360521s
  146. * evalproof_layered_network
  147. * len_product_layer_proof 64712
  148. * evalproof_layered_network 15.5708066s
  149. * R1CSEvalProof::prove 34.2930559s
  150. * len_r1cs_eval_proof 133720
  151. * SNARK::prove 39.1297568s
  152. * SNARK::proof_compressed_len 141768
  153. * SNARK::verify
  154. * verify_sat_proof
  155. * verify_sat_proof 20.0828ms
  156. * verify_eval_proof
  157. * verify_polyeval_proof
  158. * verify_prod_proof
  159. * verify_prod_proof 1.1847ms
  160. * verify_hash_proof
  161. * verify_hash_proof 81.06ms
  162. * verify_polyeval_proof 82.3583ms
  163. * verify_eval_proof 82.8937ms
  164. * SNARK::verify 103.0536ms
  165. ```
  166. ```text
  167. $ ./target/release/nizk
  168. Profiler:: NIZK
  169. * number_of_constraints 1048576
  170. * number_of_variables 1048576
  171. * number_of_inputs 10
  172. * number_non-zero_entries_A 1048576
  173. * number_non-zero_entries_B 1048576
  174. * number_non-zero_entries_C 1048576
  175. * NIZK::prove
  176. * R1CSProof::prove
  177. * polycommit
  178. * polycommit 2.7220635s
  179. * prove_sc_phase_one
  180. * prove_sc_phase_one 722.5487ms
  181. * prove_sc_phase_two
  182. * prove_sc_phase_two 862.6796ms
  183. * polyeval
  184. * polyeval 190.2233ms
  185. * R1CSProof::prove 4.4982305s
  186. * len_r1cs_sat_proof 47024
  187. * NIZK::prove 4.5139888s
  188. * NIZK::proof_compressed_len 48134
  189. * NIZK::verify
  190. * eval_sparse_polys
  191. * eval_sparse_polys 395.0847ms
  192. * verify_sat_proof
  193. * verify_sat_proof 19.286ms
  194. * NIZK::verify 414.5102ms
  195. ```
  196. ## LICENSE
  197. See [LICENSE](./LICENSE)
  198. ## Contributing
  199. See [CONTRIBUTING](./CONTRIBUTING.md)