error.rs (13212B)
1 #![forbid(unsafe_code)] 2 3 use core::fmt; 4 5 #[cfg(not(feature = "std"))] 6 use alloc::string::String; 7 #[cfg(feature = "std")] 8 use std::string::String; 9 10 #[derive(Debug, PartialEq, Eq)] 11 pub enum RadrootsAuthorityError { 12 InvalidActorPubkey, 13 14 InvalidActorAccountIdEmpty, 15 16 InvalidActorAccountIdUntrimmed, 17 18 InvalidActorAccountIdControlCharacter, 19 20 InvalidActorAccountIdTooLong { 21 max_len: usize, 22 }, 23 24 InvalidSignerPubkey, 25 26 UnknownContract { 27 contract_id: String, 28 }, 29 30 DraftKindMismatch { 31 contract_id: String, 32 expected_kind: u32, 33 actual_kind: u32, 34 }, 35 36 ActorRoleUnsatisfied { 37 contract_id: String, 38 required_role: radroots_events::contract::RadrootsActorRole, 39 }, 40 41 ActorPubkeyMismatch { 42 expected_pubkey: String, 43 actor_pubkey: String, 44 }, 45 46 SignerPubkeyMismatch { 47 expected_pubkey: String, 48 signer_pubkey: String, 49 }, 50 51 SignedEventPubkeyMismatch { 52 expected_pubkey: String, 53 actual_pubkey: String, 54 }, 55 56 SignedEventIdMismatch { 57 expected_event_id: String, 58 actual_event_id: String, 59 }, 60 61 SignedEventCreatedAtMismatch { 62 expected_created_at: u32, 63 actual_created_at: u32, 64 }, 65 66 SignedEventKindMismatch { 67 expected_kind: u32, 68 actual_kind: u32, 69 }, 70 71 SignedEventTagsMismatch { 72 expected_len: usize, 73 actual_len: usize, 74 }, 75 76 SignedEventContentMismatch { 77 expected_len: usize, 78 actual_len: usize, 79 }, 80 81 SignedEventComputedIdInvalid { 82 message: String, 83 }, 84 85 SignedEventComputedIdMismatch { 86 expected_event_id: String, 87 computed_event_id: String, 88 }, 89 90 Signer(RadrootsSignerError), 91 } 92 93 impl fmt::Display for RadrootsAuthorityError { 94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 95 match self { 96 Self::InvalidActorPubkey => write!(f, "invalid actor public key"), 97 Self::InvalidActorAccountIdEmpty => write!(f, "invalid actor account id: empty"), 98 Self::InvalidActorAccountIdUntrimmed => { 99 write!( 100 f, 101 "invalid actor account id: contains leading or trailing whitespace" 102 ) 103 } 104 Self::InvalidActorAccountIdControlCharacter => { 105 write!(f, "invalid actor account id: contains a control character") 106 } 107 Self::InvalidActorAccountIdTooLong { max_len } => { 108 write!( 109 f, 110 "invalid actor account id: longer than {max_len} characters" 111 ) 112 } 113 Self::InvalidSignerPubkey => write!(f, "invalid signer public key"), 114 Self::UnknownContract { contract_id } => { 115 write!(f, "unknown event contract `{contract_id}`") 116 } 117 Self::DraftKindMismatch { 118 contract_id, 119 expected_kind, 120 actual_kind, 121 } => write!( 122 f, 123 "event contract `{contract_id}` expects kind {expected_kind}, got {actual_kind}" 124 ), 125 Self::ActorRoleUnsatisfied { 126 contract_id, 127 required_role, 128 } => write!( 129 f, 130 "actor does not satisfy role {required_role:?} for contract `{contract_id}`" 131 ), 132 Self::ActorPubkeyMismatch { 133 expected_pubkey, 134 actor_pubkey, 135 } => write!( 136 f, 137 "actor pubkey mismatch: expected {expected_pubkey}, got {actor_pubkey}" 138 ), 139 Self::SignerPubkeyMismatch { 140 expected_pubkey, 141 signer_pubkey, 142 } => write!( 143 f, 144 "signer pubkey mismatch: expected {expected_pubkey}, got {signer_pubkey}" 145 ), 146 Self::SignedEventPubkeyMismatch { 147 expected_pubkey, 148 actual_pubkey, 149 } => write!( 150 f, 151 "signed event pubkey mismatch: expected {expected_pubkey}, got {actual_pubkey}" 152 ), 153 Self::SignedEventIdMismatch { 154 expected_event_id, 155 actual_event_id, 156 } => write!( 157 f, 158 "signed event id mismatch: expected {expected_event_id}, got {actual_event_id}" 159 ), 160 Self::SignedEventCreatedAtMismatch { 161 expected_created_at, 162 actual_created_at, 163 } => write!( 164 f, 165 "signed event created_at mismatch: expected {expected_created_at}, got {actual_created_at}" 166 ), 167 Self::SignedEventKindMismatch { 168 expected_kind, 169 actual_kind, 170 } => write!( 171 f, 172 "signed event kind mismatch: expected {expected_kind}, got {actual_kind}" 173 ), 174 Self::SignedEventTagsMismatch { 175 expected_len, 176 actual_len, 177 } => write!( 178 f, 179 "signed event tags mismatch: expected {expected_len} tags, got {actual_len} tags" 180 ), 181 Self::SignedEventContentMismatch { 182 expected_len, 183 actual_len, 184 } => write!( 185 f, 186 "signed event content mismatch: expected {expected_len} bytes, got {actual_len} bytes" 187 ), 188 Self::SignedEventComputedIdInvalid { message } => { 189 write!( 190 f, 191 "signed event computed id could not be derived: {message}" 192 ) 193 } 194 Self::SignedEventComputedIdMismatch { 195 expected_event_id, 196 computed_event_id, 197 } => write!( 198 f, 199 "signed event computed id mismatch: expected {expected_event_id}, computed {computed_event_id}" 200 ), 201 Self::Signer(error) => write!(f, "signer error: {error}"), 202 } 203 } 204 } 205 206 #[cfg(feature = "std")] 207 impl std::error::Error for RadrootsAuthorityError { 208 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 209 match self { 210 Self::Signer(error) => Some(error), 211 _ => None, 212 } 213 } 214 } 215 216 impl From<RadrootsSignerError> for RadrootsAuthorityError { 217 fn from(error: RadrootsSignerError) -> Self { 218 Self::Signer(error) 219 } 220 } 221 222 #[derive(Debug, PartialEq, Eq)] 223 pub enum RadrootsSignerError { 224 Unavailable, 225 226 Rejected, 227 228 SigningFailed { message: String }, 229 } 230 231 impl fmt::Display for RadrootsSignerError { 232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 233 match self { 234 Self::Unavailable => write!(f, "signer unavailable"), 235 Self::Rejected => write!(f, "signer rejected draft"), 236 Self::SigningFailed { message } => write!(f, "signing failed: {message}"), 237 } 238 } 239 } 240 241 #[cfg(feature = "std")] 242 impl std::error::Error for RadrootsSignerError {} 243 244 #[cfg(test)] 245 mod tests { 246 use super::*; 247 use radroots_events::contract::RadrootsActorRole; 248 use std::error::Error as _; 249 250 #[test] 251 fn authority_error_display_uses_contract_messages() { 252 let cases = [ 253 ( 254 RadrootsAuthorityError::InvalidActorPubkey, 255 "invalid actor public key", 256 ), 257 ( 258 RadrootsAuthorityError::InvalidActorAccountIdEmpty, 259 "invalid actor account id: empty", 260 ), 261 ( 262 RadrootsAuthorityError::InvalidActorAccountIdUntrimmed, 263 "invalid actor account id: contains leading or trailing whitespace", 264 ), 265 ( 266 RadrootsAuthorityError::InvalidActorAccountIdControlCharacter, 267 "invalid actor account id: contains a control character", 268 ), 269 ( 270 RadrootsAuthorityError::InvalidActorAccountIdTooLong { max_len: 128 }, 271 "invalid actor account id: longer than 128 characters", 272 ), 273 ( 274 RadrootsAuthorityError::InvalidSignerPubkey, 275 "invalid signer public key", 276 ), 277 ( 278 RadrootsAuthorityError::UnknownContract { 279 contract_id: "radroots.unknown.v1".to_owned(), 280 }, 281 "unknown event contract `radroots.unknown.v1`", 282 ), 283 ( 284 RadrootsAuthorityError::DraftKindMismatch { 285 contract_id: "radroots.social.post.v1".to_owned(), 286 expected_kind: 1, 287 actual_kind: 2, 288 }, 289 "event contract `radroots.social.post.v1` expects kind 1, got 2", 290 ), 291 ( 292 RadrootsAuthorityError::ActorRoleUnsatisfied { 293 contract_id: "radroots.listing.published.v1".to_owned(), 294 required_role: RadrootsActorRole::Seller, 295 }, 296 "actor does not satisfy role Seller for contract `radroots.listing.published.v1`", 297 ), 298 ( 299 RadrootsAuthorityError::ActorPubkeyMismatch { 300 expected_pubkey: "expected".to_owned(), 301 actor_pubkey: "actor".to_owned(), 302 }, 303 "actor pubkey mismatch: expected expected, got actor", 304 ), 305 ( 306 RadrootsAuthorityError::SignerPubkeyMismatch { 307 expected_pubkey: "expected".to_owned(), 308 signer_pubkey: "signer".to_owned(), 309 }, 310 "signer pubkey mismatch: expected expected, got signer", 311 ), 312 ( 313 RadrootsAuthorityError::SignedEventPubkeyMismatch { 314 expected_pubkey: "expected".to_owned(), 315 actual_pubkey: "actual".to_owned(), 316 }, 317 "signed event pubkey mismatch: expected expected, got actual", 318 ), 319 ( 320 RadrootsAuthorityError::SignedEventIdMismatch { 321 expected_event_id: "expected".to_owned(), 322 actual_event_id: "actual".to_owned(), 323 }, 324 "signed event id mismatch: expected expected, got actual", 325 ), 326 ( 327 RadrootsAuthorityError::SignedEventCreatedAtMismatch { 328 expected_created_at: 1, 329 actual_created_at: 2, 330 }, 331 "signed event created_at mismatch: expected 1, got 2", 332 ), 333 ( 334 RadrootsAuthorityError::SignedEventKindMismatch { 335 expected_kind: 1, 336 actual_kind: 2, 337 }, 338 "signed event kind mismatch: expected 1, got 2", 339 ), 340 ( 341 RadrootsAuthorityError::SignedEventTagsMismatch { 342 expected_len: 2, 343 actual_len: 1, 344 }, 345 "signed event tags mismatch: expected 2 tags, got 1 tags", 346 ), 347 ( 348 RadrootsAuthorityError::SignedEventContentMismatch { 349 expected_len: 17, 350 actual_len: 2, 351 }, 352 "signed event content mismatch: expected 17 bytes, got 2 bytes", 353 ), 354 ( 355 RadrootsAuthorityError::SignedEventComputedIdInvalid { 356 message: "invalid event id".to_owned(), 357 }, 358 "signed event computed id could not be derived: invalid event id", 359 ), 360 ( 361 RadrootsAuthorityError::SignedEventComputedIdMismatch { 362 expected_event_id: "expected".to_owned(), 363 computed_event_id: "computed".to_owned(), 364 }, 365 "signed event computed id mismatch: expected expected, computed computed", 366 ), 367 ]; 368 369 for (error, expected) in cases { 370 assert_eq!(error.to_string(), expected); 371 assert!(error.source().is_none()); 372 } 373 } 374 375 #[test] 376 fn signer_error_display_and_source_are_stable() { 377 assert_eq!( 378 RadrootsSignerError::Unavailable.to_string(), 379 "signer unavailable" 380 ); 381 assert_eq!( 382 RadrootsSignerError::Rejected.to_string(), 383 "signer rejected draft" 384 ); 385 386 let signer_error = RadrootsSignerError::SigningFailed { 387 message: "deterministic failure".to_owned(), 388 }; 389 assert_eq!( 390 signer_error.to_string(), 391 "signing failed: deterministic failure" 392 ); 393 394 let authority_error = RadrootsAuthorityError::from(signer_error); 395 assert_eq!( 396 authority_error.to_string(), 397 "signer error: signing failed: deterministic failure" 398 ); 399 assert_eq!( 400 authority_error.source().expect("signer source").to_string(), 401 "signing failed: deterministic failure" 402 ); 403 } 404 }