light_utils/
bigint.rs

1use num_bigint::BigUint;
2
3use crate::UtilsError;
4
5/// Converts the given [`num_bigint::BigUint`](num_bigint::BigUint) into a little-endian
6/// byte array.
7pub fn bigint_to_le_bytes_array<const BYTES_SIZE: usize>(
8    bigint: &BigUint,
9) -> Result<[u8; BYTES_SIZE], UtilsError> {
10    let mut array = [0u8; BYTES_SIZE];
11    let bytes = bigint.to_bytes_le();
12
13    if bytes.len() > BYTES_SIZE {
14        return Err(UtilsError::InputTooLarge(BYTES_SIZE));
15    }
16
17    array[..bytes.len()].copy_from_slice(bytes.as_slice());
18    Ok(array)
19}
20
21/// Converts the given [`ark_ff::BigUint`](ark_ff::BigUint) into a big-endian
22/// byte array.
23pub fn bigint_to_be_bytes_array<const BYTES_SIZE: usize>(
24    bigint: &BigUint,
25) -> Result<[u8; BYTES_SIZE], UtilsError> {
26    let mut array = [0u8; BYTES_SIZE];
27    let bytes = bigint.to_bytes_be();
28
29    if bytes.len() > BYTES_SIZE {
30        return Err(UtilsError::InputTooLarge(BYTES_SIZE));
31    }
32
33    let start_pos = BYTES_SIZE - bytes.len();
34    array[start_pos..].copy_from_slice(bytes.as_slice());
35    Ok(array)
36}
37
38#[cfg(test)]
39mod test {
40    use num_bigint::{RandBigInt, ToBigUint};
41    use rand::thread_rng;
42
43    use super::*;
44
45    const ITERATIONS: usize = 64;
46
47    #[test]
48    fn test_bigint_conversion_rand() {
49        let mut rng = thread_rng();
50
51        for _ in 0..ITERATIONS {
52            let b64 = rng.gen_biguint(32);
53            let b64_converted: [u8; 8] = bigint_to_be_bytes_array(&b64).unwrap();
54            let b64_converted = BigUint::from_bytes_be(&b64_converted);
55            assert_eq!(b64, b64_converted);
56            let b64_converted: [u8; 8] = bigint_to_le_bytes_array(&b64).unwrap();
57            let b64_converted = BigUint::from_bytes_le(&b64_converted);
58            assert_eq!(b64, b64_converted);
59
60            let b128 = rng.gen_biguint(128);
61            let b128_converted: [u8; 16] = bigint_to_be_bytes_array(&b128).unwrap();
62            let b128_converted = BigUint::from_bytes_be(&b128_converted);
63            assert_eq!(b128, b128_converted);
64            let b128_converted: [u8; 16] = bigint_to_le_bytes_array(&b128).unwrap();
65            let b128_converted = BigUint::from_bytes_le(&b128_converted);
66            assert_eq!(b128, b128_converted);
67
68            let b256 = rng.gen_biguint(256);
69            let b256_converted: [u8; 32] = bigint_to_be_bytes_array(&b256).unwrap();
70            let b256_converted = BigUint::from_bytes_be(&b256_converted);
71            assert_eq!(b256, b256_converted);
72            let b256_converted: [u8; 32] = bigint_to_le_bytes_array(&b256).unwrap();
73            let b256_converted = BigUint::from_bytes_le(&b256_converted);
74            assert_eq!(b256, b256_converted);
75
76            let b320 = rng.gen_biguint(320);
77            let b320_converted: [u8; 40] = bigint_to_be_bytes_array(&b320).unwrap();
78            let b320_converted = BigUint::from_bytes_be(&b320_converted);
79            assert_eq!(b320, b320_converted);
80            let b320_converted: [u8; 40] = bigint_to_le_bytes_array(&b320).unwrap();
81            let b320_converted = BigUint::from_bytes_le(&b320_converted);
82            assert_eq!(b320, b320_converted);
83
84            let b384 = rng.gen_biguint(384);
85            let b384_converted: [u8; 48] = bigint_to_be_bytes_array(&b384).unwrap();
86            let b384_converted = BigUint::from_bytes_be(&b384_converted);
87            assert_eq!(b384, b384_converted);
88            let b384_converted: [u8; 48] = bigint_to_le_bytes_array(&b384).unwrap();
89            let b384_converted = BigUint::from_bytes_le(&b384_converted);
90            assert_eq!(b384, b384_converted);
91
92            let b448 = rng.gen_biguint(448);
93            let b448_converted: [u8; 56] = bigint_to_be_bytes_array(&b448).unwrap();
94            let b448_converted = BigUint::from_bytes_be(&b448_converted);
95            assert_eq!(b448, b448_converted);
96            let b448_converted: [u8; 56] = bigint_to_le_bytes_array(&b448).unwrap();
97            let b448_converted = BigUint::from_bytes_le(&b448_converted);
98            assert_eq!(b448, b448_converted);
99
100            let b768 = rng.gen_biguint(768);
101            let b768_converted: [u8; 96] = bigint_to_be_bytes_array(&b768).unwrap();
102            let b768_converted = BigUint::from_bytes_be(&b768_converted);
103            assert_eq!(b768, b768_converted);
104            let b768_converted: [u8; 96] = bigint_to_le_bytes_array(&b768).unwrap();
105            let b768_converted = BigUint::from_bytes_le(&b768_converted);
106            assert_eq!(b768, b768_converted);
107
108            let b832 = rng.gen_biguint(832);
109            let b832_converted: [u8; 104] = bigint_to_be_bytes_array(&b832).unwrap();
110            let b832_converted = BigUint::from_bytes_be(&b832_converted);
111            assert_eq!(b832, b832_converted);
112            let b832_converted: [u8; 104] = bigint_to_le_bytes_array(&b832).unwrap();
113            let b832_converted = BigUint::from_bytes_le(&b832_converted);
114            assert_eq!(b832, b832_converted);
115        }
116    }
117
118    #[test]
119    fn test_bigint_conversion_zero() {
120        let zero = 0_u32.to_biguint().unwrap();
121
122        let b64_converted: [u8; 8] = bigint_to_be_bytes_array(&zero).unwrap();
123        let b64_converted = BigUint::from_bytes_be(&b64_converted);
124        assert_eq!(zero, b64_converted);
125        let b64_converted: [u8; 8] = bigint_to_le_bytes_array(&zero).unwrap();
126        let b64_converted = BigUint::from_bytes_le(&b64_converted);
127        assert_eq!(zero, b64_converted);
128
129        let b128_converted: [u8; 16] = bigint_to_be_bytes_array(&zero).unwrap();
130        let b128_converted = BigUint::from_bytes_be(&b128_converted);
131        assert_eq!(zero, b128_converted);
132        let b128_converted: [u8; 16] = bigint_to_le_bytes_array(&zero).unwrap();
133        let b128_converted = BigUint::from_bytes_le(&b128_converted);
134        assert_eq!(zero, b128_converted);
135
136        let b256_converted: [u8; 32] = bigint_to_be_bytes_array(&zero).unwrap();
137        let b256_converted = BigUint::from_bytes_be(&b256_converted);
138        assert_eq!(zero, b256_converted);
139        let b256_converted: [u8; 32] = bigint_to_le_bytes_array(&zero).unwrap();
140        let b256_converted = BigUint::from_bytes_le(&b256_converted);
141        assert_eq!(zero, b256_converted);
142
143        let b320_converted: [u8; 40] = bigint_to_be_bytes_array(&zero).unwrap();
144        let b320_converted = BigUint::from_bytes_be(&b320_converted);
145        assert_eq!(zero, b320_converted);
146        let b320_converted: [u8; 40] = bigint_to_le_bytes_array(&zero).unwrap();
147        let b320_converted = BigUint::from_bytes_le(&b320_converted);
148        assert_eq!(zero, b320_converted);
149
150        let b384_converted: [u8; 48] = bigint_to_be_bytes_array(&zero).unwrap();
151        let b384_converted = BigUint::from_bytes_be(&b384_converted);
152        assert_eq!(zero, b384_converted);
153        let b384_converted: [u8; 48] = bigint_to_le_bytes_array(&zero).unwrap();
154        let b384_converted = BigUint::from_bytes_le(&b384_converted);
155        assert_eq!(zero, b384_converted);
156
157        let b448_converted: [u8; 56] = bigint_to_be_bytes_array(&zero).unwrap();
158        let b448_converted = BigUint::from_bytes_be(&b448_converted);
159        assert_eq!(zero, b448_converted);
160        let b448_converted: [u8; 56] = bigint_to_le_bytes_array(&zero).unwrap();
161        let b448_converted = BigUint::from_bytes_le(&b448_converted);
162        assert_eq!(zero, b448_converted);
163
164        let b768_converted: [u8; 96] = bigint_to_be_bytes_array(&zero).unwrap();
165        let b768_converted = BigUint::from_bytes_be(&b768_converted);
166        assert_eq!(zero, b768_converted);
167        let b768_converted: [u8; 96] = bigint_to_le_bytes_array(&zero).unwrap();
168        let b768_converted = BigUint::from_bytes_le(&b768_converted);
169        assert_eq!(zero, b768_converted);
170
171        let b832_converted: [u8; 104] = bigint_to_be_bytes_array(&zero).unwrap();
172        let b832_converted = BigUint::from_bytes_be(&b832_converted);
173        assert_eq!(zero, b832_converted);
174        let b832_converted: [u8; 104] = bigint_to_le_bytes_array(&zero).unwrap();
175        let b832_converted = BigUint::from_bytes_le(&b832_converted);
176        assert_eq!(zero, b832_converted);
177    }
178
179    #[test]
180    fn test_bigint_conversion_one() {
181        let one = 1_u32.to_biguint().unwrap();
182
183        let b64_converted: [u8; 8] = bigint_to_be_bytes_array(&one).unwrap();
184        let b64_converted = BigUint::from_bytes_be(&b64_converted);
185        assert_eq!(one, b64_converted);
186        let b64_converted: [u8; 8] = bigint_to_le_bytes_array(&one).unwrap();
187        let b64_converted = BigUint::from_bytes_le(&b64_converted);
188        assert_eq!(one, b64_converted);
189        let b64 = BigUint::from_bytes_be(&[0, 0, 0, 0, 0, 0, 0, 1]);
190        assert_eq!(one, b64);
191        let b64 = BigUint::from_bytes_le(&[1, 0, 0, 0, 0, 0, 0, 0]);
192        assert_eq!(one, b64);
193
194        let b128_converted: [u8; 16] = bigint_to_be_bytes_array(&one).unwrap();
195        let b128_converted = BigUint::from_bytes_be(&b128_converted);
196        assert_eq!(one, b128_converted);
197        let b128_converted: [u8; 16] = bigint_to_le_bytes_array(&one).unwrap();
198        let b128_converted = BigUint::from_bytes_le(&b128_converted);
199        assert_eq!(one, b128_converted);
200
201        let b256_converted: [u8; 32] = bigint_to_be_bytes_array(&one).unwrap();
202        let b256_converted = BigUint::from_bytes_be(&b256_converted);
203        assert_eq!(one, b256_converted);
204        let b256_converted: [u8; 32] = bigint_to_le_bytes_array(&one).unwrap();
205        let b256_converted = BigUint::from_bytes_le(&b256_converted);
206        assert_eq!(one, b256_converted);
207
208        let b320_converted: [u8; 40] = bigint_to_be_bytes_array(&one).unwrap();
209        let b320_converted = BigUint::from_bytes_be(&b320_converted);
210        assert_eq!(one, b320_converted);
211        let b320_converted: [u8; 40] = bigint_to_le_bytes_array(&one).unwrap();
212        let b320_converted = BigUint::from_bytes_le(&b320_converted);
213        assert_eq!(one, b320_converted);
214
215        let b384_converted: [u8; 48] = bigint_to_be_bytes_array(&one).unwrap();
216        let b384_converted = BigUint::from_bytes_be(&b384_converted);
217        assert_eq!(one, b384_converted);
218        let b384_converted: [u8; 48] = bigint_to_le_bytes_array(&one).unwrap();
219        let b384_converted = BigUint::from_bytes_le(&b384_converted);
220        assert_eq!(one, b384_converted);
221
222        let b448_converted: [u8; 56] = bigint_to_be_bytes_array(&one).unwrap();
223        let b448_converted = BigUint::from_bytes_be(&b448_converted);
224        assert_eq!(one, b448_converted);
225        let b448_converted: [u8; 56] = bigint_to_le_bytes_array(&one).unwrap();
226        let b448_converted = BigUint::from_bytes_le(&b448_converted);
227        assert_eq!(one, b448_converted);
228
229        let b768_converted: [u8; 96] = bigint_to_be_bytes_array(&one).unwrap();
230        let b768_converted = BigUint::from_bytes_be(&b768_converted);
231        assert_eq!(one, b768_converted);
232        let b768_converted: [u8; 96] = bigint_to_le_bytes_array(&one).unwrap();
233        let b768_converted = BigUint::from_bytes_le(&b768_converted);
234        assert_eq!(one, b768_converted);
235
236        let b832_converted: [u8; 104] = bigint_to_be_bytes_array(&one).unwrap();
237        let b832_converted = BigUint::from_bytes_be(&b832_converted);
238        assert_eq!(one, b832_converted);
239        let b832_converted: [u8; 104] = bigint_to_le_bytes_array(&one).unwrap();
240        let b832_converted = BigUint::from_bytes_le(&b832_converted);
241        assert_eq!(one, b832_converted);
242    }
243
244    #[test]
245    fn test_bigint_conversion_invalid_size() {
246        let b8 = BigUint::from_bytes_be(&[1; 8]);
247        let res: Result<[u8; 1], UtilsError> = bigint_to_be_bytes_array(&b8);
248        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
249        let res: Result<[u8; 7], UtilsError> = bigint_to_be_bytes_array(&b8);
250        assert!(matches!(res, Err(UtilsError::InputTooLarge(7))));
251        let res: Result<[u8; 8], UtilsError> = bigint_to_be_bytes_array(&b8);
252        assert!(res.is_ok());
253
254        let b8 = BigUint::from_bytes_le(&[1; 8]);
255        let res: Result<[u8; 1], UtilsError> = bigint_to_le_bytes_array(&b8);
256        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
257        let res: Result<[u8; 7], UtilsError> = bigint_to_le_bytes_array(&b8);
258        assert!(matches!(res, Err(UtilsError::InputTooLarge(7))));
259        let res: Result<[u8; 8], UtilsError> = bigint_to_le_bytes_array(&b8);
260        assert!(res.is_ok());
261
262        let b16 = BigUint::from_bytes_be(&[1; 16]);
263        let res: Result<[u8; 1], UtilsError> = bigint_to_be_bytes_array(&b16);
264        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
265        let res: Result<[u8; 15], UtilsError> = bigint_to_be_bytes_array(&b16);
266        assert!(matches!(res, Err(UtilsError::InputTooLarge(15))));
267        let res: Result<[u8; 16], UtilsError> = bigint_to_be_bytes_array(&b16);
268        assert!(res.is_ok());
269
270        let b16 = BigUint::from_bytes_le(&[1; 16]);
271        let res: Result<[u8; 1], UtilsError> = bigint_to_le_bytes_array(&b16);
272        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
273        let res: Result<[u8; 15], UtilsError> = bigint_to_le_bytes_array(&b16);
274        assert!(matches!(res, Err(UtilsError::InputTooLarge(15))));
275        let res: Result<[u8; 16], UtilsError> = bigint_to_le_bytes_array(&b16);
276        assert!(res.is_ok());
277
278        let b32 = BigUint::from_bytes_be(&[1; 32]);
279        let res: Result<[u8; 1], UtilsError> = bigint_to_be_bytes_array(&b32);
280        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
281        let res: Result<[u8; 31], UtilsError> = bigint_to_be_bytes_array(&b32);
282        assert!(matches!(res, Err(UtilsError::InputTooLarge(31))));
283        let res: Result<[u8; 32], UtilsError> = bigint_to_be_bytes_array(&b32);
284        assert!(res.is_ok());
285
286        let b32 = BigUint::from_bytes_le(&[1; 32]);
287        let res: Result<[u8; 1], UtilsError> = bigint_to_le_bytes_array(&b32);
288        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
289        let res: Result<[u8; 31], UtilsError> = bigint_to_le_bytes_array(&b32);
290        assert!(matches!(res, Err(UtilsError::InputTooLarge(31))));
291        let res: Result<[u8; 32], UtilsError> = bigint_to_le_bytes_array(&b32);
292        assert!(res.is_ok());
293
294        let b64 = BigUint::from_bytes_be(&[1; 64]);
295        let res: Result<[u8; 1], UtilsError> = bigint_to_be_bytes_array(&b64);
296        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
297        let res: Result<[u8; 63], UtilsError> = bigint_to_be_bytes_array(&b64);
298        assert!(matches!(res, Err(UtilsError::InputTooLarge(63))));
299        let res: Result<[u8; 64], UtilsError> = bigint_to_be_bytes_array(&b64);
300        assert!(res.is_ok());
301
302        let b64 = BigUint::from_bytes_le(&[1; 64]);
303        let res: Result<[u8; 1], UtilsError> = bigint_to_le_bytes_array(&b64);
304        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
305        let res: Result<[u8; 63], UtilsError> = bigint_to_le_bytes_array(&b64);
306        assert!(matches!(res, Err(UtilsError::InputTooLarge(63))));
307        let res: Result<[u8; 64], UtilsError> = bigint_to_le_bytes_array(&b64);
308        assert!(res.is_ok());
309
310        let b128 = BigUint::from_bytes_be(&[1; 128]);
311        let res: Result<[u8; 1], UtilsError> = bigint_to_be_bytes_array(&b128);
312        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
313        let res: Result<[u8; 127], UtilsError> = bigint_to_be_bytes_array(&b128);
314        assert!(matches!(res, Err(UtilsError::InputTooLarge(127))));
315        let res: Result<[u8; 128], UtilsError> = bigint_to_be_bytes_array(&b128);
316        assert!(res.is_ok());
317
318        let b128 = BigUint::from_bytes_le(&[1; 128]);
319        let res: Result<[u8; 1], UtilsError> = bigint_to_le_bytes_array(&b128);
320        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
321        let res: Result<[u8; 127], UtilsError> = bigint_to_le_bytes_array(&b128);
322        assert!(matches!(res, Err(UtilsError::InputTooLarge(127))));
323        let res: Result<[u8; 128], UtilsError> = bigint_to_le_bytes_array(&b128);
324        assert!(res.is_ok());
325
326        let b256 = BigUint::from_bytes_be(&[1; 256]);
327        let res: Result<[u8; 1], UtilsError> = bigint_to_be_bytes_array(&b256);
328        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
329        let res: Result<[u8; 255], UtilsError> = bigint_to_be_bytes_array(&b256);
330        assert!(matches!(res, Err(UtilsError::InputTooLarge(255))));
331        let res: Result<[u8; 256], UtilsError> = bigint_to_be_bytes_array(&b256);
332        assert!(res.is_ok());
333
334        let b256 = BigUint::from_bytes_le(&[1; 256]);
335        let res: Result<[u8; 1], UtilsError> = bigint_to_le_bytes_array(&b256);
336        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
337        let res: Result<[u8; 255], UtilsError> = bigint_to_le_bytes_array(&b256);
338        assert!(matches!(res, Err(UtilsError::InputTooLarge(255))));
339        let res: Result<[u8; 256], UtilsError> = bigint_to_le_bytes_array(&b256);
340        assert!(res.is_ok());
341
342        let b512 = BigUint::from_bytes_be(&[1; 512]);
343        let res: Result<[u8; 1], UtilsError> = bigint_to_be_bytes_array(&b512);
344        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
345        let res: Result<[u8; 511], UtilsError> = bigint_to_be_bytes_array(&b512);
346        assert!(matches!(res, Err(UtilsError::InputTooLarge(511))));
347        let res: Result<[u8; 512], UtilsError> = bigint_to_be_bytes_array(&b512);
348        assert!(res.is_ok());
349
350        let b512 = BigUint::from_bytes_le(&[1; 512]);
351        let res: Result<[u8; 1], UtilsError> = bigint_to_le_bytes_array(&b512);
352        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
353        let res: Result<[u8; 511], UtilsError> = bigint_to_le_bytes_array(&b512);
354        assert!(matches!(res, Err(UtilsError::InputTooLarge(511))));
355        let res: Result<[u8; 512], UtilsError> = bigint_to_le_bytes_array(&b512);
356        assert!(res.is_ok());
357
358        let b768 = BigUint::from_bytes_be(&[1; 768]);
359        let res: Result<[u8; 1], UtilsError> = bigint_to_be_bytes_array(&b768);
360        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
361        let res: Result<[u8; 767], UtilsError> = bigint_to_be_bytes_array(&b768);
362        assert!(matches!(res, Err(UtilsError::InputTooLarge(767))));
363        let res: Result<[u8; 768], UtilsError> = bigint_to_be_bytes_array(&b768);
364        assert!(res.is_ok());
365
366        let b768 = BigUint::from_bytes_le(&[1; 768]);
367        let res: Result<[u8; 1], UtilsError> = bigint_to_le_bytes_array(&b768);
368        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
369        let res: Result<[u8; 767], UtilsError> = bigint_to_le_bytes_array(&b768);
370        assert!(matches!(res, Err(UtilsError::InputTooLarge(767))));
371        let res: Result<[u8; 768], UtilsError> = bigint_to_le_bytes_array(&b768);
372        assert!(res.is_ok());
373
374        let b1024 = BigUint::from_bytes_be(&[1; 1024]);
375        let res: Result<[u8; 1], UtilsError> = bigint_to_be_bytes_array(&b1024);
376        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
377        let res: Result<[u8; 1023], UtilsError> = bigint_to_be_bytes_array(&b1024);
378        assert!(matches!(res, Err(UtilsError::InputTooLarge(1023))));
379        let res: Result<[u8; 1024], UtilsError> = bigint_to_be_bytes_array(&b1024);
380        assert!(res.is_ok());
381
382        let b1024 = BigUint::from_bytes_le(&[1; 1024]);
383        let res: Result<[u8; 1], UtilsError> = bigint_to_le_bytes_array(&b1024);
384        assert!(matches!(res, Err(UtilsError::InputTooLarge(1))));
385        let res: Result<[u8; 1023], UtilsError> = bigint_to_le_bytes_array(&b1024);
386        assert!(matches!(res, Err(UtilsError::InputTooLarge(1023))));
387        let res: Result<[u8; 1024], UtilsError> = bigint_to_le_bytes_array(&b1024);
388        assert!(res.is_ok());
389    }
390}