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:

curve25519-dalek = "1"
zkp = "0.6"

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

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