1#![forbid(unsafe_code)]
15#![allow(missing_docs)] use serde::{Deserialize, Serialize};
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct RingSignature {
22 pub ring_members: Vec<Vec<u8>>,
24 pub signature: Vec<u8>,
26 pub signer_count: u32,
28 pub auditor_evidence: Option<Vec<u8>>,
30}
31
32#[derive(Debug, thiserror::Error)]
34pub enum RingError {
35 #[error("ring too small: {0} members")]
37 RingTooSmall(usize),
38 #[error("signer_count {signer_count} exceeds ring size {ring_size}")]
40 SignerCountExceeds {
41 signer_count: u32,
43 ring_size: usize,
45 },
46 #[error("threshold ring signatures are research-only (P3): {0}")]
48 ResearchOnly(String),
49}
50
51pub fn validate_structure(sig: &RingSignature) -> Result<(), RingError> {
53 if sig.ring_members.len() < 2 {
54 return Err(RingError::RingTooSmall(sig.ring_members.len()));
55 }
56 if sig.signer_count as usize > sig.ring_members.len() {
57 return Err(RingError::SignerCountExceeds {
58 signer_count: sig.signer_count,
59 ring_size: sig.ring_members.len(),
60 });
61 }
62 Ok(())
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn valid_structure_passes() {
71 let sig = RingSignature {
72 ring_members: vec![vec![0u8; 32], vec![1u8; 32], vec![2u8; 32]],
73 signature: vec![0u8; 64],
74 signer_count: 2,
75 auditor_evidence: None,
76 };
77 validate_structure(&sig).unwrap();
78 }
79
80 #[test]
81 fn ring_too_small_fails() {
82 let sig = RingSignature {
83 ring_members: vec![vec![0u8; 32]],
84 signature: vec![0u8; 64],
85 signer_count: 1,
86 auditor_evidence: None,
87 };
88 let result = validate_structure(&sig);
89 assert!(matches!(result, Err(RingError::RingTooSmall(_))));
90 }
91
92 #[test]
93 fn signer_count_exceeds_fails() {
94 let sig = RingSignature {
95 ring_members: vec![vec![0u8; 32], vec![1u8; 32]],
96 signature: vec![0u8; 64],
97 signer_count: 3,
98 auditor_evidence: None,
99 };
100 let result = validate_structure(&sig);
101 assert!(matches!(result, Err(RingError::SignerCountExceeds { .. })));
102 }
103}