1use crate::ValidationError;
4use thiserror::Error;
5
6#[derive(Debug, Error)]
45pub enum ProtocolError {
46 #[error("Invalid signature")]
47 InvalidSignature,
48
49 #[error("Nonce already used (replay attack detected)")]
50 NonceReused,
51
52 #[error("Timestamp out of valid range")]
53 TimestampOutdated,
54
55 #[error("Content not found: {0}")]
56 ContentNotFound(String),
57
58 #[error("Chunk not found: index {0}")]
59 ChunkNotFound(u64),
60
61 #[error("Encryption error: {0}")]
62 EncryptionError(String),
63
64 #[error("Decryption error: {0}")]
65 DecryptionError(String),
66
67 #[error("Network error: {0}")]
68 NetworkError(String),
69
70 #[error("Database error: {0}")]
71 DatabaseError(String),
72
73 #[error("Validation error: {0}")]
74 ValidationError(String),
75
76 #[error("Peer not found: {0}")]
77 PeerNotFound(String),
78
79 #[error("Insufficient storage space")]
80 InsufficientStorage,
81
82 #[error("Bandwidth limit exceeded")]
83 BandwidthLimitExceeded,
84
85 #[error("Rate limit exceeded")]
86 RateLimitExceeded,
87
88 #[error("Invalid protocol version: {0}")]
89 InvalidProtocolVersion(String),
90
91 #[error("Connection failed: {0}")]
92 ConnectionFailed(String),
93
94 #[error("Timeout: {0}")]
95 Timeout(String),
96
97 #[error("Unauthorized: {0}")]
98 Unauthorized(String),
99}
100
101impl From<ValidationError> for ProtocolError {
102 fn from(err: ValidationError) -> Self {
103 ProtocolError::ValidationError(err.to_string())
104 }
105}
106
107#[derive(Debug, Error)]
151pub enum VerificationError {
152 #[error("Invalid provider signature")]
153 InvalidProviderSignature,
154
155 #[error("Invalid requester signature")]
156 InvalidRequesterSignature,
157
158 #[error("Nonce has already been used")]
159 NonceReused,
160
161 #[error("Timestamp is too old or in the future")]
162 TimestampOutOfRange,
163
164 #[error("Statistical anomaly detected: {0}")]
165 AnomalyDetected(String),
166
167 #[error("Peer is banned: {0}")]
168 PeerBanned(String),
169
170 #[error("Invalid proof structure: {0}")]
171 InvalidProofStructure(String),
172
173 #[error("Challenge nonce mismatch")]
174 ChallengeMismatch,
175
176 #[error("Chunk hash mismatch")]
177 ChunkHashMismatch,
178
179 #[error("Invalid latency: {0}ms")]
180 InvalidLatency(u32),
181
182 #[error("Blacklisted peer: {0}")]
183 BlacklistedPeer(String),
184}
185
186impl From<ValidationError> for VerificationError {
187 fn from(err: ValidationError) -> Self {
188 VerificationError::InvalidProofStructure(err.to_string())
189 }
190}
191
192#[derive(Debug, Error)]
233pub enum RewardError {
234 #[error("Content not registered: {0}")]
235 ContentNotRegistered(String),
236
237 #[error("Invalid proof data")]
238 InvalidProof,
239
240 #[error("Database error: {0}")]
241 DatabaseError(String),
242
243 #[error("Calculation failed: {0}")]
244 CalculationFailed(String),
245
246 #[error("Insufficient points balance")]
247 InsufficientBalance,
248
249 #[error("Creator not found: {0}")]
250 CreatorNotFound(String),
251
252 #[error("Invalid reward amount: {0}")]
253 InvalidRewardAmount(u64),
254
255 #[error("Reward distribution failed: {0}")]
256 DistributionFailed(String),
257}
258
259pub type ProtocolResult<T> = Result<T, ProtocolError>;
283
284pub type VerificationResult<T> = Result<T, VerificationError>;
308
309pub type RewardResult<T> = Result<T, RewardError>;
337
338#[derive(Debug, Error)]
398pub enum ContentValidationError {
399 #[error("Invalid content size: {0} bytes")]
400 InvalidContentSize(u64),
401
402 #[error("Invalid chunk index: {index} out of {total}")]
403 InvalidChunkIndex { index: u64, total: u64 },
404
405 #[error("Invalid timestamp: {0}")]
406 InvalidTimestamp(String),
407
408 #[error("Invalid signature length: expected {expected}, got {actual}")]
409 InvalidSignatureLength { expected: usize, actual: usize },
410
411 #[error("Invalid public key length: expected {expected}, got {actual}")]
412 InvalidPublicKeyLength { expected: usize, actual: usize },
413
414 #[error("Invalid bandwidth value: {0}")]
415 InvalidBandwidth(String),
416
417 #[error("Content too large: {size} bytes exceeds max {max} bytes")]
418 ContentTooLarge { size: u64, max: u64 },
419
420 #[error("Content too small: {size} bytes is below min {min} bytes")]
421 ContentTooSmall { size: u64, min: u64 },
422
423 #[error("Invalid nonce length: expected {expected}, got {actual}")]
424 InvalidNonceLength { expected: usize, actual: usize },
425
426 #[error("Invalid hash length: expected {expected}, got {actual}")]
427 InvalidHashLength { expected: usize, actual: usize },
428}
429
430pub type ContentValidationResult<T> = Result<T, ContentValidationError>;
432
433#[cfg(test)]
434mod tests {
435 use super::*;
436
437 #[test]
438 fn test_protocol_error_display() {
439 assert_eq!(
440 ProtocolError::InvalidSignature.to_string(),
441 "Invalid signature"
442 );
443
444 assert_eq!(
445 ProtocolError::NonceReused.to_string(),
446 "Nonce already used (replay attack detected)"
447 );
448
449 assert_eq!(
450 ProtocolError::TimestampOutdated.to_string(),
451 "Timestamp out of valid range"
452 );
453
454 assert_eq!(
455 ProtocolError::ContentNotFound("QmTest123".to_string()).to_string(),
456 "Content not found: QmTest123"
457 );
458
459 assert_eq!(
460 ProtocolError::ChunkNotFound(42).to_string(),
461 "Chunk not found: index 42"
462 );
463
464 assert_eq!(
465 ProtocolError::EncryptionError("Key error".to_string()).to_string(),
466 "Encryption error: Key error"
467 );
468
469 assert_eq!(
470 ProtocolError::DecryptionError("Invalid data".to_string()).to_string(),
471 "Decryption error: Invalid data"
472 );
473
474 assert_eq!(
475 ProtocolError::NetworkError("Connection timeout".to_string()).to_string(),
476 "Network error: Connection timeout"
477 );
478
479 assert_eq!(
480 ProtocolError::DatabaseError("Query failed".to_string()).to_string(),
481 "Database error: Query failed"
482 );
483 }
484
485 #[test]
486 fn test_verification_error_display() {
487 assert_eq!(
488 VerificationError::InvalidProviderSignature.to_string(),
489 "Invalid provider signature"
490 );
491
492 assert_eq!(
493 VerificationError::InvalidRequesterSignature.to_string(),
494 "Invalid requester signature"
495 );
496
497 assert_eq!(
498 VerificationError::NonceReused.to_string(),
499 "Nonce has already been used"
500 );
501
502 assert_eq!(
503 VerificationError::TimestampOutOfRange.to_string(),
504 "Timestamp is too old or in the future"
505 );
506
507 assert_eq!(
508 VerificationError::AnomalyDetected("Suspicious pattern".to_string()).to_string(),
509 "Statistical anomaly detected: Suspicious pattern"
510 );
511
512 assert_eq!(
513 VerificationError::PeerBanned("12D3Koo...".to_string()).to_string(),
514 "Peer is banned: 12D3Koo..."
515 );
516 }
517
518 #[test]
519 fn test_reward_error_display() {
520 assert_eq!(
521 RewardError::ContentNotRegistered("QmAbc".to_string()).to_string(),
522 "Content not registered: QmAbc"
523 );
524
525 assert_eq!(RewardError::InvalidProof.to_string(), "Invalid proof data");
526
527 assert_eq!(
528 RewardError::DatabaseError("Connection lost".to_string()).to_string(),
529 "Database error: Connection lost"
530 );
531
532 assert_eq!(
533 RewardError::CalculationFailed("Division by zero".to_string()).to_string(),
534 "Calculation failed: Division by zero"
535 );
536 }
537
538 #[test]
539 fn test_error_source() {
540 let err = ProtocolError::InvalidSignature;
542 let _: &dyn std::error::Error = &err;
543
544 let err = VerificationError::NonceReused;
545 let _: &dyn std::error::Error = &err;
546
547 let err = RewardError::InvalidProof;
548 let _: &dyn std::error::Error = &err;
549 }
550
551 #[test]
552 fn test_new_protocol_errors() {
553 assert_eq!(
554 ProtocolError::PeerNotFound("peer123".to_string()).to_string(),
555 "Peer not found: peer123"
556 );
557 assert_eq!(
558 ProtocolError::InsufficientStorage.to_string(),
559 "Insufficient storage space"
560 );
561 assert_eq!(
562 ProtocolError::BandwidthLimitExceeded.to_string(),
563 "Bandwidth limit exceeded"
564 );
565 assert_eq!(
566 ProtocolError::RateLimitExceeded.to_string(),
567 "Rate limit exceeded"
568 );
569 }
570
571 #[test]
572 fn test_new_verification_errors() {
573 assert_eq!(
574 VerificationError::ChallengeMismatch.to_string(),
575 "Challenge nonce mismatch"
576 );
577 assert_eq!(
578 VerificationError::ChunkHashMismatch.to_string(),
579 "Chunk hash mismatch"
580 );
581 assert_eq!(
582 VerificationError::InvalidLatency(5000).to_string(),
583 "Invalid latency: 5000ms"
584 );
585 }
586
587 #[test]
588 fn test_new_reward_errors() {
589 assert_eq!(
590 RewardError::InsufficientBalance.to_string(),
591 "Insufficient points balance"
592 );
593 assert_eq!(
594 RewardError::CreatorNotFound("creator123".to_string()).to_string(),
595 "Creator not found: creator123"
596 );
597 assert_eq!(
598 RewardError::InvalidRewardAmount(9999).to_string(),
599 "Invalid reward amount: 9999"
600 );
601 }
602
603 #[test]
604 fn test_validation_error_conversion() {
605 use crate::ValidationError;
606
607 let val_err = ValidationError::EmptyCid;
608 let proto_err: ProtocolError = val_err.into();
609 assert!(
610 proto_err
611 .to_string()
612 .contains("Content CID cannot be empty")
613 );
614
615 let val_err2 = ValidationError::SelfTransfer;
616 let verif_err: VerificationError = val_err2.into();
617 assert!(
618 verif_err
619 .to_string()
620 .contains("Provider and requester cannot be the same")
621 );
622 }
623
624 #[test]
625 fn test_result_type_aliases() {
626 fn test_protocol_result() -> ProtocolResult<String> {
627 Ok("success".to_string())
628 }
629
630 fn test_verification_result() -> VerificationResult<i32> {
631 Err(VerificationError::NonceReused)
632 }
633
634 fn test_reward_result() -> RewardResult<u64> {
635 Ok(1000)
636 }
637
638 assert!(test_protocol_result().is_ok());
639 assert!(test_verification_result().is_err());
640 assert_eq!(test_reward_result().unwrap(), 1000);
641 }
642
643 #[test]
644 fn test_content_validation_error_display() {
645 assert_eq!(
646 ContentValidationError::InvalidContentSize(1000).to_string(),
647 "Invalid content size: 1000 bytes"
648 );
649
650 assert_eq!(
651 ContentValidationError::InvalidChunkIndex { index: 5, total: 3 }.to_string(),
652 "Invalid chunk index: 5 out of 3"
653 );
654
655 assert_eq!(
656 ContentValidationError::InvalidTimestamp("future timestamp".to_string()).to_string(),
657 "Invalid timestamp: future timestamp"
658 );
659
660 assert_eq!(
661 ContentValidationError::InvalidSignatureLength {
662 expected: 64,
663 actual: 32
664 }
665 .to_string(),
666 "Invalid signature length: expected 64, got 32"
667 );
668
669 assert_eq!(
670 ContentValidationError::ContentTooLarge {
671 size: 1_000_000_000,
672 max: 500_000_000
673 }
674 .to_string(),
675 "Content too large: 1000000000 bytes exceeds max 500000000 bytes"
676 );
677 }
678
679 #[test]
680 fn test_content_validation_result() {
681 fn validate_size(size: u64) -> ContentValidationResult<u64> {
682 if size > 1000 {
683 Err(ContentValidationError::ContentTooLarge { size, max: 1000 })
684 } else {
685 Ok(size)
686 }
687 }
688
689 assert!(validate_size(500).is_ok());
690 assert!(validate_size(2000).is_err());
691 }
692}