vdf/lib.rs
1// Copyright 2018 Chia Network Inc and POA Networks Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14#![deny(warnings)]
15//! # Rust implementations of class groups and verifyable delay functions
16//!
17//! This repo includes three crates
18//!
19//! * `classgroup`, which includes a class group implementation, as well as a
20//! trait for class groups.
21//! * `vdf`, which includes a Verifyable Delay Function (VDF) trait, as well as
22//! an implementation of that trait.
23//! * `vdf-cli`, which includes a command-line interface to the `vdf` crate. It
24//! also includes additional commands, which are deprecated and will later be
25//! replaced by a CLI to the `classgroup` crate.
26//!
27//! ## Usage
28//!
29//! First, install Rust, Cargo, and the GNU Multiprecision Library (GMP). Then,
30//! follow one of the below steps.
31//!
32//! ### To use the command line interface
33//!
34//! ```sh
35//! $ git clone https://github.com/poanetwork/vdf
36//! $ cd vdf
37//! $ cargo install
38//! $ vdf-cli aa 100
39//! 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
40//! $ vdf-cli aa 100 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
41//! Proof is valid
42//! ```
43//!
44//! ### To use the VDF library
45//!
46//! ```rust
47//! extern crate vdf;
48//! use vdf::{InvalidProof, PietrzakVDFParams, VDFParams, WesolowskiVDFParams, VDF};
49//! const CORRECT_SOLUTION: &[u8] =
50//! b"\x00\x52\x71\xe8\xf9\xab\x2e\xb8\xa2\x90\x6e\x85\x1d\xfc\xb5\x54\x2e\x41\x73\xf0\x16\
51//! \xb8\x5e\x29\xd4\x81\xa1\x08\xdc\x82\xed\x3b\x3f\x97\x93\x7b\x7a\xa8\x24\x80\x11\x38\
52//! \xd1\x77\x1d\xea\x8d\xae\x2f\x63\x97\xe7\x6a\x80\x61\x3a\xfd\xa3\x0f\x2c\x30\xa3\x4b\
53//! \x04\x0b\xaa\xaf\xe7\x6d\x57\x07\xd6\x86\x89\x19\x3e\x5d\x21\x18\x33\xb3\x72\xa6\xa4\
54//! \x59\x1a\xbb\x88\xe2\xe7\xf2\xf5\xa5\xec\x81\x8b\x57\x07\xb8\x6b\x8b\x2c\x49\x5c\xa1\
55//! \x58\x1c\x17\x91\x68\x50\x9e\x35\x93\xf9\xa1\x68\x79\x62\x0a\x4d\xc4\xe9\x07\xdf\x45\
56//! \x2e\x8d\xd0\xff\xc4\xf1\x99\x82\x5f\x54\xec\x70\x47\x2c\xc0\x61\xf2\x2e\xb5\x4c\x48\
57//! \xd6\xaa\x5a\xf3\xea\x37\x5a\x39\x2a\xc7\x72\x94\xe2\xd9\x55\xdd\xe1\xd1\x02\xae\x2a\
58//! \xce\x49\x42\x93\x49\x2d\x31\xcf\xf2\x19\x44\xa8\xbc\xb4\x60\x89\x93\x06\x5c\x9a\x00\
59//! \x29\x2e\x8d\x3f\x46\x04\xe7\x46\x5b\x4e\xee\xfb\x49\x4f\x5b\xea\x10\x2d\xb3\x43\xbb\
60//! \x61\xc5\xa1\x5c\x7b\xdf\x28\x82\x06\x88\x5c\x13\x0f\xa1\xf2\xd8\x6b\xf5\xe4\x63\x4f\
61//! \xdc\x42\x16\xbc\x16\xef\x7d\xac\x97\x0b\x0e\xe4\x6d\x69\x41\x6f\x9a\x9a\xce\xe6\x51\
62//! \xd1\x58\xac\x64\x91\x5b";
63//!
64//! fn main() {
65//! let pietrzak_vdf = PietrzakVDFParams(2048).new();
66//! assert_eq!(
67//! &pietrzak_vdf.solve(b"\xaa", 100).unwrap()[..],
68//! CORRECT_SOLUTION
69//! );
70//! assert!(pietrzak_vdf.verify(b"\xaa", 100, CORRECT_SOLUTION).is_ok());
71//! }
72//! ```
73//!
74//! ### To run the benchmarks
75//!
76//! Benchmarks are provided for the classgroup operations. Run `cargo bench`
77//! to run them. Additional benchmarks are under development.
78use classgroup;
79
80mod create_discriminant;
81use std::fmt::Debug;
82
83pub use self::{
84 create_discriminant::create_discriminant,
85 proof_pietrzak::{PietrzakVDF, PietrzakVDFParams},
86 proof_wesolowski::{WesolowskiVDF, WesolowskiVDFParams},
87};
88
89/// Message used to report an internal miscalculation of serialization buffer
90/// sizes.
91const INCORRECT_BUFFER_SIZE: &str =
92 "internal error: incorrect buffer size calculation (this is a bug)";
93
94mod proof_of_time;
95mod proof_pietrzak;
96mod proof_wesolowski;
97
98/// An empty struct indicating verification failure.
99///
100/// For security reasons, the functions that perform verification *do not*
101/// return any information on failure. Use `VDF::validate_params` to check if
102/// the parameters are correct.
103#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
104pub struct InvalidProof;
105
106/// An error return indicating an invalid number of iterations. The string is a
107/// human-readable message describing the valid iterations. It should not be
108/// interpreted by programs.
109#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
110pub struct InvalidIterations(String);
111
112/// The type of VDF parameters.
113///
114/// Parameters represent public information that can be shared by all users
115/// of the protocol. As such, they must implement `Clone`, so that they can
116/// be duplicated. They also must implement `Send`, so that a parallel
117/// application can send them safely across threads.
118///
119/// The parameters *do not* include the difficulty level (usually an
120/// iteration count), since that can be separate for each invocation.
121///
122/// This must implement `Clone` and `Eq`.
123pub trait VDFParams: Clone + Eq {
124 type VDF: VDF + Sized;
125
126 /// Creates an instance of this VDF from the given parameters.
127 ///
128 /// # Performance
129 ///
130 /// This method is expected to be fairly cheap. For example, it is okay if
131 /// it allocates memory, but it should not perform expensive computations or
132 /// I/O.
133 ///
134 /// # Panics
135 ///
136 /// This method **MUST NOT** fail due to invalid values for `params`. Such
137 /// errors should be checked by the factory functions for `Self::Params`.
138 ///
139 /// This function **MAY** panic for other reasons. For example, it is
140 /// allowed to panic if an allocation fails, or if a needed external library
141 /// could not be dynamically loaded.
142 fn new(self) -> Self::VDF;
143}
144
145/// A Verifiable Delay Function (VDF).
146///
147/// VDFs are problems that require a certain amount of time to solve, even on a
148/// parallel machine, but can be validated much more easily.
149///
150/// While VDFs are considered to be cryptographic primitives, they generally do
151/// *not* operate on highly sensitive data. As such, implementers of this trait
152/// **do not** guarantee that they will be immune to side-channel attacks, and
153/// consumers of this trait **MUST NOT** expect this.
154///
155/// Instances of this trait are *not* expected to be `Sync`. This allows them
156/// to reuse allocations (such as scratch memory) accross invocations without
157/// the need for locking. However, they **MUST** be `Send` and `Clone`, so that
158/// consumers can duplicate them and send them across threads.
159pub trait VDF: Send + Debug {
160 /// Solve an instance of this VDF, with challenge `challenge` and difficulty
161 /// `difficulty`.
162 ///
163 /// The output is to be returned in a `Vec<u8>`, so it can be stored to disk
164 /// or sent over the network.
165 ///
166 /// # Challenge format
167 ///
168 /// The challenge is an opaque byte string of arbitrary length.
169 /// Implementors **MUST NOT** make any assumptions about its contents,
170 /// and **MUST** produce distinct outputs for distinct challenges
171 /// (except with negiligible probability).
172 ///
173 /// This can be most easily implemented by using the challenge as part of
174 /// the input of a cryptographic hash function. The VDFs provided in this
175 /// crate use this strategy.
176 ///
177 /// The difficulty must be checked before performing any expensive
178 /// computations.
179 ///
180 /// Most applications will generate the challenge using a
181 /// cryptographically-secure pseudorandom number generator, but implementors
182 /// **MUST NOT** rely on this. In particular, this function must be secure
183 /// even if `challenge` is chosen by an adversary. Excessive values for
184 /// `difficulty` may cause excessive resource consumption, but must not
185 /// create any other vulnerabilities.
186 ///
187 /// # Complexity
188 ///
189 /// The VDFs in this crate consume memory that does not depend on
190 /// `difficulty`, and time linearly proportional to `difficulty`.
191 /// Implementors of this trait should document the resource use.
192 ///
193 /// # Purity
194 ///
195 /// This method must have no side effects. In particular, it must be
196 /// **deterministic**: it must always return the same output for the same
197 /// inputs, except with negligible probability. Furthermore, while it may
198 /// change `self` via interior mutability, such changes must not affect
199 /// future calls to this method, `Self::check_difficulty`, or
200 /// `Self::verify`. They *may* affect the `Debug` output.
201 fn solve(&self, challenge: &[u8], difficulty: u64) -> Result<Vec<u8>, InvalidIterations>;
202
203 /// Check that the difficulty is valid.
204 ///
205 /// This must return `Ok` if and only if `difficulty` is valid. Otherwise,
206 /// it must return `Err`.
207 ///
208 /// # Rationale
209 ///
210 /// It would be more ideomatic Rust to use the type system to enforce that a
211 /// difficulty has been validated before use. However, I (Demi) have not
212 /// yet figured out an object-safe way to do so.
213 fn check_difficulty(&self, difficulty: u64) -> Result<(), InvalidIterations>;
214
215 /// Verifies an alleged solution of this VDF, with challenge `challenge` and
216 /// difficulty `difficulty`. Return `Ok(())` on success, or
217 /// `Err(InvalidProof)` on failure.
218 ///
219 /// This function *does not* return any extended error information for
220 /// security reasons. To check that the difficulty is correct, call
221 /// `Self::check_difficulty`.
222 ///
223 /// # Uniqueness of valid solutions
224 ///
225 /// For any `(challenge, difficulty)` tuple, there must be at most one
226 /// `alleged_solution` (as measured by `Eq`) that causes this function to
227 /// return `Ok(())`. If the difficulty is valid (as determined by
228 /// `check_difficulty`), there must be exactly one such solution; otherwise,
229 /// there must be none.
230 ///
231 /// # Purity
232 ///
233 /// This method must have no side effects. In particular, it must be
234 /// **deterministic**: it must always return the same output for the same
235 /// inputs. Furthermore, while it may change `self` via interior
236 /// mutability, such changes must not affect future calls to this method,
237 /// `Self::prove`, or `Self::check_difficulty`. Such changes **MAY** affect
238 /// debugging output.
239 fn verify(
240 &self,
241 challenge: &[u8],
242 difficulty: u64,
243 alleged_solution: &[u8],
244 ) -> Result<(), InvalidProof>;
245}