frost_core/
error.rs

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
//! FROST Error types

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

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

use crate::{Ciphersuite, Identifier};

#[derive(Error, Debug, Clone, Copy, Eq, PartialEq)]
pub struct ParticipantError<C: Ciphersuite>(Identifier<C>);

/// An error related to FROST.
#[non_exhaustive]
#[derive(Error, Debug, Copy, Clone, Eq, PartialEq)]
pub enum Error<C: Ciphersuite> {
    /// 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 identifier.")]
    DuplicatedIdentifier,
    /// 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,
    /// The participant's commitment is missing from the Signing Package
    #[error("The Signing Package must contain the participant's Commitment.")]
    MissingCommitment,
    /// The participant's commitment is incorrect
    #[error("The participant's commitment is incorrect.")]
    IncorrectCommitment,
    /// Incorrect number of commitments.
    #[error("Incorrect number of commitments.")]
    IncorrectNumberOfCommitments,
    /// Signature share verification failed.
    #[error("Invalid signature share.")]
    InvalidSignatureShare {
        /// The identifier of the signer whose share validation failed.
        culprit: Identifier<C>,
    },
    /// 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<C>,
    },
    /// 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,
    /// Error serializing value.
    #[error("Error serializing value.")]
    SerializationError,
    /// Error deserializing value.
    #[error("Error deserializing value.")]
    DeserializationError,
}

impl<C> Error<C>
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<Identifier<C>> {
        // 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::MissingCommitment
            | Error::IncorrectCommitment
            | Error::PackageNotFound
            | Error::IncorrectNumberOfPackages
            | Error::IncorrectPackage
            | Error::DKGNotSupported
            | Error::FieldError(_)
            | Error::GroupError(_)
            | Error::DuplicatedIdentifier
            | Error::InvalidCoefficient
            | Error::UnknownIdentifier
            | Error::IncorrectNumberOfIdentifiers
            | Error::IncorrectNumberOfCommitments
            | Error::SerializationError
            | Error::DeserializationError
            | 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,
}