Skip to main content

kinetic_core/error/
vdf.rs

1//! VDF engine error types (`KIN-VDF-NNN`).
2//!
3//! Two complementary enums cover the full VDF error surface:
4//!
5//! - [`VdfRejectReason`] — proof-level rejection; used by the DHT store verifier
6//!   when a submitted proof cannot be verified against its challenge.
7//! - [`VdfError`] — engine-level failure; used by the VDF prover when generating
8//!   a new proof for the local node's own registrations.
9//!
10//! ## Protocol Context
11//!
12//! Kinetic uses a Wesolowski VDF (chiavdf library) where the challenge is derived
13//! from the Drand randomness at commitment time:
14//! `challenge = SHA-256(network_id || name || salt || drand_signature_hex)`.
15//!
16//! The VDF prover is serialized via a filesystem lock file to prevent parallel
17//! proof generation from exhausting CPU resources. [`VdfError::LockAcquireError`]
18//! is the only retryable variant (`KIN-VDF-002`).
19use super::Severity;
20use thiserror::Error;
21
22/// Why a VDF proof was rejected.
23#[derive(Error, Debug, PartialEq, Eq)]
24pub enum VdfRejectReason {
25    /// The proof byte array was the wrong size or could not be parsed.
26    #[error("proof bytes are malformed")]
27    MalformedProof,
28    /// The proof verified successfully, but for a different challenge than expected.
29    #[error("proof does not match the challenge")]
30    ChallengeMismatch,
31    /// The underlying chiavdf verifier threw an internal error.
32    #[error("VDF engine error: {0}")]
33    EngineError(String),
34    /// Generating the discriminant from the challenge failed.
35    #[error("discriminant creation failed")]
36    DiscriminantFailed,
37}
38
39/// Errors originating from the VDF engine
40#[derive(Error, Debug, PartialEq, Eq)]
41pub enum VdfError {
42    /// The filesystem could not create the lock file needed to serialize VDF tasks.
43    #[error("Failed to create VDF lock file: {0}")]
44    LockFileError(String),
45    /// A timeout or OS error occurred while attempting to acquire the VDF lock.
46    #[error("Failed to acquire VDF lock: {0}")]
47    LockAcquireError(String),
48    /// Generating the discriminant from the challenge failed.
49    #[error("Failed to create VDF discriminant")]
50    DiscriminantError,
51    /// The underlying chiavdf prover threw an internal error or panicked.
52    #[error("Failed to generate VDF proof")]
53    ProofGenerationError,
54    /// The current architecture or OS is not supported by the embedded chiavdf library.
55    #[error("VDF operation is unsupported on this platform")]
56    UnsupportedPlatform,
57    /// The proof exceeds acceptable bounds or is malformed before parsing.
58    #[error("VDF proof is structurally invalid or too large")]
59    InvalidProof,
60}
61
62impl VdfError {
63    /// Stable protocol error code. Part of the Kinetic error taxonomy.
64    pub fn code(&self) -> &'static str {
65        match self {
66            Self::LockFileError(_) => "KIN-VDF-001",
67            Self::LockAcquireError(_) => "KIN-VDF-002",
68            Self::DiscriminantError => "KIN-VDF-003",
69            Self::ProofGenerationError => "KIN-VDF-004",
70            Self::UnsupportedPlatform => "KIN-VDF-005",
71            Self::InvalidProof => "KIN-VDF-006",
72        }
73    }
74
75    /// RFC 7807 type URI for this error.
76    pub fn error_type_uri(&self) -> String {
77        format!("{}/errors/{}", crate::constants::DOCS_URL, self.code())
78    }
79
80    /// Severity level for logging and monitoring.
81    pub fn severity(&self) -> Severity {
82        match self {
83            Self::LockFileError(_) | Self::LockAcquireError(_) => Severity::Error,
84            Self::DiscriminantError | Self::ProofGenerationError | Self::InvalidProof => {
85                Severity::Error
86            }
87            Self::UnsupportedPlatform => Severity::Critical,
88        }
89    }
90
91    /// Whether the client should offer a retry action.
92    pub fn is_retryable(&self) -> bool {
93        matches!(self, Self::LockAcquireError(_))
94    }
95
96    /// Returns the user-facing message.
97    pub fn user_message(&self) -> String {
98        match self {
99            Self::LockFileError(_) => "Failed to create VDF lock file.".to_string(),
100            Self::LockAcquireError(_) => "Failed to acquire VDF lock.".to_string(),
101            Self::DiscriminantError => "Failed to create VDF discriminant.".to_string(),
102            Self::ProofGenerationError => "Failed to generate VDF proof.".to_string(),
103            Self::UnsupportedPlatform => {
104                "VDF operations are not supported on this platform.".to_string()
105            }
106            Self::InvalidProof => "The VDF proof is structurally invalid or too large.".to_string(),
107        }
108    }
109}