zkp: a toolkit for Schnorr proofs

Henry de Valence
2 min readMar 29, 2019

--

About two years ago, I made a proof-of-concept library called zkp, which used Rust macros to auto-generate an implementation of proving and verification for a class of Schnorr-style discrete logarithm proof statements. However, this approach had a number of limitations and wasn’t suitable for use in real applications. Today, I published a new and completely rewritten version of the library, which is now available on crates.io.

The new implementation contains a lower-level, Bellman-inspired programmable constraint system API, which allows imperative specification of proof statements, as well as a higher-level macro, which allows declarative specification of proof statements using a DSL that resembles mathematical notation:

define_proof! {
vrf_proof, // Name of the module for generated implementation
"VRF", // Label for the proof statement
(x), // Secret variables
(A, G, H), // Public variables unique to each proof
(B) : // Public variables common between proofs
A = (x * B), // Statements to prove
G = (x * H)
}

This macro expands into a module containing an implementation of proving, verification, batch verification, and benchmarks for the proof statement. Proving uses constant-time implementations, and the proofs have a derived implementation of (memory-safe) serialization and deserialization via Serde.

The repository’s tests directory contains examples of how to use both the higher-level and lower-level APIs:

  • a specification of an “anonymous credential presentation with 10 hidden attributes” proof from CMZ’13. Thanks to the choice of group, as well as the backend optimization work I did, the generated implementation performs verification between 20 to 40 times faster than the benchmark numbers reported in that paper.
  • A transcript-based signature and VRF construction with an auto-generated implementation. This includes an example of using the online interactive composition described in the Merlin blog post to provide chained signatures between two counterparties.
  • An example of using the lower-level constraint system API manually.

Using the API

To experiment with the API, add the crates to Cargo.toml:

[dependencies]
curve25519-dalek = "1"
zkp = "0.6"

then add the crates to lib.rs (or main.rs):

#[macro_use]
extern crate zkp;
extern crate curve25519_dalek;

The documentation on the new API can be found on doc.dalek.rs or on docs.rs. After generating an implementation with the define_proof macro, the documentation on how to use the generated code will appear in your crates’ documentation. Here’s an example of one way to use it:

What’s next

I’m hoping to streamline the API a little bit and release 1.0 soon. If this toolkit seems like it would be useful to you, please try out the API and leave comments on the issue tracker!

--

--

Henry de Valence

interested in zero-knowledge, privacy, freedom, mathematics, & the number 24