//! FROST Error types use thiserror::Error; use crate::{frost::Identifier, Ciphersuite}; #[derive(Error, Debug, Clone, Copy, Eq, PartialEq)] pub struct ParticipantError(Identifier); /// An error related to FROST. #[non_exhaustive] #[derive(Error, Debug, Copy, Clone, Eq, PartialEq)] pub enum Error { /// min_signers is invalid #[error("min_signers must be at least 2 and not larger than max_signers")] InvalidMinSigners, /// max_signers is invalid #[error("max_signers must be at least 2")] InvalidMaxSigners, /// max_signers is invalid #[error("coefficients must have min_signers-1 elements")] InvalidCoefficients, /// This identifier is unserializable. #[error("Malformed identifier is unserializable.")] MalformedIdentifier, /// This identifier is duplicated. #[error("Duplicated identifiers.")] DuplicatedIdentifiers, /// This identifier does not belong to a participant in the signing process. #[error("Unknown identifier.")] UnknownIdentifier, /// Incorrect number of identifiers. #[error("Incorrect number of identifiers.")] IncorrectNumberOfIdentifiers, /// The encoding of a signing key was malformed. #[error("Malformed signing key encoding.")] MalformedSigningKey, /// The encoding of a verifying key was malformed. #[error("Malformed verifying key encoding.")] MalformedVerifyingKey, /// The encoding of a signature was malformed. #[error("Malformed signature encoding.")] MalformedSignature, /// Signature verification failed. #[error("Invalid signature.")] InvalidSignature, /// Duplicated shares provided #[error("Duplicated shares provided.")] DuplicatedShares, /// Incorrect number of shares. #[error("Incorrect number of shares.")] IncorrectNumberOfShares, /// Commitment equals the identity #[error("Commitment equals the identity.")] IdentityCommitment, /// Signature share verification failed. #[error("Invalid signature share.")] InvalidSignatureShare { /// The identifier of the signer whose share validation failed. culprit: Identifier, }, /// Secret share verification failed. #[error("Invalid secret share.")] InvalidSecretShare, /// Round 1 package not found for Round 2 participant. #[error("Round 1 package not found for Round 2 participant.")] PackageNotFound, /// Incorrect number of packages. #[error("Incorrect number of packages.")] IncorrectNumberOfPackages, /// The incorrect package was specified. #[error("The incorrect package was specified.")] IncorrectPackage, /// The ciphersuite does not support DKG. #[error("The ciphersuite does not support DKG.")] DKGNotSupported, /// The proof of knowledge is not valid. #[error("The proof of knowledge is not valid.")] InvalidProofOfKnowledge { /// The identifier of the signer whose share validation failed. culprit: Identifier, }, /// Error in scalar Field. #[error("Error in scalar Field.")] FieldError(#[from] FieldError), /// Error in elliptic curve Group. #[error("Error in elliptic curve Group.")] GroupError(#[from] GroupError), /// Error in coefficient commitment deserialization. #[error("Invalid coefficient")] InvalidCoefficient, /// The ciphersuite does not support deriving identifiers from strings. #[error("The ciphersuite does not support deriving identifiers from strings.")] IdentifierDerivationNotSupported, } impl Error where C: Ciphersuite, { /// Return the identifier of the participant that caused the error. /// Returns None if not applicable for the error. /// /// This can be used to penalize a participant that does not follow the /// protocol correctly, e.g. removing them from further signings. pub fn culprit(&self) -> Option> { // Use an exhaustive match to make sure that if we add new enum items // then we will explicitly check if they should be added here. match self { Error::InvalidSignatureShare { culprit: identifier, } | Error::InvalidProofOfKnowledge { culprit: identifier, } => Some(*identifier), Error::InvalidSecretShare | Error::InvalidMinSigners | Error::InvalidMaxSigners | Error::InvalidCoefficients | Error::MalformedIdentifier | Error::MalformedSigningKey | Error::MalformedVerifyingKey | Error::MalformedSignature | Error::InvalidSignature | Error::DuplicatedShares | Error::IncorrectNumberOfShares | Error::IdentityCommitment | Error::PackageNotFound | Error::IncorrectNumberOfPackages | Error::IncorrectPackage | Error::DKGNotSupported | Error::FieldError(_) | Error::GroupError(_) | Error::DuplicatedIdentifiers | Error::InvalidCoefficient | Error::UnknownIdentifier | Error::IncorrectNumberOfIdentifiers | Error::IdentifierDerivationNotSupported => None, } } } /// An error related to a scalar Field. #[non_exhaustive] #[derive(Error, Debug, Copy, Clone, Eq, PartialEq)] pub enum FieldError { /// The encoding of a group scalar was malformed. #[error("Malformed scalar encoding.")] MalformedScalar, /// This scalar MUST NOT be zero. #[error("Invalid for this scalar to be zero.")] InvalidZeroScalar, } /// An error related to a Group (usually an elliptic curve or constructed from one) or one of its Elements. #[non_exhaustive] #[derive(Error, Debug, Copy, Clone, Eq, PartialEq)] pub enum GroupError { /// The encoding of a group element was malformed. #[error("Malformed group element encoding.")] MalformedElement, /// This element MUST NOT be the identity. #[error("Invalid for this element to be the identity.")] InvalidIdentityElement, /// This element MUST have (large) prime order. #[error("Invalid for this element to not have large prime order.")] InvalidNonPrimeOrderElement, }