1use crate::{NetworkAddress, PrettyPrintRecordKey};
10use libp2p::kad::store;
11use serde::{Deserialize, Serialize};
12use thiserror::Error;
13
14pub type Result<T> = std::result::Result<T, Error>;
16
17#[derive(Error, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
29#[non_exhaustive]
30pub enum Error {
31 #[error("Chunk does not exist {0:?}")]
33 ChunkDoesNotExist(NetworkAddress),
34
35 #[error("Failed to derive CipherText from encrypted_data")]
38 ScratchpadCipherTextFailed,
39 #[error("Provided cypher text is invalid")]
41 ScratchpadCipherTextInvalid,
42
43 #[error("There was an error getting the storecost from kademlia store")]
45 GetStoreQuoteFailed,
46 #[error("There was an error generating the payment quote")]
47 QuoteGenerationFailed,
48
49 #[error("Peer {holder:?} cannot find Record {key:?}")]
52 ReplicatedRecordNotFound {
53 holder: Box<NetworkAddress>,
55 key: Box<NetworkAddress>,
57 },
58
59 #[error("Could not Serialize/Deserialize RecordHeader to/from Record")]
62 RecordHeaderParsingFailed,
63 #[error("Could not Serialize/Deserialize Record")]
65 RecordParsingFailed,
66 #[error("The record already exists, so do not charge for it: {0:?}")]
68 RecordExists(PrettyPrintRecordKey<'static>),
69
70 #[error("Error handling record put: {0}")]
72 PutRecordFailed(String),
73 #[error("Outdated record: with counter {counter}, expected any above {expected}")]
74 OutdatedRecordCounter { counter: u64, expected: u64 },
75
76 #[error("There was an error getting the Merkle candidate quote: {0}")]
78 GetMerkleCandidateQuoteFailed(String),
79 #[error("Failed to sign Merkle candidate node: {0}")]
80 FailedToSignMerkleCandidate(String),
81 #[error("Merkle payment verification failed: {0}")]
82 MerklePaymentVerificationFailed(String),
83 #[error(
84 "Topology verification failed: only {valid_count}/{total_paid} paid nodes in closest {closest_count}"
85 )]
86 TopologyVerificationFailed {
87 target_address: Box<NetworkAddress>,
89 valid_count: usize,
91 total_paid: usize,
93 closest_count: usize,
95 #[serde(with = "crate::peer_id_serde")]
97 node_peers: Vec<libp2p::PeerId>,
98 #[serde(with = "crate::peer_id_serde")]
100 paid_peers: Vec<libp2p::PeerId>,
101 },
102
103 #[error("Unknown error: the peer and you are using different protocol versions")]
107 #[serde(other)]
108 Unknown,
109}
110
111impl From<Error> for store::Error {
112 fn from(_err: Error) -> Self {
113 store::Error::ValueTooLarge
114 }
115}
116
117impl From<store::Error> for Error {
118 fn from(_err: store::Error) -> Self {
119 Error::RecordParsingFailed
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use libp2p::PeerId;
126
127 use super::*;
128
129 #[test]
130 fn test_error_retro_compatibility() {
131 #[derive(Error, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
133 #[non_exhaustive]
134 enum ExtendedError {
135 #[error("Chunk does not exist {0:?}")]
136 ChunkDoesNotExist(NetworkAddress),
137 #[error("Failed to deserialize hex ScratchpadAddress")]
138 ScratchpadHexDeserializeFailed,
139 #[error("Failed to derive CipherText from encrypted_data")]
140 ScratchpadCipherTextFailed,
141 #[error("Provided cypher text is invalid")]
142 ScratchpadCipherTextInvalid,
143 #[error("There was an error getting the storecost from kademlia store")]
144 GetStoreQuoteFailed,
145 #[error("There was an error generating the payment quote")]
146 QuoteGenerationFailed,
147 #[error("Peer {holder:?} cannot find Record {key:?}")]
148 ReplicatedRecordNotFound {
149 holder: Box<NetworkAddress>,
150 key: Box<NetworkAddress>,
151 },
152 #[error("Could not Serialize/Deserialize RecordHeader to/from Record")]
153 RecordHeaderParsingFailed,
154 #[error("Could not Serialize/Deserialize Record")]
155 RecordParsingFailed,
156 #[error("The record already exists, so do not charge for it: {0:?}")]
157 RecordExists(PrettyPrintRecordKey<'static>),
158 #[error("New error variant for testing")]
160 NewErrorVariant,
161 #[error("Unknown error variant")]
162 #[serde(other)]
163 Unknown,
164 }
165
166 let extended_error = ExtendedError::NewErrorVariant;
168 let serialized = rmp_serde::to_vec(&extended_error).unwrap();
169
170 let deserialized: Error = rmp_serde::from_slice(&serialized).unwrap();
172 assert_eq!(deserialized, Error::Unknown);
173 }
174
175 #[test]
176 fn test_error_retro_compatibility_reduced() {
177 #[derive(Error, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
179 #[non_exhaustive]
180 enum ReducedError {
181 #[error("Chunk does not exist {0:?}")]
182 ChunkDoesNotExist(NetworkAddress),
183 #[error("Failed to deserialize hex ScratchpadAddress")]
184 ScratchpadHexDeserializeFailed,
185 #[error("Provided cypher text is invalid")]
189 ScratchpadCipherTextInvalid,
190 #[error("There was an error getting the storecost from kademlia store")]
191 GetStoreQuoteFailed,
192 #[error("There was an error generating the payment quote")]
193 QuoteGenerationFailed,
194 #[error("Peer {holder:?} cannot find Record {key:?}")]
195 ReplicatedRecordNotFound {
196 holder: Box<NetworkAddress>,
197 key: Box<NetworkAddress>,
198 },
199 #[error("Could not Serialize/Deserialize RecordHeader to/from Record")]
200 RecordHeaderParsingFailed,
201 #[error("Could not Serialize/Deserialize Record")]
202 RecordParsingFailed,
203 #[error("The record already exists, so do not charge for it: {0:?}")]
204 RecordExists(PrettyPrintRecordKey<'static>),
205 #[error("Unknown error variant")]
207 #[serde(other)]
208 Unknown,
209 }
210
211 let current_error = Error::ScratchpadCipherTextInvalid;
213 let serialized_current = rmp_serde::to_vec(¤t_error).unwrap();
214
215 let deserialized_reduced: ReducedError =
217 rmp_serde::from_slice(&serialized_current).unwrap();
218 assert_eq!(
219 deserialized_reduced,
220 ReducedError::ScratchpadCipherTextInvalid
221 );
222
223 let unknown_variant = Error::ScratchpadCipherTextFailed;
225 let serialized_unknown = rmp_serde::to_vec(&unknown_variant).unwrap();
226 let deserialized_unknown: ReducedError =
227 rmp_serde::from_slice(&serialized_unknown).unwrap();
228 assert_eq!(deserialized_unknown, ReducedError::Unknown);
229
230 let reduced_simple_error = ReducedError::GetStoreQuoteFailed;
232 let serialized_reduced_simple = rmp_serde::to_vec(&reduced_simple_error).unwrap();
233 let deserialized_reduced_simple: Error =
234 rmp_serde::from_slice(&serialized_reduced_simple).unwrap();
235 assert_eq!(deserialized_reduced_simple, Error::GetStoreQuoteFailed);
236
237 let addr = NetworkAddress::from(PeerId::random());
239 let reduced_complex_error = ReducedError::ChunkDoesNotExist(addr.clone());
240 let serialized_reduced_complex = rmp_serde::to_vec(&reduced_complex_error).unwrap();
241 let deserialized_reduced_complex: Error =
242 rmp_serde::from_slice(&serialized_reduced_complex).unwrap();
243 assert_eq!(deserialized_reduced_complex, Error::ChunkDoesNotExist(addr));
244
245 let holder = NetworkAddress::from(PeerId::random());
247 let key = NetworkAddress::from(PeerId::random());
248 let reduced_struct_error = ReducedError::ReplicatedRecordNotFound {
249 holder: Box::new(holder.clone()),
250 key: Box::new(key.clone()),
251 };
252 let serialized_reduced_struct = rmp_serde::to_vec(&reduced_struct_error).unwrap();
253 let deserialized_reduced_struct: Error =
254 rmp_serde::from_slice(&serialized_reduced_struct).unwrap();
255 assert_eq!(
256 deserialized_reduced_struct,
257 Error::ReplicatedRecordNotFound {
258 holder: Box::new(holder),
259 key: Box::new(key),
260 }
261 );
262 }
263
264 #[test]
265 fn test_error_retro_compatibility_many_missing() {
266 #[derive(Error, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
268 #[non_exhaustive]
269 enum ManyMissingVariants {
270 #[error("Chunk does not exist {0:?}")]
271 ChunkDoesNotExist(NetworkAddress),
272 #[error("There was an error getting the storecost from kademlia store")]
273 GetStoreQuoteFailed,
274 #[error("Unknown error variant")]
276 #[serde(other)]
277 Unknown,
278 }
279
280 let current_error = Error::ScratchpadCipherTextInvalid;
282 let serialized_current = rmp_serde::to_vec(¤t_error).unwrap();
283 let deserialized_many_missing: ManyMissingVariants =
284 rmp_serde::from_slice(&serialized_current).unwrap();
285 assert_eq!(deserialized_many_missing, ManyMissingVariants::Unknown);
286
287 let chunk_error = Error::GetStoreQuoteFailed;
289 let serialized_chunk = rmp_serde::to_vec(&chunk_error).unwrap();
290 let deserialized_chunk: ManyMissingVariants =
291 rmp_serde::from_slice(&serialized_chunk).unwrap();
292 assert_eq!(deserialized_chunk, ManyMissingVariants::GetStoreQuoteFailed);
293
294 let many_missing_error = ManyMissingVariants::GetStoreQuoteFailed;
296 let serialized_many_missing = rmp_serde::to_vec(&many_missing_error).unwrap();
297 let deserialized_to_error: Error = rmp_serde::from_slice(&serialized_many_missing).unwrap();
298 assert_eq!(deserialized_to_error, Error::GetStoreQuoteFailed);
299
300 let addr = NetworkAddress::from(PeerId::random());
302
303 let chunk_error = Error::ChunkDoesNotExist(addr.clone());
305 let serialized_chunk = rmp_serde::to_vec(&chunk_error).unwrap();
306 let deserialized_chunk: ManyMissingVariants =
307 rmp_serde::from_slice(&serialized_chunk).unwrap();
308 assert_eq!(
309 deserialized_chunk,
310 ManyMissingVariants::ChunkDoesNotExist(addr.clone())
311 );
312
313 let many_missing_chunk = ManyMissingVariants::ChunkDoesNotExist(addr.clone());
315 let serialized_many_missing_chunk = rmp_serde::to_vec(&many_missing_chunk).unwrap();
316 let deserialized_many_missing_chunk: Error =
317 rmp_serde::from_slice(&serialized_many_missing_chunk).unwrap();
318 assert_eq!(
319 deserialized_many_missing_chunk,
320 Error::ChunkDoesNotExist(addr)
321 );
322
323 let record_error = Error::RecordParsingFailed;
325 let serialized_record = rmp_serde::to_vec(&record_error).unwrap();
326 let deserialized_record: ManyMissingVariants =
327 rmp_serde::from_slice(&serialized_record).unwrap();
328 assert_eq!(deserialized_record, ManyMissingVariants::Unknown);
329 }
330
331 #[test]
333 fn test_error_retro_compatibility_complex_types() {
334 #[derive(Error, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
336 #[non_exhaustive]
337 enum ComplexTypesRemoved {
338 #[error("Chunk does not exist {0:?}")]
339 ChunkDoesNotExist(NetworkAddress),
340 #[error("Failed to deserialize hex ScratchpadAddress")]
341 ScratchpadHexDeserializeFailed,
342 #[error("Failed to derive CipherText from encrypted_data")]
343 ScratchpadCipherTextFailed,
344 #[error("Provided cypher text is invalid")]
345 ScratchpadCipherTextInvalid,
346 #[error("There was an error getting the storecost from kademlia store")]
347 GetStoreQuoteFailed,
348 #[error("There was an error generating the payment quote")]
349 QuoteGenerationFailed,
350 #[error("Could not Serialize/Deserialize RecordHeader to/from Record")]
357 RecordHeaderParsingFailed,
358 #[error("Could not Serialize/Deserialize Record")]
359 RecordParsingFailed,
360 #[error("The record already exists, so do not charge for it: {0:?}")]
361 RecordExists(PrettyPrintRecordKey<'static>),
362 #[error("Unknown error variant")]
364 #[serde(other)]
365 Unknown,
366 }
367
368 let holder = NetworkAddress::from(PeerId::random());
371 let key = NetworkAddress::from(PeerId::random());
372 let complex_error = Error::ReplicatedRecordNotFound {
373 holder: Box::new(holder),
374 key: Box::new(key),
375 };
376 let serialized_complex = rmp_serde::to_vec(&complex_error).unwrap();
377
378 assert!(rmp_serde::from_slice::<ComplexTypesRemoved>(&serialized_complex).is_err());
384
385 let simple_error = Error::ScratchpadCipherTextInvalid;
387 let serialized_simple = rmp_serde::to_vec(&simple_error).unwrap();
388 let deserialized_simple: ComplexTypesRemoved =
389 rmp_serde::from_slice(&serialized_simple).unwrap();
390 assert_eq!(
391 deserialized_simple,
392 ComplexTypesRemoved::ScratchpadCipherTextInvalid
393 );
394
395 let addr = NetworkAddress::from(PeerId::random());
397 let chunk_error = Error::ChunkDoesNotExist(addr.clone());
398 let serialized_chunk = rmp_serde::to_vec(&chunk_error).unwrap();
399 let deserialized_chunk: ComplexTypesRemoved =
400 rmp_serde::from_slice(&serialized_chunk).unwrap();
401 assert_eq!(
402 deserialized_chunk,
403 ComplexTypesRemoved::ChunkDoesNotExist(addr)
404 );
405 }
406}