# Curdleproofs
[Curdleproofs](https://github.com/asn-d6/curdleproofs/blob/main/doc/curdleproofs.pdf) is a *zero-knowledge shuffle argument* inspired by [BG12](http://www0.cs.ucl.ac.uk/staff/J.Groth/MinimalShuffle.pdf).
Zero-knowledge shuffle arguments can have multiple use cases:
- [Secret leader election](https://ethresear.ch/t/whisk-a-practical-shuffle-based-ssle-protocol-for-ethereum/11763) protocols
- Message shuffling in [mixnets](https://eprint.iacr.org/2020/490.pdf)
- Universally verifiable [electronic voting](https://web.cs.ucdavis.edu/~franklin/ecs228/2013/neff_2001.pdf) protocols
## Documentation
The user-facing documentation for this library can be [found here](https://docs.rs/curdleproofs).
In this library, we provide high-level protocol documentation for the core [`curdleproofs`] shuffle argument and its sub-arguments:
- [`same_scalar_argument`]
- [`same_permutation_argument`]
- [`grand_product_argument`]
- [`inner_product_argument`]
- [`same_multiscalar_argument`]
There are also notes on the [optimizations deployed](crate::notes::optimizations) to speed up the verifier.
For all the details and the security proofs, please see the [Curdleproofs paper](https://github.com/asn-d6/curdleproofs/blob/main/doc/curdleproofs.pdf).
## Performance
The following table gives the proof size as well as timings for proving and verifying Curdleproofs on an `Intel i7-8550U CPU @ 1.80GHz` over the BLS12-381 curve:
| Shuffled Elements | Proving (ms) | Verification (ms) | Shuffling (ms): | Proof Size (bytes) |
|------------------:|-------------:|------------------:|----------------:|-------------------:|
| 60 | 177 | 22 | 28 | 3968 |
| 124 | 304 | 27 | 57 | 4448 |
| 252 | 560 | 35 | 121 | 4928 |
_(The number of shuffled elements above is disturbingly close to a power of two but not quite, because we reserve four elements for zero-knowledge blinders.)_
## Example
The following example shows how to create and verify a shuffle proof that shuffles 28 elements:
```rust
# // The #-commented lines are hidden in Rustdoc but not in raw
# // markdown rendering, and contain boilerplate code so that the
# // code in the README.md is actually run as part of the test suite.
#
# use ark_std::rand::prelude::SliceRandom;
# use ark_std::UniformRand;
# use ark_bls12_381::Fr;
# use ark_bls12_381::G1Affine;
# use ark_bls12_381::G1Projective;
# use ark_ec::ProjectiveCurve;
# use ark_std::rand::{rngs::StdRng, SeedableRng};
# use core::iter;
#
# use curdleproofs::N_BLINDERS;
# use curdleproofs::curdleproofs::{CurdleproofsProof, generate_crs};
# use curdleproofs::util::shuffle_permute_and_commit_input;
#
# fn main() {
let mut rng = StdRng::seed_from_u64(0u64);
// Number of elements we are shuffling
let ell = 28;
// Construct the CRS
let crs = generate_crs(ell);
// Generate some witnesses: the permutation and the randomizer
let mut permutation: Vec = (0..ell as u32).collect();
permutation.shuffle(&mut rng);
let k = Fr::rand(&mut rng);
// Generate some shuffle input vectors
let vec_R: Vec = iter::repeat_with(|| G1Projective::rand(&mut rng).into_affine())
.take(ell)
.collect();
let vec_S: Vec = iter::repeat_with(|| G1Projective::rand(&mut rng).into_affine())
.take(ell)
.collect();
// Shuffle and permute inputs to generate output vectors and permutation commitments
let (vec_T, vec_U, M, vec_m_blinders) =
shuffle_permute_and_commit_input(&crs, &vec_R, &vec_S, &permutation, &k, &mut rng);
// Generate a shuffle proof
let shuffle_proof = CurdleproofsProof::new(
&crs,
vec_R.clone(),
vec_S.clone(),
vec_T.clone(),
vec_U.clone(),
M,
permutation,
k,
vec_m_blinders,
&mut rng,
);
// Verify the shuffle proof
assert!(shuffle_proof
.verify(&crs, &vec_R, &vec_S, &vec_T, &vec_U, &M, &mut rng)
.is_ok());
# }
```
## Building & Running
This library can be compiled with `cargo build` and requires rust nightly.
You can run the tests using `cargo test --release` and the benchmarks using `cargo bench`.