Skip to content

Commit

Permalink
Replace failure with thiserror to have std-compatible errors.
Browse files Browse the repository at this point in the history
Because std::error::Error is not part of core, this commit feature-gates the
derived `Error` implementation on whether `std` is available.  If we are in a
`no_std` context, the `Error` enums are just plain enums with no `Error`
implementation.
  • Loading branch information
hdevalence committed Jan 17, 2020
1 parent 27318bc commit 0314d48
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 30 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ rand = { version = "0.7", default-features = false, optional = true }
byteorder = { version = "1", default-features = false }
serde = { version = "1", default-features = false, features = ["alloc"] }
serde_derive = { version = "1", default-features = false }
failure = { version = "0.1", default-features = false, features = ["derive"] }
thiserror = { version = "1", optional = true }
merlin = { version = "2", default-features = false }
clear_on_drop = { version = "0.2", default-features = false, features = ["nightly"] }

Expand All @@ -36,7 +36,7 @@ rand_chacha = "0.2"
default = ["std", "avx2_backend"]
avx2_backend = ["curve25519-dalek/avx2_backend"]
yoloproofs = []
std = ["rand", "rand/std"]
std = ["rand", "rand/std", "thiserror"]

[[test]]
name = "range_proof"
Expand Down
70 changes: 47 additions & 23 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,47 @@
extern crate alloc;
use alloc::vec::Vec;

#[cfg(feature = "std")]
use thiserror::Error;

/// Represents an error in proof creation, verification, or parsing.
#[derive(Fail, Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "std", derive(Error))]
pub enum ProofError {
/// This error occurs when a proof failed to verify.
#[fail(display = "Proof verification failed.")]
#[cfg_attr(feature = "std", error("Proof verification failed."))]
VerificationError,
/// This error occurs when the proof encoding is malformed.
#[fail(display = "Proof data could not be parsed.")]
#[cfg_attr(feature = "std", error("Proof data could not be parsed."))]
FormatError,
/// This error occurs during proving if the number of blinding
/// factors does not match the number of values.
#[fail(display = "Wrong number of blinding factors supplied.")]
#[cfg_attr(feature = "std", error("Wrong number of blinding factors supplied."))]
WrongNumBlindingFactors,
/// This error occurs when attempting to create a proof with
/// bitsize other than \\(8\\), \\(16\\), \\(32\\), or \\(64\\).
#[fail(display = "Invalid bitsize, must have n = 8,16,32,64.")]
#[cfg_attr(feature = "std", error("Invalid bitsize, must have n = 8,16,32,64."))]
InvalidBitsize,
/// This error occurs when attempting to create an aggregated
/// proof with non-power-of-two aggregation size.
#[fail(display = "Invalid aggregation size, m must be a power of 2.")]
#[cfg_attr(
feature = "std",
error("Invalid aggregation size, m must be a power of 2.")
)]
InvalidAggregation,
/// This error occurs when there are insufficient generators for the proof.
#[fail(display = "Invalid generators size, too few generators for proof")]
#[cfg_attr(
feature = "std",
error("Invalid generators size, too few generators for proof")
)]
InvalidGeneratorsLength,
/// This error results from an internal error during proving.
///
/// The single-party prover is implemented by performing
/// multiparty computation with ourselves. However, because the
/// MPC protocol is not exposed by the single-party API, we
/// consider its errors to be internal errors.
#[fail(display = "Internal error during proof creation: {}", _0)]
#[cfg_attr(feature = "std", error("Internal error during proof creation: {0}"))]
ProvingError(MPCError),
}

Expand All @@ -55,38 +65,48 @@ impl From<MPCError> for ProofError {
/// API: although the MPC protocol is used internally for single-party
/// proving, its API should not expose the complexity of the MPC
/// protocol.
#[derive(Fail, Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "std", derive(Error))]
pub enum MPCError {
/// This error occurs when the dealer gives a zero challenge,
/// which would annihilate the blinding factors.
#[fail(display = "Dealer gave a malicious challenge value.")]
#[cfg_attr(feature = "std", error("Dealer gave a malicious challenge value."))]
MaliciousDealer,
/// This error occurs when attempting to create a proof with
/// bitsize other than \\(8\\), \\(16\\), \\(32\\), or \\(64\\).
#[fail(display = "Invalid bitsize, must have n = 8,16,32,64")]
#[cfg_attr(feature = "std", error("Invalid bitsize, must have n = 8,16,32,64"))]
InvalidBitsize,
/// This error occurs when attempting to create an aggregated
/// proof with non-power-of-two aggregation size.
#[fail(display = "Invalid aggregation size, m must be a power of 2")]
#[cfg_attr(
feature = "std",
error("Invalid aggregation size, m must be a power of 2")
)]
InvalidAggregation,
/// This error occurs when there are insufficient generators for the proof.
#[fail(display = "Invalid generators size, too few generators for proof")]
#[cfg_attr(
feature = "std",
error("Invalid generators size, too few generators for proof")
)]
InvalidGeneratorsLength,
/// This error occurs when the dealer is given the wrong number of
/// value commitments.
#[fail(display = "Wrong number of value commitments")]
#[cfg_attr(feature = "std", error("Wrong number of value commitments"))]
WrongNumBitCommitments,
/// This error occurs when the dealer is given the wrong number of
/// polynomial commitments.
#[fail(display = "Wrong number of value commitments")]
#[cfg_attr(feature = "std", error("Wrong number of value commitments"))]
WrongNumPolyCommitments,
/// This error occurs when the dealer is given the wrong number of
/// proof shares.
#[fail(display = "Wrong number of proof shares")]
#[cfg_attr(feature = "std", error("Wrong number of proof shares"))]
WrongNumProofShares,
/// This error occurs when one or more parties submit malformed
/// proof shares.
#[fail(display = "Malformed proof shares from parties {:?}", bad_shares)]
#[cfg_attr(
feature = "std",
error("Malformed proof shares from parties {bad_shares:?}")
)]
MalformedProofShares {
/// A vector with the indexes of the parties whose shares were malformed.
bad_shares: Vec<usize>,
Expand All @@ -97,27 +117,31 @@ pub enum MPCError {
///
/// XXX: should this be separate from a `ProofError`?
#[cfg(feature = "yoloproofs")]
#[derive(Fail, Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "std", derive(Error))]
pub enum R1CSError {
/// Occurs when there are insufficient generators for the proof.
#[fail(display = "Invalid generators size, too few generators for proof")]
#[cfg_attr(
feature = "std",
error("Invalid generators size, too few generators for proof")
)]
InvalidGeneratorsLength,
/// This error occurs when the proof encoding is malformed.
#[fail(display = "Proof data could not be parsed.")]
#[cfg_attr(feature = "std", error("Proof data could not be parsed."))]
FormatError,
/// Occurs when verification of an
/// [`R1CSProof`](::r1cs::R1CSProof) fails.
#[fail(display = "R1CSProof did not verify correctly.")]
#[cfg_attr(feature = "std", error("R1CSProof did not verify correctly."))]
VerificationError,

/// Occurs when trying to use a missing variable assignment.
/// Used by gadgets that build the constraint system to signal that
/// a variable assignment is not provided when the prover needs it.
#[fail(display = "Variable does not have a value assignment.")]
#[cfg_attr(feature = "std", error("Variable does not have a value assignment."))]
MissingAssignment,

/// Occurs when a gadget receives an inconsistent input.
#[fail(display = "Gadget error: {:?}", description)]
#[cfg_attr(feature = "std", error("Gadget error: {description:?}"))]
GadgetError {
/// The description of the reasons for the error.
description: String,
Expand Down
3 changes: 0 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ extern crate alloc;
#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate failure;

mod util;

#[doc(include = "../docs/notes-intro.md")]
Expand Down
9 changes: 8 additions & 1 deletion src/r1cs/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,14 @@ impl<'de> Deserialize<'de> for R1CSProof {
where
E: serde::de::Error,
{
R1CSProof::from_bytes(v).map_err(serde::de::Error::custom)
// Using Error::custom requires T: Display, which our error
// type only implements when it implements std::error::Error.
#[cfg(feature = "std")]
return R1CSProof::from_bytes(v).map_err(serde::de::Error::custom);
// In no-std contexts, drop the error message.
#[cfg(not(feature = "std"))]
return R1CSProof::from_bytes(v)
.map_err(|_| serde::de::Error::custom("deserialization error"));
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/range_proof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,14 @@ impl<'de> Deserialize<'de> for RangeProof {
where
E: serde::de::Error,
{
RangeProof::from_bytes(v).map_err(serde::de::Error::custom)
// Using Error::custom requires T: Display, which our error
// type only implements when it implements std::error::Error.
#[cfg(feature = "std")]
return RangeProof::from_bytes(v).map_err(serde::de::Error::custom);
// In no-std contexts, drop the error message.
#[cfg(not(feature = "std"))]
return RangeProof::from_bytes(v)
.map_err(|_| serde::de::Error::custom("deserialization error"));
}
}

Expand Down

0 comments on commit 0314d48

Please sign in to comment.