1pub type Gas = u64;
8
9pub const G_BASE: Gas = 10;
11
12pub const MAX_LIMBS: usize = 512;
14
15pub fn cost_add(n: usize) -> Gas {
19 G_BASE + (3 * n as Gas)
20}
21
22pub fn cost_sub(n: usize) -> Gas {
26 G_BASE + (3 * n as Gas)
27}
28
29pub fn cost_neg(n: usize) -> Gas {
33 G_BASE + (2 * n as Gas)
34}
35
36pub fn cost_cmp(n: usize) -> Gas {
40 G_BASE + (2 * n as Gas)
41}
42
43pub fn cost_shift(n: usize) -> Gas {
47 G_BASE + (2 * n as Gas)
48}
49
50pub fn cost_mul(n: usize) -> Gas {
54 G_BASE + (2 * (n as Gas) * (n as Gas))
55}
56
57pub fn cost_sqr(n: usize) -> Gas {
61 G_BASE + ((16 * (n as Gas) * (n as Gas)) / 10)
62}
63
64pub fn cost_mac(n: usize) -> Gas {
68 cost_mul(n)
69}
70
71pub fn cost_div(n: usize) -> Gas {
75 G_BASE + (4 * (n as Gas) * (n as Gas))
76}
77
78pub fn cost_mod(n: usize) -> Gas {
82 cost_div(n)
83}
84
85pub fn cost_divmod(n: usize) -> Gas {
89 cost_div(n)
90}
91
92pub fn cost_mont_reduce(n: usize) -> Gas {
96 G_BASE + ((n as Gas) * (n as Gas))
97}
98
99pub fn cost_mont_mul(n: usize) -> Gas {
103 G_BASE + (2 * (n as Gas) * (n as Gas))
104}
105
106pub fn cost_mont_add(n: usize) -> Gas {
110 G_BASE + (3 * n as Gas)
111}
112
113pub fn cost_tomont(n: usize) -> Gas {
117 cost_mont_mul(n)
118}
119
120pub fn cost_frommont(n: usize) -> Gas {
124 cost_mont_reduce(n)
125}
126
127pub fn cost_modexp(n: usize, k: usize) -> Gas {
132 let n_gas = n as Gas;
133 let k_gas = k as Gas;
134 G_BASE + (k_gas * 4 * n_gas * n_gas) + (20 * n_gas * n_gas)
135}
136
137pub fn cost_inv_modexp(n: usize, k: usize) -> Gas {
141 cost_modexp(n, k)
142}
143
144pub fn cost_inv_gcd(n: usize) -> Gas {
148 G_BASE + (6 * (n as Gas) * (n as Gas))
149}
150
151pub fn cost_canonicalize(n: usize) -> Gas {
155 G_BASE + (n as Gas)
156}
157
158pub fn cost_encode(n: usize) -> Gas {
162 G_BASE + (n as Gas)
163}
164
165pub fn cost_decode(n: usize) -> Gas {
169 G_BASE + (n as Gas)
170}
171
172pub fn validate_limb_count(n: usize) -> Result<(), ()> {
174 if n > MAX_LIMBS { Err(()) } else { Ok(()) }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[test]
182 fn test_cost_add() {
183 assert_eq!(cost_add(4), 10 + 12); assert_eq!(cost_add(32), 10 + 96); }
186
187 #[test]
188 fn test_cost_mul() {
189 assert_eq!(cost_mul(4), 10 + 32); assert_eq!(cost_mul(32), 10 + 2048); }
192
193 #[test]
194 fn test_cost_modexp() {
195 let cost = cost_modexp(4, 256);
197 assert_eq!(cost, 10 + 16704);
199 }
200
201 #[test]
202 fn test_max_limbs() {
203 assert!(validate_limb_count(512).is_ok());
204 assert!(validate_limb_count(513).is_err());
205 }
206
207 #[test]
208 fn test_cost_sub() {
209 assert_eq!(cost_sub(4), 10 + 12); assert_eq!(cost_sub(32), 10 + 96); }
212
213 #[test]
214 fn test_cost_neg() {
215 assert_eq!(cost_neg(4), 10 + 8); assert_eq!(cost_neg(32), 10 + 64); }
218
219 #[test]
220 fn test_cost_cmp() {
221 assert_eq!(cost_cmp(4), 10 + 8); assert_eq!(cost_cmp(32), 10 + 64); }
224
225 #[test]
226 fn test_cost_shift() {
227 assert_eq!(cost_shift(4), 10 + 8); assert_eq!(cost_shift(32), 10 + 64); }
230
231 #[test]
232 fn test_cost_sqr() {
233 assert_eq!(cost_sqr(4), 10 + 25); assert_eq!(cost_sqr(32), 10 + 1638); }
236
237 #[test]
238 fn test_cost_mac() {
239 assert_eq!(cost_mac(4), 10 + 32); assert_eq!(cost_mac(32), 10 + 2048); }
242
243 #[test]
244 fn test_cost_div() {
245 assert_eq!(cost_div(4), 10 + 64); assert_eq!(cost_div(32), 10 + 4096); }
248
249 #[test]
250 fn test_cost_mod() {
251 assert_eq!(cost_mod(4), 10 + 64); assert_eq!(cost_mod(32), 10 + 4096); }
254
255 #[test]
256 fn test_cost_divmod() {
257 assert_eq!(cost_divmod(4), 10 + 64); assert_eq!(cost_divmod(32), 10 + 4096); }
260
261 #[test]
262 fn test_cost_mont_reduce() {
263 assert_eq!(cost_mont_reduce(4), 10 + 16); assert_eq!(cost_mont_reduce(32), 10 + 1024); }
266
267 #[test]
268 fn test_cost_mont_mul() {
269 assert_eq!(cost_mont_mul(4), 10 + 32); assert_eq!(cost_mont_mul(32), 10 + 2048); }
272
273 #[test]
274 fn test_cost_mont_add() {
275 assert_eq!(cost_mont_add(4), 10 + 12); assert_eq!(cost_mont_add(32), 10 + 96); }
278
279 #[test]
280 fn test_cost_tomont() {
281 assert_eq!(cost_tomont(4), 10 + 32); assert_eq!(cost_tomont(32), 10 + 2048); }
284
285 #[test]
286 fn test_cost_frommont() {
287 assert_eq!(cost_frommont(4), 10 + 16); assert_eq!(cost_frommont(32), 10 + 1024); }
290
291 #[test]
292 fn test_cost_inv_modexp() {
293 let cost = cost_inv_modexp(4, 256);
295 assert_eq!(cost, cost_modexp(4, 256));
297 }
298
299 #[test]
300 fn test_cost_inv_gcd() {
301 assert_eq!(cost_inv_gcd(4), 10 + 96); assert_eq!(cost_inv_gcd(32), 10 + 6144); }
304
305 #[test]
306 fn test_cost_canonicalize() {
307 assert_eq!(cost_canonicalize(4), 10 + 4); assert_eq!(cost_canonicalize(32), 10 + 32); }
310
311 #[test]
312 fn test_cost_encode() {
313 assert_eq!(cost_encode(4), 10 + 4); assert_eq!(cost_encode(32), 10 + 32); }
316
317 #[test]
318 fn test_cost_decode() {
319 assert_eq!(cost_decode(4), 10 + 4); assert_eq!(cost_decode(32), 10 + 32); }
322
323 #[test]
324 fn test_gas_costs_are_positive() {
325 assert!(cost_add(1) > 0);
327 assert!(cost_sub(1) > 0);
328 assert!(cost_mul(1) > 0);
329 assert!(cost_div(1) > 0);
330 assert!(cost_modexp(1, 1) > 0);
331 }
332
333 #[test]
334 fn test_gas_costs_increase_with_size() {
335 assert!(cost_add(8) > cost_add(4));
337 assert!(cost_mul(8) > cost_mul(4));
338 assert!(cost_modexp(8, 64) > cost_modexp(4, 32));
339 }
340
341 #[test]
342 fn test_gas_constants() {
343 assert_eq!(G_BASE, 10);
344 assert_eq!(MAX_LIMBS, 512);
345 }
346}