ves_stark_verifier/
error.rs1use thiserror::Error;
4
5pub const PROOF_VERSION: u32 = 2;
7
8pub const MAX_PROOF_SIZE: usize = 10 * 1024 * 1024;
10
11#[derive(Debug, Error)]
13pub enum VerifierError {
14 #[error("Invalid proof structure: {0}")]
16 InvalidProofStructure(String),
17
18 #[error("Public input mismatch: {0}")]
20 PublicInputMismatch(String),
21
22 #[error("FRI verification failed: {0}")]
24 FriVerificationFailed(String),
25
26 #[error("Constraint check failed: {0}")]
28 ConstraintCheckFailed(String),
29
30 #[error("Deserialization error: {0}")]
32 DeserializationError(String),
33
34 #[error("Invalid policy hash: expected {expected}, got {actual}")]
36 InvalidPolicyHash { expected: String, actual: String },
37
38 #[error("Proof verification failed: {0}")]
40 VerificationFailed(String),
41
42 #[error(
45 "Policy mismatch: expected policy '{expected}', but proof was generated for '{actual}'"
46 )]
47 PolicyMismatch { expected: String, actual: String },
48
49 #[error("Limit mismatch: expected {expected}, but proof was generated for {actual}")]
51 LimitMismatch { expected: u64, actual: u64 },
52
53 #[error("Invalid hex format in field '{field}': {reason}")]
55 InvalidHexFormat { field: String, reason: String },
56
57 #[error("Unsupported proof version {version}: only version {supported} is supported")]
59 UnsupportedProofVersion { version: u32, supported: u32 },
60
61 #[error(
63 "Witness commitment mismatch: the proof's commitment doesn't match the expected commitment"
64 )]
65 WitnessCommitmentMismatch,
66
67 #[error("Payload amount binding required: {0}")]
69 PayloadAmountBindingRequired(String),
70
71 #[error("Proof too large: {size} bytes exceeds maximum of {max_size} bytes")]
73 ProofTooLarge { size: usize, max_size: usize },
74}
75
76impl VerifierError {
77 pub fn invalid_structure<S: Into<String>>(msg: S) -> Self {
79 Self::InvalidProofStructure(msg.into())
80 }
81
82 pub fn verification_failed<S: Into<String>>(msg: S) -> Self {
84 Self::VerificationFailed(msg.into())
85 }
86
87 pub fn policy_mismatch(expected: &str, actual: &str) -> Self {
89 Self::PolicyMismatch {
90 expected: expected.to_string(),
91 actual: actual.to_string(),
92 }
93 }
94
95 pub fn limit_mismatch(expected: u64, actual: u64) -> Self {
97 Self::LimitMismatch { expected, actual }
98 }
99
100 pub fn invalid_hex(field: &str, reason: &str) -> Self {
102 Self::InvalidHexFormat {
103 field: field.to_string(),
104 reason: reason.to_string(),
105 }
106 }
107
108 pub fn unsupported_version(version: u32) -> Self {
110 Self::UnsupportedProofVersion {
111 version,
112 supported: PROOF_VERSION,
113 }
114 }
115}
116
117pub fn validate_hex_string(
124 field: &str,
125 value: &str,
126 expected_len: usize,
127) -> Result<(), VerifierError> {
128 if value.len() != expected_len {
130 return Err(VerifierError::invalid_hex(
131 field,
132 &format!("expected {} characters, got {}", expected_len, value.len()),
133 ));
134 }
135
136 for (i, c) in value.chars().enumerate() {
138 if !c.is_ascii_hexdigit() {
139 return Err(VerifierError::invalid_hex(
140 field,
141 &format!("invalid character '{}' at position {}", c, i),
142 ));
143 }
144 if c.is_ascii_uppercase() {
145 return Err(VerifierError::invalid_hex(
146 field,
147 &format!(
148 "uppercase character '{}' at position {} (must be lowercase)",
149 c, i
150 ),
151 ));
152 }
153 }
154
155 Ok(())
156}