From 0314d48deacd759af5e8b908ca9baf6b1f736c40 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Fri, 27 Dec 2019 11:17:24 -0800 Subject: [PATCH] Replace failure with thiserror to have std-compatible errors. 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. --- Cargo.toml | 4 +-- src/errors.rs | 70 ++++++++++++++++++++++++++++-------------- src/lib.rs | 3 -- src/r1cs/proof.rs | 9 +++++- src/range_proof/mod.rs | 9 +++++- 5 files changed, 65 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 35fe2f86..fe778665 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } @@ -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" diff --git a/src/errors.rs b/src/errors.rs index b20fbb61..776915d1 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -3,29 +3,39 @@ 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. /// @@ -33,7 +43,7 @@ pub enum ProofError { /// 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), } @@ -55,38 +65,48 @@ impl From 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, @@ -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, diff --git a/src/lib.rs b/src/lib.rs index 111764d8..cf99be55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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")] diff --git a/src/r1cs/proof.rs b/src/r1cs/proof.rs index b1ead97d..6bf0817c 100644 --- a/src/r1cs/proof.rs +++ b/src/r1cs/proof.rs @@ -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")); } } diff --git a/src/range_proof/mod.rs b/src/range_proof/mod.rs index 13de40dd..6eee8d31 100644 --- a/src/range_proof/mod.rs +++ b/src/range_proof/mod.rs @@ -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")); } }