1use thiserror::Error;
2
3#[derive(Error, Debug, PartialEq, Eq)]
4pub enum SparkCryptographyError {
5 #[error("Invalid leaf: {0}")]
6 InvalidLeaf(InvalidLeafError),
7
8 #[error("Invalid seed")]
9 InvalidSeed,
10
11 #[error("Invalid key: {0}")]
12 InvalidKey(InvalidKeyError),
13
14 #[error("Invalid identifier: {0}")]
15 InvalidIdentifier(InvalidIdentifierError),
16
17 #[error("Invalid commitment: {0}")]
18 InvalidCommitment(InvalidCommitmentError),
19
20 #[error("Invalid nonce: {0}")]
21 InvalidNonce(InvalidNonceError),
22
23 #[error("Invalid key package: {0}")]
24 InvalidKeyPackage(InvalidKeyPackageError),
25
26 #[error("Invalid signature share: {0}")]
27 InvalidSignatureShare(InvalidSignatureShareError),
28
29 #[error("Invalid derivation path: {0}")]
30 InvalidDerivationPath(String),
31
32 #[error("Invalid role: {0}")]
33 InvalidRole(InvalidRoleError),
34
35 #[error("Secp256k1 error: {0}")]
36 SecpError(SecpError),
37
38 #[error("FROST operation error: {0}")]
39 FrostOperation(FrostOperationError),
40}
41
42impl From<bitcoin::secp256k1::Error> for SparkCryptographyError {
43 fn from(err: bitcoin::secp256k1::Error) -> Self {
44 Self::SecpError(SecpError::BitcoinSecp256k1Error(err))
45 }
46}
47
48impl From<String> for SparkCryptographyError {
49 fn from(_: String) -> Self {
50 Self::FrostOperation(FrostOperationError::GenericError)
51 }
52}
53
54#[derive(Error, Debug, PartialEq, Eq)]
55pub enum InvalidLeafError {
56 #[error("Invalid leaf ID: {0}")]
57 InvalidLeafId(String),
58
59 #[error("Index not in leaf index range: {0}")]
60 IndexNotInLeafIndexRange(u32),
61
62 #[error("Cannot derive child number from index: {0}. Index must be less than 0x7FFFFFFF or 2,147,483,647 both for hardened and normal indices.")]
63 CannotDeriveChildNumberFromIndex(u32),
64}
65
66#[derive(Error, Debug, PartialEq, Eq)]
67pub enum SecpError {
68 #[error("Cannot operator on equal public keys")]
69 PubkeysAreEqual,
70
71 #[from(bitcoin::secp256k1::Error)]
72 #[error("Bitcoin secp256k1 error: {0}")]
73 BitcoinSecp256k1Error(bitcoin::secp256k1::Error),
74}
75
76#[derive(Error, Debug, PartialEq, Eq)]
77pub enum InvalidKeyError {
78 #[error("Invalid verifying key format")]
79 InvalidFormat,
80 #[error("Invalid key length")]
81 InvalidLength,
82 #[error("Invalid verifying key")]
83 InvalidVerifyingKey,
84 #[error("Invalid public key")]
85 InvalidPublicKey,
86}
87
88#[derive(Error, Debug, PartialEq, Eq)]
89pub enum InvalidCommitmentError {
90 #[error("Invalid commitment format")]
91 InvalidFormat,
92 #[error("Invalid commitment map structure")]
93 InvalidCommitmentMap,
94 #[error("Invalid commitment value")]
95 InvalidCommitmentValue,
96 #[error("Failed to parse commitment")]
97 ParseError,
98}
99
100#[derive(Error, Debug, PartialEq, Eq)]
101pub enum InvalidNonceError {
102 #[error("Invalid nonce format")]
103 InvalidFormat,
104 #[error("Invalid nonce length")]
105 InvalidLength,
106 #[error("Failed to parse nonce")]
107 ParseError,
108}
109
110#[derive(Error, Debug, PartialEq, Eq)]
111pub enum InvalidIdentifierError {
112 #[error("Invalid identifier format")]
113 InvalidFormat,
114 #[error("Invalid identifier length")]
115 InvalidLength,
116 #[error("Failed to parse identifier")]
117 ParseError,
118}
119
120#[derive(Error, Debug, PartialEq, Eq)]
121pub enum InvalidSignatureShareError {
122 #[error("Invalid signature share format")]
123 InvalidFormat,
124 #[error("Signature verification failed")]
125 VerificationFailed,
126 #[error("Invalid participant")]
127 InvalidParticipant,
128 #[error("Failed to parse signature share")]
129 ParseError,
130 #[error("Failed to aggregate signatures")]
131 AggregationError,
132}
133
134#[derive(Error, Debug, PartialEq, Eq)]
135pub enum InvalidKeyPackageError {
136 #[error("Missing key package")]
137 MissingKeyPackage,
138 #[error("Invalid key package format")]
139 InvalidFormat,
140 #[error("Invalid key package content")]
141 InvalidContent,
142 #[error("Failed to parse key package")]
143 ParseError,
144}
145
146#[derive(Error, Debug, PartialEq, Eq)]
147pub enum InvalidRoleError {
148 #[error("Invalid role")]
149 InvalidRole,
150 #[error("Unsupported role")]
151 UnsupportedRole,
152}
153
154#[derive(Error, Debug, PartialEq, Eq)]
155pub enum FrostOperationError {
156 #[error("Failed to parse FROST operation")]
157 ParseError,
158 #[error("Failed to aggregate FROST operation")]
159 AggregationError,
160 #[error("Failed to serialize FROST operation")]
161 SerializationError,
162 #[error("Generic FROST operation error")]
163 GenericError,
164}
165
166#[cfg(test)]
167mod tests {
168 use super::*;
169
170 #[test]
171 fn test_invalid_leaf_error_messages() {
172 let err = InvalidLeafError::InvalidLeafId("test_id".to_string());
173 assert_eq!(err.to_string(), "Invalid leaf ID: test_id");
174
175 let err = InvalidLeafError::IndexNotInLeafIndexRange(100);
176 assert_eq!(err.to_string(), "Index not in leaf index range: 100");
177
178 let err = InvalidLeafError::CannotDeriveChildNumberFromIndex(0x80000000);
179 assert_eq!(
180 err.to_string(),
181 "Cannot derive child number from index: 2147483648. Index must be less than 0x7FFFFFFF or 2,147,483,647 both for hardened and normal indices."
182 );
183 }
184
185 #[test]
186 fn test_secp_error_conversion() {
187 use bitcoin::secp256k1::Error as Secp256k1Error;
188
189 let secp_err = Secp256k1Error::InvalidPublicKey;
191 let spark_err: SparkCryptographyError = secp_err.into();
192
193 assert!(matches!(
194 spark_err,
195 SparkCryptographyError::SecpError(SecpError::BitcoinSecp256k1Error(
196 Secp256k1Error::InvalidPublicKey
197 ))
198 ));
199 }
200
201 #[test]
202 fn test_spark_cryptography_error_messages() {
203 let err = SparkCryptographyError::InvalidSeed;
204 assert_eq!(err.to_string(), "Invalid seed");
205
206 let err = SparkCryptographyError::InvalidDerivationPath("m/44'/0'".to_string());
207 assert_eq!(err.to_string(), "Invalid derivation path: m/44'/0'");
208
209 let err = SparkCryptographyError::InvalidLeaf(InvalidLeafError::InvalidLeafId(
210 "test".to_string(),
211 ));
212 assert_eq!(err.to_string(), "Invalid leaf: Invalid leaf ID: test");
213 }
214
215 #[test]
216 fn test_error_equality() {
217 let err1 = SparkCryptographyError::InvalidSeed;
218 let err2 = SparkCryptographyError::InvalidSeed;
219 assert_eq!(err1, err2);
220
221 let err1 = SecpError::PubkeysAreEqual;
222 let err2 = SecpError::PubkeysAreEqual;
223 assert_eq!(err1, err2);
224 }
225}