1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![deny(warnings)]
//! # Rust implementations of class groups and verifyable delay functions
//!
//! This repo includes three crates
//!
//! * `classgroup`, which includes a class group implementation, as well as a
//!   trait for class groups.
//! * `vdf`, which includes a Verifyable Delay Function (VDF) trait, as well as
//!   an implementation of that trait.
//! * `vdf-cli`, which includes a command-line interface to the `vdf` crate.  It
//!   also includes additional commands, which are deprecated and will later be
//!   replaced by a CLI to the `classgroup` crate.
//!
//! ## Usage
//!
//! First, install Rust, Cargo, and the GNU Multiprecision Library (GMP).  Then,
//! follow one of the below steps.
//!
//! ### To use the command line interface
//!
//! ```sh
//! $ git clone https://github.com/poanetwork/vdf
//! $ cd vdf
//! $ cargo install
//! $ vdf-cli aa 100
//! 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
//! $ vdf-cli aa 100 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
//! Proof is valid
//! ```
//!
//! ### To use the VDF library
//!
//! ```rust
//! extern crate vdf;
//! use vdf::{InvalidProof, PietrzakVDFParams, VDFParams, WesolowskiVDFParams, VDF};
//! const CORRECT_SOLUTION: &[u8] =
//!     b"\x00\x52\x71\xe8\xf9\xab\x2e\xb8\xa2\x90\x6e\x85\x1d\xfc\xb5\x54\x2e\x41\x73\xf0\x16\
//!     \xb8\x5e\x29\xd4\x81\xa1\x08\xdc\x82\xed\x3b\x3f\x97\x93\x7b\x7a\xa8\x24\x80\x11\x38\
//!     \xd1\x77\x1d\xea\x8d\xae\x2f\x63\x97\xe7\x6a\x80\x61\x3a\xfd\xa3\x0f\x2c\x30\xa3\x4b\
//!     \x04\x0b\xaa\xaf\xe7\x6d\x57\x07\xd6\x86\x89\x19\x3e\x5d\x21\x18\x33\xb3\x72\xa6\xa4\
//!     \x59\x1a\xbb\x88\xe2\xe7\xf2\xf5\xa5\xec\x81\x8b\x57\x07\xb8\x6b\x8b\x2c\x49\x5c\xa1\
//!     \x58\x1c\x17\x91\x68\x50\x9e\x35\x93\xf9\xa1\x68\x79\x62\x0a\x4d\xc4\xe9\x07\xdf\x45\
//!     \x2e\x8d\xd0\xff\xc4\xf1\x99\x82\x5f\x54\xec\x70\x47\x2c\xc0\x61\xf2\x2e\xb5\x4c\x48\
//!     \xd6\xaa\x5a\xf3\xea\x37\x5a\x39\x2a\xc7\x72\x94\xe2\xd9\x55\xdd\xe1\xd1\x02\xae\x2a\
//!     \xce\x49\x42\x93\x49\x2d\x31\xcf\xf2\x19\x44\xa8\xbc\xb4\x60\x89\x93\x06\x5c\x9a\x00\
//!     \x29\x2e\x8d\x3f\x46\x04\xe7\x46\x5b\x4e\xee\xfb\x49\x4f\x5b\xea\x10\x2d\xb3\x43\xbb\
//!     \x61\xc5\xa1\x5c\x7b\xdf\x28\x82\x06\x88\x5c\x13\x0f\xa1\xf2\xd8\x6b\xf5\xe4\x63\x4f\
//!     \xdc\x42\x16\xbc\x16\xef\x7d\xac\x97\x0b\x0e\xe4\x6d\x69\x41\x6f\x9a\x9a\xce\xe6\x51\
//!     \xd1\x58\xac\x64\x91\x5b";
//!
//! fn main() {
//!     let pietrzak_vdf = PietrzakVDFParams(2048).new();
//!     assert_eq!(
//!         &pietrzak_vdf.solve(b"\xaa", 100).unwrap()[..],
//!         CORRECT_SOLUTION
//!     );
//!     assert!(pietrzak_vdf.verify(b"\xaa", 100, CORRECT_SOLUTION).is_ok());
//! }
//! ```
//!
//! ### To run the benchmarks
//!
//! Benchmarks are provided for the classgroup operations.  Run `cargo bench`
//! to run them.  Additional benchmarks are under development.
use classgroup;

mod create_discriminant;
use std::fmt::Debug;

pub use self::{
    create_discriminant::create_discriminant,
    proof_pietrzak::{PietrzakVDF, PietrzakVDFParams},
    proof_wesolowski::{WesolowskiVDF, WesolowskiVDFParams},
};

/// Message used to report an internal miscalculation of serialization buffer
/// sizes.
const INCORRECT_BUFFER_SIZE: &str =
    "internal error: incorrect buffer size calculation (this is a bug)";

mod proof_of_time;
mod proof_pietrzak;
mod proof_wesolowski;

/// An empty struct indicating verification failure.
///
/// For security reasons, the functions that perform verification *do not*
/// return any information on failure.  Use `VDF::validate_params` to check if
/// the parameters are correct.
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
pub struct InvalidProof;

/// An error return indicating an invalid number of iterations.  The string is a
/// human-readable message describing the valid iterations.  It should not be
/// interpreted by programs.
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
pub struct InvalidIterations(String);

/// The type of VDF parameters.
///
/// Parameters represent public information that can be shared by all users
/// of the protocol.  As such, they must implement `Clone`, so that they can
/// be duplicated.  They also must implement `Send`, so that a parallel
/// application can send them safely across threads.
///
/// The parameters *do not* include the difficulty level (usually an
/// iteration count), since that can be separate for each invocation.
///
/// This must implement `Clone` and `Eq`.
pub trait VDFParams: Clone + Eq {
    type VDF: VDF + Sized;

    /// Creates an instance of this VDF from the given parameters.
    ///
    /// # Performance
    ///
    /// This method is expected to be fairly cheap.  For example, it is okay if
    /// it allocates memory, but it should not perform expensive computations or
    /// I/O.
    ///
    /// # Panics
    ///
    /// This method **MUST NOT** fail due to invalid values for `params`.  Such
    /// errors should be checked by the factory functions for `Self::Params`.
    ///
    /// This function **MAY** panic for other reasons.  For example, it is
    /// allowed to panic if an allocation fails, or if a needed external library
    /// could not be dynamically loaded.
    fn new(self) -> Self::VDF;
}

/// A Verifiable Delay Function (VDF).
///
/// VDFs are problems that require a certain amount of time to solve, even on a
/// parallel machine, but can be validated much more easily.
///
/// While VDFs are considered to be cryptographic primitives, they generally do
/// *not* operate on highly sensitive data.  As such, implementers of this trait
/// **do not** guarantee that they will be immune to side-channel attacks, and
/// consumers of this trait **MUST NOT** expect this.
///
/// Instances of this trait are *not* expected to be `Sync`.  This allows them
/// to reuse allocations (such as scratch memory) accross invocations without
/// the need for locking.  However, they **MUST** be `Send` and `Clone`, so that
/// consumers can duplicate them and send them across threads.
pub trait VDF: Send + Debug {
    /// Solve an instance of this VDF, with challenge `challenge` and difficulty
    /// `difficulty`.
    ///
    /// The output is to be returned in a `Vec<u8>`, so it can be stored to disk
    /// or sent over the network.
    ///
    /// # Challenge format
    ///
    /// The challenge is an opaque byte string of arbitrary length.
    /// Implementors **MUST NOT** make any assumptions about its contents,
    /// and **MUST** produce distinct outputs for distinct challenges
    /// (except with negiligible probability).
    ///
    /// This can be most easily implemented by using the challenge as part of
    /// the input of a cryptographic hash function.  The VDFs provided in this
    /// crate use this strategy.
    ///
    /// The difficulty must be checked before performing any expensive
    /// computations.
    ///
    /// Most applications will generate the challenge using a
    /// cryptographically-secure pseudorandom number generator, but implementors
    /// **MUST NOT** rely on this.  In particular, this function must be secure
    /// even if `challenge` is chosen by an adversary.  Excessive values for
    /// `difficulty` may cause excessive resource consumption, but must not
    /// create any other vulnerabilities.
    ///
    /// # Complexity
    ///
    /// The VDFs in this crate consume memory that does not depend on
    /// `difficulty`, and time linearly proportional to `difficulty`.
    /// Implementors of this trait should document the resource use.
    ///
    /// # Purity
    ///
    /// This method must have no side effects.  In particular, it must be
    /// **deterministic**: it must always return the same output for the same
    /// inputs, except with negligible probability.  Furthermore, while it may
    /// change `self` via interior mutability, such changes must not affect
    /// future calls to this method, `Self::check_difficulty`, or
    /// `Self::verify`.  They *may* affect the `Debug` output.
    fn solve(&self, challenge: &[u8], difficulty: u64) -> Result<Vec<u8>, InvalidIterations>;

    /// Check that the difficulty is valid.
    ///
    /// This must return `Ok` if and only if `difficulty` is valid.  Otherwise,
    /// it must return `Err`.
    ///
    /// # Rationale
    ///
    /// It would be more ideomatic Rust to use the type system to enforce that a
    /// difficulty has been validated before use.  However, I (Demi) have not
    /// yet figured out an object-safe way to do so.
    fn check_difficulty(&self, difficulty: u64) -> Result<(), InvalidIterations>;

    /// Verifies an alleged solution of this VDF, with challenge `challenge` and
    /// difficulty `difficulty`.  Return `Ok(())` on success, or
    /// `Err(InvalidProof)` on failure.
    ///
    /// This function *does not* return any extended error information for
    /// security reasons.  To check that the difficulty is correct, call
    /// `Self::check_difficulty`.
    ///
    /// # Uniqueness of valid solutions
    ///
    /// For any `(challenge, difficulty)` tuple, there must be at most one
    /// `alleged_solution` (as measured by `Eq`) that causes this function to
    /// return `Ok(())`.  If the difficulty is valid (as determined by
    /// `check_difficulty`), there must be exactly one such solution; otherwise,
    /// there must be none.
    ///
    /// # Purity
    ///
    /// This method must have no side effects.  In particular, it must be
    /// **deterministic**: it must always return the same output for the same
    /// inputs.  Furthermore, while it may change `self` via interior
    /// mutability, such changes must not affect future calls to this method,
    /// `Self::prove`, or `Self::check_difficulty`.  Such changes **MAY** affect
    /// debugging output.
    fn verify(
        &self,
        challenge: &[u8],
        difficulty: u64,
        alleged_solution: &[u8],
    ) -> Result<(), InvalidProof>;
}