@ -15,20 +15,12 @@ We now highlight Spartan's distinctive features.
* **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.
* **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.
* **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.
* **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 linear-time prover, a property that has remained elusive for nearly all zkSNARKs in the literature.
* **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`.
* **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`.
* **State-of-the-art performance:**
* **State-of-the-art performance:**
Among transparent SNARKs, Spartan
offers the fastest prover with speedups of 36–152× depending on the baseline,
produces proofs that are shorter by 1.2–416×, and incurs the lowest verification
times with speedups of 3.6–1326×. When compared to the state-of-the-art zkSNARK
with trusted setup, Spartan’s prover is 2× faster for arbitrary R1CS instances and
16× faster for data-parallel workloads.
### Status
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.
Among transparent SNARKs, Spartan offers the fastest prover with speedups of 36–152× depending on the baseline, produces proofs that are shorter by 1.2–416×, and incurs the lowest verification times with speedups of 3.6–1326×. The only exception is proof sizes under Bulletproofs, but Bulletproofs incurs slower verification both asymptotically and concretely. When compared to the state-of-the-art zkSNARK with trusted setup, Spartan’s prover is 2× faster for arbitrary R1CS instances and 16× faster for data-parallel workloads.
### Implementation details
### Implementation details
`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.
`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.
@ -53,7 +45,7 @@ Some of our public APIs' style is inspired by the underlying crates we use.
let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_non_zero_entries);
let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_non_zero_entries);
// ask the library to produce a synthentic R1CS instance
// ask the library to produce a synthentic R1CS instance
let (inst, vars, inputs) = Instance::new(num_cons, num_vars, num_inputs);
let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
// create a commitment to the R1CS instance
// create a commitment to the R1CS instance
let (comm, decomm) = SNARK::encode(&inst, &gens);
let (comm, decomm) = SNARK::encode(&inst, &gens);
@ -86,7 +78,7 @@ Here is another example to use the NIZK variant of the Spartan proof system:
let gens = NIZKGens::new(num_cons, num_vars);
let gens = NIZKGens::new(num_cons, num_vars);
// ask the library to produce a synthentic R1CS instance
// ask the library to produce a synthentic R1CS instance
let (inst, vars, inputs) = Instance::new(num_cons, num_vars, num_inputs);
let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
// produce a proof of satisfiability
// produce a proof of satisfiability
let mut prover_transcript = Transcript::new(b"nizk_example");
let mut prover_transcript = Transcript::new(b"nizk_example");
@ -100,6 +92,153 @@ Here is another example to use the NIZK variant of the Spartan proof system:
# }
# }
```
```
Finally, we provide an example that specifies a custom R1CS instance instead of using a synthetic instance
```rust
# extern crate curve25519_dalek;
# extern crate libspartan;
# extern crate merlin;
# use curve25519_dalek::scalar::Scalar;
# use libspartan::{InputsAssignment, Instance, SNARKGens, VarsAssignment, SNARK};
# use merlin::Transcript;
# use rand::rngs::OsRng;
# fn main() {
// produce a tiny instance
let (
num_cons,
num_vars,
num_inputs,
num_non_zero_entries,
inst,
assignment_vars,
assignment_inputs,
) = produce_tiny_r1cs();
// produce public parameters
let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_non_zero_entries);
// create a commitment to the R1CS instance
let (comm, decomm) = SNARK::encode(&inst, &gens);
// produce a proof of satisfiability
let mut prover_transcript = Transcript::new(b"snark_example");
let proof = SNARK::prove(
&inst,
&decomm,
assignment_vars,
&assignment_inputs,
&gens,
&mut prover_transcript,
);
// verify the proof of satisfiability
let mut verifier_transcript = Transcript::new(b"snark_example");