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}