1#[cfg(feature = "serde")]
9use serde::Serialize;
10
11pub const N: usize = 256;
13
14pub const Q: i64 = 8_380_417;
16
17pub const Q_HALF: i64 = (Q - 1) / 2;
19
20pub const MONT_R: i64 = 4_193_792;
22
23pub const MONT_R_INV: i64 = 8_265_825;
25
26pub const Q_INV: i64 = 58_728_449;
28
29pub const MAX_ATTEMPTS: usize = 256;
31
32pub const OUTPUT_SIZE: usize = 64;
34
35pub const CHALLENGE_SEED_SIZE: usize = 32;
37
38pub const SEED_SIZE: usize = 32;
40
41pub const DOMAIN_CHALLENGE: &[u8] = b"eyvara-challenge";
43
44pub const DOMAIN_OUTPUT: &[u8] = b"eyvara-output";
46
47pub const DOMAIN_MATRIX: &[u8] = b"vrf-matrix\x00\x00\x00\x00\x00\x00";
49
50#[cfg_attr(feature = "serde", derive(Serialize))]
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65pub struct Params {
66 n: usize,
67 k: usize,
68 q: i64,
69 eta: i64,
70 gamma_1: i64,
71 gamma_2: i64,
72 tau: usize,
73 beta: i64,
74 omega: usize,
75}
76
77impl Params {
78 #[allow(clippy::too_many_arguments)]
79 const fn new(
80 n: usize,
81 k: usize,
82 q: i64,
83 eta: i64,
84 gamma_1: i64,
85 gamma_2: i64,
86 tau: usize,
87 beta: i64,
88 omega: usize,
89 ) -> Self {
90 assert!(tau <= n, "tau must not exceed n");
91 assert!(tau > 0, "tau must be positive");
92 assert!(gamma_1 > beta, "gamma_1 must exceed beta");
93 assert!(gamma_2 > 0, "gamma_2 must be positive");
94 assert!(beta > 0, "beta must be positive");
95 assert!(eta > 0, "eta must be positive");
96 assert!(omega > 0, "omega must be positive");
97 assert!(k > 0, "k must be positive");
98 assert!(q > 0, "q must be positive");
99 Self {
100 n,
101 k,
102 q,
103 eta,
104 gamma_1,
105 gamma_2,
106 tau,
107 beta,
108 omega,
109 }
110 }
111
112 pub const fn n(&self) -> usize {
114 self.n
115 }
116
117 pub const fn k(&self) -> usize {
119 self.k
120 }
121
122 pub const fn q(&self) -> i64 {
124 self.q
125 }
126
127 pub const fn eta(&self) -> i64 {
129 self.eta
130 }
131
132 pub const fn gamma_1(&self) -> i64 {
134 self.gamma_1
135 }
136
137 pub const fn gamma_2(&self) -> i64 {
139 self.gamma_2
140 }
141
142 pub const fn tau(&self) -> usize {
144 self.tau
145 }
146
147 pub const fn beta(&self) -> i64 {
149 self.beta
150 }
151
152 pub const fn omega(&self) -> usize {
154 self.omega
155 }
156
157 pub const fn rejection_bound(&self) -> i64 {
159 self.gamma_1 - self.beta
160 }
161}
162
163pub const EYVARA_128: Params = Params::new(256, 2, 8_380_417, 2, 131_072, 95_232, 39, 78, 80);
165
166pub const EYVARA_192: Params = Params::new(256, 3, 8_380_417, 2, 524_288, 261_888, 49, 98, 120);
169
170#[cfg(test)]
171mod tests {
172 use super::*;
173
174 #[test]
175 fn test_eyvara_i_rejection_bound() {
176 assert_eq!(EYVARA_128.rejection_bound(), 131_072 - 78);
177 }
178
179 #[test]
180 fn test_eyvara_iii_rejection_bound() {
181 assert_eq!(EYVARA_192.rejection_bound(), 524_288 - 98);
182 }
183
184 #[test]
185 fn test_gamma2_divides_q_minus_1() {
186 assert_eq!((Q - 1) % (2 * EYVARA_128.gamma_2()), 0);
187 assert_eq!((Q - 1) % (2 * EYVARA_192.gamma_2()), 0);
188 }
189
190 #[test]
191 fn test_domain_tags_are_nonempty() {
192 assert_eq!(DOMAIN_CHALLENGE.len(), 16);
193 assert!(!DOMAIN_OUTPUT.is_empty());
194 assert_eq!(DOMAIN_MATRIX.len(), 16);
195 }
196}