confium_tc_frost_ed25519/
error.rs1use snafu::Snafu;
13
14pub const FROST_ERROR_BASE: u32 = 0x2100;
18
19#[derive(Snafu, Debug)]
22#[snafu(visibility(pub))]
23pub enum FrostError {
24 #[snafu(display("invalid commitment from party '{party}': {reason}"))]
26 InvalidCommitment {
27 party: String,
28 reason: &'static str,
29 code: u32,
30 },
31
32 #[snafu(display("invalid share response from party '{party}': {reason}"))]
34 InvalidShareResponse {
35 party: String,
36 reason: &'static str,
37 code: u32,
38 },
39
40 #[snafu(display("below threshold: {have} contributing parties, need {need}"))]
42 BelowThreshold { have: u32, need: u32, code: u32 },
43
44 #[snafu(display("missing commitment for party '{party}'"))]
46 MissingCommitment { party: String, code: u32 },
47
48 #[snafu(display("party '{party}' produced an invalid share response (byzantine)"))]
51 InvalidShareSignature { party: String, code: u32 },
52
53 #[snafu(display("aggregate signature failed verification"))]
56 AggregateVerificationFailed { code: u32 },
57
58 #[snafu(display("local share is malformed: {reason}"))]
60 MalformedShare { reason: &'static str, code: u32 },
61
62 #[snafu(display("VSS share from party '{party}' failed verification (byzantine)"))]
65 VssShareVerificationFailed { party: String, code: u32 },
66
67 #[snafu(display("roster configuration error: {reason}"))]
69 RosterConfig { reason: &'static str, code: u32 },
70
71 #[snafu(display("malformed wire message: {reason}"))]
73 MalformedMessage { reason: &'static str, code: u32 },
74
75 #[snafu(display("round overflow at round {round}"))]
77 RoundOverflow { round: u8, code: u32 },
78
79 #[snafu(display("session is not complete"))]
81 SessionNotComplete { code: u32 },
82}
83
84impl FrostError {
85 pub fn code(&self) -> u32 {
89 match self {
90 FrostError::InvalidCommitment { code, .. }
91 | FrostError::InvalidShareResponse { code, .. }
92 | FrostError::BelowThreshold { code, .. }
93 | FrostError::MissingCommitment { code, .. }
94 | FrostError::InvalidShareSignature { code, .. }
95 | FrostError::AggregateVerificationFailed { code, .. }
96 | FrostError::MalformedShare { code, .. }
97 | FrostError::VssShareVerificationFailed { code, .. }
98 | FrostError::RosterConfig { code, .. }
99 | FrostError::MalformedMessage { code, .. }
100 | FrostError::RoundOverflow { code, .. }
101 | FrostError::SessionNotComplete { code, .. } => *code,
102 }
103 }
104
105 pub fn framework(self) -> confium_tc::Error {
109 confium_tc::error::SchemeInternalSnafu {
110 code: FROST_ERROR_BASE | self.code(),
111 }
112 .build()
113 }
114}
115
116pub type Result<T> = std::result::Result<T, FrostError>;
117
118pub const CODE_INVALID_COMMITMENT: u32 = 0x01;
123pub const CODE_INVALID_SHARE_RESPONSE: u32 = 0x02;
124pub const CODE_BELOW_THRESHOLD: u32 = 0x03;
125pub const CODE_MISSING_COMMITMENT: u32 = 0x04;
126pub const CODE_INVALID_SHARE_SIG: u32 = 0x05;
127pub const CODE_AGG_VERIFY_FAILED: u32 = 0x06;
128pub const CODE_MALFORMED_SHARE: u32 = 0x07;
129pub const CODE_VSS_VERIFY_FAILED: u32 = 0x08;
130pub const CODE_ROSTER_CONFIG: u32 = 0x09;
131pub const CODE_MALFORMED_MESSAGE: u32 = 0x0A;
132pub const CODE_ROUND_OVERFLOW: u32 = 0x0B;
133pub const CODE_SESSION_NOT_COMPLETE: u32 = 0x0C;
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn codes_are_disjoint() {
141 let codes = [
142 CODE_INVALID_COMMITMENT,
143 CODE_INVALID_SHARE_RESPONSE,
144 CODE_BELOW_THRESHOLD,
145 CODE_MISSING_COMMITMENT,
146 CODE_INVALID_SHARE_SIG,
147 CODE_AGG_VERIFY_FAILED,
148 CODE_MALFORMED_SHARE,
149 CODE_VSS_VERIFY_FAILED,
150 CODE_ROSTER_CONFIG,
151 CODE_MALFORMED_MESSAGE,
152 CODE_ROUND_OVERFLOW,
153 CODE_SESSION_NOT_COMPLETE,
154 ];
155 let mut sorted = codes;
156 sorted.sort_unstable();
157 for w in sorted.windows(2) {
158 assert_ne!(w[0], w[1], "error sub-codes must be distinct");
159 }
160 }
161
162 #[test]
163 fn framework_code_carries_base() {
164 let e = FrostError::BelowThreshold {
165 have: 1,
166 need: 2,
167 code: CODE_BELOW_THRESHOLD,
168 };
169 let fw = e.framework();
170 let reported = match fw {
171 confium_tc::Error::SchemeInternalError { code, .. } => code,
172 _ => panic!("expected SchemeInternalError"),
173 };
174 assert_eq!(reported, FROST_ERROR_BASE | CODE_BELOW_THRESHOLD);
175 }
176}