diff --git a/README.md b/README.md index 01af25b..aa9fb2b 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Note that nightly compilers after `nightly-2024-02-04` will [not work](https://g You can examine performance using the benchmarks: either `cargo bench` or `cargo +nightly-2024-02-04 bench`. Proofs support a custom serialization format designed to be efficient and canonical. -This functionality has an associated fuzzer that can be run using a nightly compiler: `cargo +nightly-2024-02-04 fuzz run proofs` +This functionality has an associated fuzzer that can be run using a nightly compiler: `cargo +nightly-2024-02-04 fuzz run proofs`. ## Warning diff --git a/src/lib.rs b/src/lib.rs index ec07656..9e1c948 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,7 @@ //! //! Proofs support a custom serialization format designed to be efficient and canonical. //! This functionality has an associated fuzzer that can be run using a nightly compiler: `cargo +nightly-2024-02-04 -//! fuzz run proofs` +//! fuzz run proofs`. //! //! # Warning //! diff --git a/src/parameters.rs b/src/parameters.rs index 9786f25..7625b8b 100644 --- a/src/parameters.rs +++ b/src/parameters.rs @@ -16,8 +16,8 @@ use snafu::prelude::*; /// Public parameters used for generating and verifying Triptych proofs. /// /// Parameters require a base and exponent that define the size of verification key vectors, as well as group generators -/// `G` and `U` required by the protocol. You can either use `new` to have these generators defined securely for you, or -/// use `new_with_generators` if your use case requires specific values for these. +/// `G` and `U` required by the protocol. You can either use [`Parameters::new`] to have these generators defined +/// securely for you, or use [`Parameters::new_with_generators`] if your use case requires specific values for these. #[allow(non_snake_case)] #[derive(Clone, Eq, PartialEq)] pub struct Parameters { @@ -30,7 +30,7 @@ pub struct Parameters { hash: Vec, } -/// Errors that can arise relating to `Parameters`. +/// Errors that can arise relating to [`Parameters`]. #[derive(Debug, Snafu)] pub enum ParameterError { /// An invalid parameter was provided. @@ -39,13 +39,13 @@ pub enum ParameterError { } impl Parameters { - /// Generate new parameters for Triptych proofs. + /// Generate new [`Parameters`] for Triptych proofs. /// /// The base `n > 1` and exponent `m > 1` define the size of verification key vectors, so it must be the case that - /// `n**m` does not overflow `u32`. If any of these conditions is not met, returns an error. + /// `n**m` does not overflow [`prim@u32`]. If any of these conditions is not met, returns a [`ParameterError`]. /// /// This function produces group generators `G` and `U` for you. - /// If your use case requires specific generators, use `new_with_generators` instead. + /// If your use case requires specific generators, use [`Parameters::new_with_generators`] instead. #[allow(non_snake_case)] pub fn new(n: u32, m: u32) -> Result { // Use the default base point for `G` (this is arbitrary) @@ -61,17 +61,17 @@ impl Parameters { Self::new_with_generators(n, m, &G, &U) } - /// Generate new parameters for Triptych proofs. + /// Generate new [`Parameters`] for Triptych proofs. /// /// The base `n > 1` and exponent `m > 1` define the size of verification key vectors, so it must be the case that - /// `n**m` does not overflow `u32`. If any of these conditions is not met, returns an error. + /// `n**m` does not overflow [`prim@u32`]. If any of these conditions is not met, returns a [`ParameterError`]. /// /// You must also provide independent group generators `G` and `U`: /// - The generator `G` is used to define verification keys. /// - The generator `U` is used to define linking tags. /// /// The security of these generators cannot be checked by this function. - /// If you'd rather have the generators securely defined for you, use `new` instead. + /// If you'd rather have the generators securely defined for you, use [`Parameters::new`] instead. #[allow(non_snake_case)] pub fn new_with_generators(n: u32, m: u32, G: &RistrettoPoint, U: &RistrettoPoint) -> Result { // These bounds are required by the protocol @@ -154,7 +154,7 @@ impl Parameters { } } - /// Get the group generator `G` from these parameters. + /// Get the group generator `G` from these [`Parameters`]. /// /// This is the generator used for defining verification keys. #[allow(non_snake_case)] @@ -162,7 +162,7 @@ impl Parameters { &self.G } - /// Get the group generator `U` from these parameters. + /// Get the group generator `U` from these [`Parameters`]. /// /// This is the generator used for defining linking tags. #[allow(non_snake_case)] @@ -170,21 +170,21 @@ impl Parameters { &self.U } - /// Get the value `n` from these parameters. + /// Get the value `n` from these [`Parameters`]. /// /// This is the base used for defining the verification key vector size. pub fn get_n(&self) -> u32 { self.n } - /// Get the value `m` from these parameters. + /// Get the value `m` from these [`Parameters`]. /// /// This is the exponent used for defining the verification key vector size. pub fn get_m(&self) -> u32 { self.m } - /// Get the value `N == n**m` from these parameters. + /// Get the value `N == n**m` from these [`Parameters`]. /// /// This is the verification key vector size. #[allow(non_snake_case)] @@ -193,19 +193,19 @@ impl Parameters { self.n.pow(self.m) } - /// Get the value `CommitmentG` from these parameters. + /// Get the value `CommitmentG` from these [`Parameters`]. #[allow(non_snake_case)] pub(crate) fn get_CommitmentG(&self) -> &Vec { &self.CommitmentG } - /// Get the value `CommitmentH` from these parameters. + /// Get the value `CommitmentH` from these [`Parameters`]. #[allow(non_snake_case)] pub(crate) fn get_CommitmentH(&self) -> &RistrettoPoint { &self.CommitmentH } - /// Get a cryptographic hash representation of these parameters, suitable for transcripting. + /// Get a cryptographic hash representation of these [`Parameters`], suitable for transcripting. pub(crate) fn get_hash(&self) -> &[u8] { &self.hash } diff --git a/src/proof.rs b/src/proof.rs index 93de62d..0f61a83 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -44,7 +44,7 @@ pub struct Proof { z: Scalar, } -/// Errors that can arise relating to proofs. +/// Errors that can arise relating to [`Proof`]. #[derive(Debug, Snafu)] pub enum ProofError { /// An invalid parameter was provided. @@ -91,13 +91,15 @@ fn xi_powers(transcript: &mut Transcript, m: u32) -> Result, ProofEr } impl Proof { - /// Generate a Triptych proof, throwing constant-time operations out the window. + /// Generate a Triptych [`Proof`]. /// - /// The proof is generated by supplying a witness `witness` and corresponding statement `statement`. + /// The proof is generated by supplying a [`Witness`] `witness` and corresponding [`Statement`] `statement`. /// If the witness and statement do not share the same parameters, or if the statement is invalid for the witness, - /// returns an error. + /// returns a [`ProofError`]. /// - /// You must also supply a Merlin `transcript`. + /// This function provides a cryptographically-secure random number generator for you. + /// + /// You must also supply a [`Transcript`] `transcript`. /// /// This function specifically avoids constant-time operations for efficiency. #[cfg(feature = "rand")] @@ -111,13 +113,13 @@ impl Proof { Self::prove_internal(witness, statement, &mut OsRng, transcript, true) } - /// Generate a Triptych proof, throwing constant-time operations out the window. + /// Generate a Triptych [`Proof`]. /// - /// The proof is generated by supplying a witness `witness` and corresponding statement `statement`. + /// The proof is generated by supplying a [`Witness`] `witness` and corresponding [`Statement`] `statement`. /// If the witness and statement do not share the same parameters, or if the statement is invalid for the witness, - /// returns an error. + /// returns a [`ProofError`]. /// - /// You must also supply a cryptographically-secure random number generator `rng` and a Merlin `transcript`. + /// You must also supply a [`CryptoRngCore`] random number generator `rng` and a [`Transcript`] `transcript`. /// /// This function specifically avoids constant-time operations for efficiency. pub fn prove_with_rng_vartime( @@ -129,18 +131,17 @@ impl Proof { Self::prove_internal(witness, statement, rng, transcript, true) } - /// Generate a Triptych proof. + /// Generate a Triptych [`Proof`]. /// - /// The proof is generated by supplying a witness `witness` and corresponding statement `statement`. + /// The proof is generated by supplying a [`Witness`] `witness` and corresponding [`Statement`] `statement`. /// If the witness and statement do not share the same parameters, or if the statement is invalid for the witness, - /// returns an error. + /// returns a [`ProofError`]. /// /// This function provides a cryptographically-secure random number generator for you. /// - /// You must also supply a Merlin `transcript`. + /// You must also supply a [`Transcript`] `transcript`. /// - /// This function makes some attempt at avoiding timing side-channel attacks. - /// operations. + /// This function makes some attempt at avoiding timing side-channel attacks using constant-time operations. #[cfg(feature = "rand")] pub fn prove(witness: &Witness, statement: &Statement, transcript: &mut Transcript) -> Result { use rand_core::OsRng; @@ -148,15 +149,15 @@ impl Proof { Self::prove_internal(witness, statement, &mut OsRng, transcript, false) } - /// Generate a Triptych proof. + /// Generate a Triptych [`Proof`]. /// - /// The proof is generated by supplying a witness `witness` and corresponding statement `statement`. + /// The proof is generated by supplying a [`Witness`] `witness` and corresponding [`Statement`] `statement`. /// If the witness and statement do not share the same parameters, or if the statement is invalid for the witness, - /// returns an error. + /// returns a [`ProofError`]. /// - /// You must also supply a cryptographically-secure random number generator `rng` and a Merlin `transcript`. + /// You must also supply a [`CryptoRngCore`] random number generator `rng` and a [`Transcript`] `transcript`. /// - /// This function makes some attempt at avoiding timing side-channel attacks. + /// This function makes some attempt at avoiding timing side-channel attacks using constant-time operations. pub fn prove_with_rng( witness: &Witness, statement: &Statement, @@ -384,11 +385,12 @@ impl Proof { }) } - /// Verify a Triptych proof. + /// Verify a Triptych [`Proof`]. /// /// Verification requires that the `statement` and `transcript` match those used when the proof was generated. /// - /// Returns a boolean that is `true` if and only if the above requirement is met and the proof is valid. + /// Returns a [`prim@bool`] that is [`prim@true`] if and only if the above requirement is met and the proof is + /// valid. pub fn verify(&self, statement: &Statement, transcript: &mut Transcript) -> bool { // Verify as a trivial batch Self::verify_batch( @@ -398,13 +400,14 @@ impl Proof { ) } - /// Verify a batch of Triptych proofs that share a common input set and parameters. + /// Verify a batch of Triptych [`Proofs`](`Proof`). /// /// Verification requires that the `statements` and `transcripts` match those used when the `proofs` were generated, - /// and that they share a common input set and parameters. + /// and that they share a common [`InputSet`](`crate::statement::InputSet`) and + /// [`Parameters`](`crate::parameters::Parameters`). /// - /// Returns a boolean that is `true` if and only if the above requirements are met and each proof is valid. - /// If the batch is empty, returns `true`. + /// Returns a [`prim@bool`] that is [`prim@true`] if and only if the above requirements are met and each proof is + /// valid. If the batch is empty, returns [`prim@true`]. #[allow(clippy::too_many_lines, non_snake_case)] pub fn verify_batch(statements: &[Statement], proofs: &[Proof], transcripts: &mut [Transcript]) -> bool { // Check that we have the same number of statements, proofs, and transcripts @@ -676,7 +679,7 @@ impl Proof { RistrettoPoint::vartime_multiscalar_mul(scalars.iter(), points) == RistrettoPoint::identity() } - /// Serialize a proof to a canonical byte array. + /// Serialize a [`Proof`] to a canonical byte vector. #[allow(non_snake_case)] pub fn to_bytes(&self) -> Vec { let mut result = Vec::with_capacity( @@ -718,7 +721,9 @@ impl Proof { result } - /// Deserialize a proof from a canonical byte slice. + /// Deserialize a [`Proof`] from a canonical byte slice. + /// + /// If `bytes` does not represent a canonical encoding, returns a [`ProofError`]. #[allow(non_snake_case)] pub fn from_bytes(bytes: &[u8]) -> Result { // Helper to parse a `u32` from a `u8` iterator diff --git a/src/statement.rs b/src/statement.rs index b914d1e..1fb7f30 100644 --- a/src/statement.rs +++ b/src/statement.rs @@ -21,7 +21,7 @@ pub struct InputSet { } impl InputSet { - /// Generate a new input set from a slice `M` of verification keys. + /// Generate a new [`InputSet`] from a slice `M` of verification keys. #[allow(non_snake_case)] pub fn new(M: &[RistrettoPoint]) -> Self { // Use `BLAKE3` for the transcript hash @@ -37,12 +37,12 @@ impl InputSet { } } - /// Get the verification keys for this input set. + /// Get the verification keys for this [`InputSet`]. pub fn get_keys(&self) -> &[RistrettoPoint] { &self.M } - /// Get a cryptographic hash representation of this input set, suitable for transcripting. + /// Get a cryptographic hash representation of this [`InputSet`], suitable for transcripting. pub(crate) fn get_hash(&self) -> &[u8] { &self.hash } @@ -50,8 +50,8 @@ impl InputSet { /// A Triptych proof statement. /// -/// The statement consists of an input set of verification keys and a linking tag. -/// It also contains parameters that, among other things, enforce the size of the input set. +/// The statement consists of an [`InputSet`] of verification keys and a linking tag. +/// It also contains [`Parameters`] that, among other things, enforce the size of the [`InputSet`]. #[allow(non_snake_case)] #[derive(Clone, Eq, PartialEq)] pub struct Statement { @@ -60,7 +60,7 @@ pub struct Statement { J: RistrettoPoint, } -/// Errors that can arise relating to `Statement`. +/// Errors that can arise relating to [`Statement`]. #[derive(Debug, Snafu)] pub enum StatementError { /// An invalid parameter was provided. @@ -69,13 +69,15 @@ pub enum StatementError { } impl Statement { - /// Generate a new Triptych proof statement. + /// Generate a new [`Statement`]. /// - /// The input set `input_set` must have a verification key vector whose size matches that specified by the - /// parameters `params`, and which does not contain the identity group element. - /// If either of these conditions is not met, returns an error. + /// The [`InputSet`] `input_set` must have a verification key vector whose size matches that specified by the + /// [`Parameters`] `params`, and which does not contain the identity group element. + /// If either of these conditions is not met, returns a [`StatementError`]. /// - /// The linking tag `J` is assumed to have been computed from witness data or otherwise provided externally. + /// The linking tag `J` is assumed to have been computed from + /// [`Witness::compute_linking_tag`](`crate::witness::Witness::compute_linking_tag`) data or otherwise provided + /// externally. #[allow(non_snake_case)] pub fn new( params: &Arc, @@ -97,17 +99,17 @@ impl Statement { }) } - /// Get the parameters for this statement. + /// Get the parameters for this [`Statement`]. pub fn get_params(&self) -> &Arc { &self.params } - /// Get the input set for this statement. + /// Get the input set for this [`Statement`]. pub fn get_input_set(&self) -> &Arc { &self.input_set } - /// Get the linking tag for this statement. + /// Get the linking tag for this [`Statement`]. #[allow(non_snake_case)] pub fn get_J(&self) -> &RistrettoPoint { &self.J diff --git a/src/witness.rs b/src/witness.rs index fd160df..5872b23 100644 --- a/src/witness.rs +++ b/src/witness.rs @@ -12,8 +12,9 @@ use crate::parameters::Parameters; /// A Triptych proof witness. /// -/// The witness consists of a signing key and an index where the corresponding verification key will appear in a proof -/// statement verification key vector. It also contains a set of parameters. +/// The witness consists of a signing key and an index where the corresponding verification key will appear in the +/// [`InputSet`](`crate::statement::InputSet`) of a [`Statement`](`crate::statement::Statement`). It also contains +/// [`Parameters`]. #[derive(Zeroize, ZeroizeOnDrop)] pub struct Witness { #[zeroize(skip)] @@ -22,7 +23,7 @@ pub struct Witness { r: Scalar, } -/// Errors that can arise relating to `Witness`. +/// Errors that can arise relating to [`Witness`]. #[derive(Debug, Snafu)] pub enum WitnessError { /// An invalid parameter was provided. @@ -31,12 +32,12 @@ pub enum WitnessError { } impl Witness { - /// Generate a new Triptych proof witness from secret data. + /// Generate a new [`Witness`] from secret data. /// - /// The signing key `r` must be nonzero, and the index `l` must be valid for the parameters `params`. - /// If any of these conditions is not met, returns an error. + /// The signing key `r` must be nonzero, and the index `l` must be valid for the [`Parameters`] `params`. + /// If any of these conditions is not met, returns a [`WitnessError`]. /// - /// If you'd like a witness generated securely for you, use `random` instead. + /// If you'd like a [`Witness`] generated securely for you, use [`Witness::random`] instead. #[allow(non_snake_case)] pub fn new(params: &Arc, l: u32, r: &Scalar) -> Result { if r == &Scalar::ZERO { @@ -53,12 +54,12 @@ impl Witness { }) } - /// Generate a new random Triptych proof witness. + /// Generate a new random [`Witness`]. /// - /// You must provide parameters `params` and a cryptographically-secure random number generator `rng`. - /// This will generate a witness with a cryptographically-secure signing key and random index. + /// You must provide [`Parameters`] `params` and a [`CryptoRngCore`] random number generator `rng`. + /// This will generate a [`Witness`] with a cryptographically-secure signing key and random index. /// - /// If you'd rather provide your own secret data, use `new` instead. + /// If you'd rather provide your own secret data, use [`Witness::new`] instead. #[allow(clippy::cast_possible_truncation)] pub fn random(params: &Arc, rng: &mut R) -> Self { // Generate a random index using wide reduction @@ -72,28 +73,28 @@ impl Witness { } } - /// Get the parameters from this witness. + /// Get the [`Parameters`] from this [`Witness`]. pub fn get_params(&self) -> &Arc { &self.params } - /// Get the index from this witness. + /// Get the index from this [`Witness`]. pub fn get_l(&self) -> u32 { self.l } - /// Get the signing key from this witness. + /// Get the signing key from this [`Witness`]. pub fn get_r(&self) -> &Scalar { &self.r } - /// Compute the linking tag for the witness signing key. + /// Compute the linking tag for the [`Witness`] signing key. #[allow(non_snake_case)] pub fn compute_linking_tag(&self) -> RistrettoPoint { *Zeroizing::new(self.r.invert()) * self.params.get_U() } - /// Compute the verification key for the witness signing key. + /// Compute the verification key for the [`Witness`] signing key. pub fn compute_verification_key(&self) -> RistrettoPoint { self.r * self.params.get_G() }