1use ark_ec::pairing::Pairing;
6use ark_serialize::CanonicalDeserialize;
7use ark_std::{collections::BTreeMap, format, io::Read, marker::PhantomData, vec, vec::Vec};
8use std::io::{Seek, SeekFrom};
9
10use crate::circom::{
11 error::CircomError,
12 r1cs::{Constraint, Header, R1CSFile, LC},
13 witness::check_subgroup_order,
14};
15
16impl<E: Pairing> R1CSFile<E> {
17 pub fn new_from_file(path: impl AsRef<std::path::Path>) -> Result<Self, CircomError> {
18 let reader = std::fs::File::open(path).map_err(|err| {
19 log::error!("Encountered error while opening R1CS file: {:?}", err);
20 CircomError::UnableToOpenR1CSFile(format!(
21 "Encountered error while opening R1CS file: {:?}",
22 err
23 ))
24 })?;
25 Self::new(reader)
26 }
27
28 pub fn new<R: Read + Seek>(mut reader: R) -> Result<Self, CircomError> {
34 let mut magic = [0u8; 4];
35 read_exact(&mut reader, &mut magic)?;
36 if magic != [0x72, 0x31, 0x63, 0x73] {
37 return Err(CircomError::R1CSFileParsing(
39 "Invalid magic number".to_string(),
40 ));
41 }
42
43 let version = read_u32(&mut reader)?;
44 if version != 1 {
45 return Err(CircomError::R1CSFileParsing(
46 "Unsupported version".to_string(),
47 ));
48 }
49
50 let num_sections = read_u32(&mut reader)?;
51
52 let mut sec_offsets = BTreeMap::<u32, u64>::new();
55 let mut sec_sizes = BTreeMap::<u32, u64>::new();
56
57 for _ in 0..num_sections {
59 let sec_type = read_u32(&mut reader)?;
60 let sec_size = read_u64(&mut reader)?;
61 let offset = seek(&mut reader, SeekFrom::Current(0))?;
62 sec_offsets.insert(sec_type, offset);
63 sec_sizes.insert(sec_type, sec_size);
64 seek(&mut reader, SeekFrom::Current(sec_size as i64))?;
65 }
66
67 let header_type = 1;
68 let constraint_type = 2;
69 let wire2label_type = 3;
70
71 let header_offset = sec_offsets.get(&header_type).ok_or_else(|| {
72 CircomError::R1CSFileParsing("No section offset for header type found".to_string())
73 })?;
74
75 seek(&mut reader, SeekFrom::Start(*header_offset))?;
76
77 let header_size = sec_sizes.get(&header_type).ok_or_else(|| {
78 CircomError::R1CSFileParsing("No section size for header type found".to_string())
79 })?;
80
81 let header = Header::new(&mut reader, *header_size)?;
82
83 let constraint_offset = sec_offsets.get(&constraint_type).ok_or_else(|| {
84 CircomError::R1CSFileParsing("No section offset for constraint type found".to_string())
85 })?;
86
87 seek(&mut reader, SeekFrom::Start(*constraint_offset))?;
88
89 let constraints = read_constraints::<&mut R, E>(&mut reader, &header)?;
90
91 let wire2label_offset = sec_offsets.get(&wire2label_type).ok_or_else(|| {
92 CircomError::R1CSFileParsing("No section offset for wire2label type found".to_string())
93 })?;
94
95 seek(&mut reader, SeekFrom::Start(*wire2label_offset))?;
96
97 let wire2label_size = sec_sizes.get(&wire2label_type).ok_or_else(|| {
98 CircomError::R1CSFileParsing("No section size for wire2label type found".to_string())
99 })?;
100
101 let wire_mapping = read_map(&mut reader, *wire2label_size, &header)?;
102
103 Ok(R1CSFile {
104 version,
105 header,
106 constraints,
107 wire_mapping,
108 })
109 }
110}
111
112impl<E: Pairing> Header<E> {
113 fn new<R: Read>(mut reader: R, size: u64) -> Result<Header<E>, CircomError> {
114 let field_size = read_u32(&mut reader)?;
115 if field_size != 32 {
116 return Err(CircomError::R1CSFileParsing(
117 "This parser only supports 32-byte fields".to_string(),
118 ));
119 }
120
121 if size != 32 + field_size as u64 {
122 return Err(CircomError::R1CSFileParsing(
123 "Invalid header section size".to_string(),
124 ));
125 }
126
127 let mut subgroup_order_bytes = vec![0u8; field_size as usize];
129 read_exact(&mut reader, &mut subgroup_order_bytes)?;
130 let curve = check_subgroup_order::<E>(&subgroup_order_bytes)?;
131
132 Ok(Header {
133 field_size,
134 subgroup_order: subgroup_order_bytes,
135 curve,
136 n_wires: read_u32(&mut reader)?,
137 n_pub_out: read_u32(&mut reader)?,
138 n_pub_in: read_u32(&mut reader)?,
139 n_prv_in: read_u32(&mut reader)?,
140 n_labels: read_u64(&mut reader)?,
141 n_constraints: read_u32(&mut reader)?,
142 phantom: PhantomData,
143 })
144 }
145}
146
147fn read_u32<R: Read>(reader: R) -> Result<u32, CircomError> {
148 let mut buf = [0; 4];
149 read_exact(reader, &mut buf)?;
150 Ok(u32::from_le_bytes(buf))
151}
152
153fn read_u64<R: Read>(reader: R) -> Result<u64, CircomError> {
154 let mut buf = [0; 8];
155 read_exact(reader, &mut buf)?;
156 Ok(u64::from_le_bytes(buf))
157}
158
159fn read_exact<R: Read>(mut reader: R, buf: &mut [u8]) -> Result<(), CircomError> {
160 reader.read_exact(buf).map_err(|err| {
161 log::error!("Encountered error while parsing R1CS file: {:?}", err);
162 CircomError::R1CSFileParsing(format!(
163 "Encountered error while parsing R1CS file: {:?}",
164 err
165 ))
166 })
167}
168
169fn seek<R: Read + Seek>(mut reader: R, pos: SeekFrom) -> Result<u64, CircomError> {
170 reader.seek(pos).map_err(|err| {
171 log::error!("Encountered error while parsing R1CS file: {:?}", err);
172 CircomError::R1CSFileParsing(format!(
173 "Encountered error while parsing R1CS file: {:?}",
174 err
175 ))
176 })
177}
178
179fn read_lc<R: Read, E: Pairing>(mut reader: R) -> Result<LC<E>, CircomError> {
181 let num_terms = read_u32(&mut reader)? as usize;
182 let mut terms = Vec::with_capacity(num_terms);
183 for _ in 0..num_terms {
184 terms.push((
185 read_u32(&mut reader)? as usize, E::ScalarField::deserialize_uncompressed(&mut reader) .map_err(|err| {
188 log::error!("Encountered error while parsing R1CS file: {:?}", err);
189 CircomError::R1CSFileParsing(format!(
190 "Encountered error while parsing R1CS file: {:?}",
191 err
192 ))
193 })?,
194 ));
195 }
196 Ok(LC(terms))
197}
198
199fn read_constraints<R: Read, E: Pairing>(
201 mut reader: R,
202 header: &Header<E>,
203) -> Result<Vec<Constraint<E>>, CircomError> {
204 let mut vec = Vec::with_capacity(header.n_constraints as usize);
206 for _ in 0..header.n_constraints {
207 vec.push({
208 let a = read_lc::<&mut R, E>(&mut reader)?;
209 let b = read_lc::<&mut R, E>(&mut reader)?;
210 let c = read_lc::<&mut R, E>(&mut reader)?;
211 Constraint { a, b, c }
212 });
213 }
214 Ok(vec)
215}
216
217fn read_map<R: Read, E: Pairing>(
220 mut reader: R,
221 size: u64,
222 header: &Header<E>,
223) -> Result<Vec<u64>, CircomError> {
224 if size != header.n_wires as u64 * 8 {
225 return Err(CircomError::R1CSFileParsing(
226 "Invalid map section size".to_string(),
227 ));
228 }
229 let mut vec = Vec::with_capacity(header.n_wires as usize);
230 for _ in 0..header.n_wires {
231 vec.push(read_u64(&mut reader)?);
232 }
233 if vec[0] != 0 {
234 return Err(CircomError::R1CSFileParsing(
235 "Wire 0 should always be mapped to 0".to_string(),
236 ));
237 }
238 Ok(vec)
239}
240
241#[cfg(test)]
242mod tests {
243 use super::*;
244 use crate::circom::{r1cs::Curve, tests::abs_path};
245 use ark_bls12_381::Bls12_381;
246 use ark_bn254::{Bn254, Fr as BnFr};
247 use ark_std::io::{BufReader, Cursor};
248 use num_bigint::BigUint;
249 use std::str::FromStr;
250
251 fn basic_checks<E: Pairing>(file: &R1CSFile<E>, curve_type: Curve) {
253 assert_eq!(file.version, 1);
254 assert_eq!(file.header.field_size, 32);
255 assert_eq!(file.header.curve, curve_type);
256
257 if curve_type == Curve::Bn128 {
258 assert_eq!(
259 file.header.subgroup_order,
260 BigUint::from_str(
261 "21888242871839275222246405745257275088548364400416034343698204186575808495617"
262 )
263 .unwrap()
264 .to_bytes_le(),
265 );
266 }
267
268 if curve_type == Curve::Bls12_381 {
269 assert_eq!(
270 file.header.subgroup_order,
271 BigUint::from_str(
272 "52435875175126190479447740508185965837690552500527637822603658699938581184513"
273 )
274 .unwrap()
275 .to_bytes_le(),
276 );
277 }
278
279 assert!(file.header.n_labels >= file.header.n_wires as u64);
280 assert_eq!(file.wire_mapping.len() as u32, file.header.n_wires);
281 }
282
283 #[test]
284 fn bn_254() {
285 let data = hex_literal::hex!(
286 "
287 72316373
288 01000000
289 03000000
290 01000000 40000000 00000000
291 20000000
292 010000f0 93f5e143 9170b979 48e83328 5d588181 b64550b8 29a031e1 724e6430
293 07000000
294 01000000
295 02000000
296 03000000
297 e8030000 00000000
298 03000000
299 02000000 88020000 00000000
300 02000000
301 05000000 03000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
302 06000000 08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
303 03000000
304 00000000 02000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
305 02000000 14000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
306 03000000 0C000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
307 02000000
308 00000000 05000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
309 02000000 07000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
310 03000000
311 01000000 04000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
312 04000000 08000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
313 05000000 03000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
314 02000000
315 03000000 2C000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
316 06000000 06000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
317 00000000
318 01000000
319 06000000 04000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
320 03000000
321 00000000 06000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
322 02000000 0B000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
323 03000000 05000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
324 01000000
325 06000000 58020000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
326 03000000 38000000 00000000
327 00000000 00000000
328 03000000 00000000
329 0a000000 00000000
330 0b000000 00000000
331 0c000000 00000000
332 0f000000 00000000
333 44010000 00000000
334 "
335 );
336
337 let reader = BufReader::new(Cursor::new(&data[..]));
338 let file = R1CSFile::<Bn254>::new(reader).unwrap();
339 basic_checks(&file, Curve::Bn128);
340 assert_eq!(file.header.n_wires, 7);
341 assert_eq!(file.header.n_pub_out, 1);
342 assert_eq!(file.header.n_pub_in, 2);
343 assert_eq!(file.header.n_prv_in, 3);
344 assert_eq!(file.header.n_labels, 0x03e8);
345 assert_eq!(file.header.n_constraints, 3);
346
347 assert_eq!(file.constraints.len(), 3);
348 assert_eq!(file.constraints[0].a.len(), 2);
349 assert_eq!(file.constraints[0].a.0[0].0, 5);
350 assert_eq!(file.constraints[0].a.0[0].1, BnFr::from(3));
351 assert_eq!(file.constraints[2].b.0[0].0, 0);
352 assert_eq!(file.constraints[2].b.0[0].1, BnFr::from(6));
353 assert_eq!(file.constraints[1].c.len(), 0);
354
355 assert_eq!(file.wire_mapping.len(), 7);
356 assert_eq!(file.wire_mapping[1], 3);
357 }
358
359 #[test]
360 fn input_validation() {
361 assert_eq!(
362 R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bls12-381/multiply2.r1cs"))
363 .unwrap_err(),
364 CircomError::IncompatibleWithCurve
365 );
366 assert_eq!(
367 R1CSFile::<Bls12_381>::new_from_file(abs_path("test-vectors/bn128/multiply2.r1cs"))
368 .unwrap_err(),
369 CircomError::IncompatibleWithCurve
370 );
371
372 assert_eq!(
374 R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/multiply2_goldilocks.r1cs"))
375 .unwrap_err(),
376 CircomError::R1CSFileParsing("This parser only supports 32-byte fields".to_string())
377 );
378 assert_eq!(
379 R1CSFile::<Bls12_381>::new_from_file(abs_path(
380 "test-vectors/multiply2_goldilocks.r1cs"
381 ))
382 .unwrap_err(),
383 CircomError::R1CSFileParsing("This parser only supports 32-byte fields".to_string())
384 );
385 }
386
387 #[test]
388 fn multiply2() {
389 fn check<E: Pairing>(file: &R1CSFile<E>, curve_type: Curve) {
390 basic_checks(&file, curve_type);
391 assert_eq!(file.header.n_wires, 4);
393 assert_eq!(file.header.n_labels, 4);
394 assert_eq!(file.header.n_pub_out, 1);
395 assert_eq!(file.header.n_pub_in, 0);
396 assert_eq!(file.header.n_prv_in, 2);
397 assert_eq!(file.header.n_constraints, 1);
398
399 assert_eq!(file.constraints.len(), 1);
400 assert_eq!(file.constraints[0].a.len(), 1);
401 assert_eq!(file.constraints[0].b.len(), 1);
402 assert_eq!(file.constraints[0].c.len(), 1);
403
404 assert_eq!(file.wire_mapping, vec![0, 1, 2, 3]);
405 }
406 check(
407 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/multiply2.r1cs"))
408 .unwrap(),
409 Curve::Bn128,
410 );
411 check(
412 &R1CSFile::<Bls12_381>::new_from_file(abs_path(
413 "test-vectors/bls12-381/multiply2.r1cs",
414 ))
415 .unwrap(),
416 Curve::Bls12_381,
417 );
418 }
419
420 #[test]
421 fn test_1() {
422 fn check<E: Pairing>(file: &R1CSFile<E>, curve_type: Curve) {
423 basic_checks(&file, curve_type);
424 assert_eq!(file.header.n_wires, 4);
425 assert_eq!(file.header.n_labels, 5);
426 assert_eq!(file.header.n_pub_out, 1);
427 assert_eq!(file.header.n_pub_in, 0);
428 assert_eq!(file.header.n_prv_in, 1);
429 assert_eq!(file.header.n_constraints, 2);
430
431 assert_eq!(file.constraints.len(), 2);
432 assert_eq!(file.constraints[0].a.len(), 1);
433 assert_eq!(file.constraints[0].b.len(), 1);
434 assert_eq!(file.constraints[0].c.len(), 1);
435 assert_eq!(file.constraints[1].a.len(), 1);
436 assert_eq!(file.constraints[1].b.len(), 1);
437 assert_eq!(file.constraints[1].c.len(), 3);
438
439 assert_eq!(file.wire_mapping, vec![0, 1, 2, 3]);
440 }
441
442 check(
443 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/test1.r1cs")).unwrap(),
444 Curve::Bn128,
445 );
446 check(
447 &R1CSFile::<Bls12_381>::new_from_file(abs_path("test-vectors/bls12-381/test1.r1cs"))
448 .unwrap(),
449 Curve::Bls12_381,
450 );
451 }
452
453 #[test]
454 fn test_2() {
455 fn check<E: Pairing>(file: &R1CSFile<E>, curve_type: Curve) {
456 basic_checks(&file, curve_type);
457 assert_eq!(file.header.n_wires, 6);
458 assert_eq!(file.header.n_labels, 7);
459 assert_eq!(file.header.n_pub_out, 1);
460 assert_eq!(file.header.n_pub_in, 0);
461 assert_eq!(file.header.n_prv_in, 2);
462 assert_eq!(file.header.n_constraints, 3);
463
464 assert_eq!(file.constraints.len(), 3);
465 assert_eq!(file.constraints[0].a.len(), 1);
466 assert_eq!(file.constraints[0].b.len(), 1);
467 assert_eq!(file.constraints[0].c.len(), 1);
468 assert_eq!(file.constraints[1].a.len(), 1);
469 assert_eq!(file.constraints[1].b.len(), 1);
470 assert_eq!(file.constraints[1].c.len(), 1);
471 assert_eq!(file.constraints[2].a.len(), 1);
472 assert_eq!(file.constraints[2].b.len(), 1);
473 assert_eq!(file.constraints[2].c.len(), 5);
474
475 assert_eq!(file.wire_mapping, vec![0, 1, 2, 3, 4, 5]);
476 }
477
478 check(
479 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/test2.r1cs")).unwrap(),
480 Curve::Bn128,
481 );
482 check(
483 &R1CSFile::<Bls12_381>::new_from_file(abs_path("test-vectors/bls12-381/test2.r1cs"))
484 .unwrap(),
485 Curve::Bls12_381,
486 );
487 }
488
489 #[test]
490 fn test_3() {
491 fn check<E: Pairing>(file: &R1CSFile<E>, curve_type: Curve) {
492 basic_checks(&file, curve_type);
493 assert_eq!(file.header.n_wires, 12);
494 assert_eq!(file.header.n_labels, 14);
495 assert_eq!(file.header.n_pub_out, 2);
496 assert_eq!(file.header.n_pub_in, 2);
497 assert_eq!(file.header.n_prv_in, 4);
498 assert_eq!(file.header.n_constraints, 5);
499
500 assert_eq!(file.constraints.len(), 5);
501 assert_eq!(file.constraints[0].a.len(), 1);
502 assert_eq!(file.constraints[0].b.len(), 1);
503 assert_eq!(file.constraints[0].c.len(), 1);
504 assert_eq!(file.constraints[1].a.len(), 1);
505 assert_eq!(file.constraints[1].b.len(), 1);
506 assert_eq!(file.constraints[1].c.len(), 1);
507 assert_eq!(file.constraints[2].a.len(), 1);
508 assert_eq!(file.constraints[2].b.len(), 1);
509 assert_eq!(file.constraints[2].c.len(), 3);
510 assert_eq!(file.constraints[3].a.len(), 1);
511 assert_eq!(file.constraints[3].b.len(), 1);
512 assert_eq!(file.constraints[3].c.len(), 1);
513 assert_eq!(file.constraints[4].a.len(), 1);
514 assert_eq!(file.constraints[4].b.len(), 1);
515 assert_eq!(file.constraints[4].c.len(), 2);
516 }
517
518 check(
519 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/test3.r1cs")).unwrap(),
520 Curve::Bn128,
521 );
522 check(
523 &R1CSFile::<Bls12_381>::new_from_file(abs_path("test-vectors/bls12-381/test3.r1cs"))
524 .unwrap(),
525 Curve::Bls12_381,
526 );
527 }
528
529 #[test]
530 fn test_4() {
531 fn check<E: Pairing>(file: &R1CSFile<E>, curve_type: Curve) {
532 basic_checks(&file, curve_type);
533 assert_eq!(file.header.n_wires, 40);
534 assert_eq!(file.header.n_labels, 42);
535 assert_eq!(file.header.n_pub_out, 2);
536 assert_eq!(file.header.n_pub_in, 4);
537 assert_eq!(file.header.n_prv_in, 4);
538 assert_eq!(file.header.n_constraints, 31);
539 }
540
541 check(
542 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/test4.r1cs")).unwrap(),
543 Curve::Bn128,
544 );
545 check(
546 &R1CSFile::<Bls12_381>::new_from_file(abs_path("test-vectors/bls12-381/test4.r1cs"))
547 .unwrap(),
548 Curve::Bls12_381,
549 );
550 }
551
552 #[test]
553 fn multiply_n() {
554 fn check<E: Pairing>(file: &R1CSFile<E>, curve_type: Curve) {
555 basic_checks(&file, curve_type);
556 assert_eq!(file.header.n_wires, 600);
557 assert_eq!(file.header.n_labels, 602);
558 assert_eq!(file.header.n_pub_out, 1);
559 assert_eq!(file.header.n_pub_in, 0);
560 assert_eq!(file.header.n_prv_in, 300);
561 assert_eq!(file.header.n_constraints, 299);
562
563 assert_eq!(file.constraints.len(), 299);
564 for i in 0..299 {
565 assert_eq!(file.constraints[i].a.len(), 1);
566 assert_eq!(file.constraints[i].b.len(), 1);
567 assert_eq!(file.constraints[i].c.len(), 1);
568 }
569
570 for i in 0..=301 {
571 assert_eq!(file.wire_mapping[i], i as u64);
572 }
573 for i in 302..=599 {
574 assert_eq!(file.wire_mapping[i], i as u64 + 1);
575 }
576 }
577
578 check(
579 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/multiply_n.r1cs"))
580 .unwrap(),
581 Curve::Bn128,
582 );
583 check(
584 &R1CSFile::<Bls12_381>::new_from_file(abs_path(
585 "test-vectors/bls12-381/multiply_n.r1cs",
586 ))
587 .unwrap(),
588 Curve::Bls12_381,
589 );
590 }
591
592 #[test]
593 fn nconstraints() {
594 fn check<E: Pairing>(file: &R1CSFile<E>, curve_type: Curve) {
595 basic_checks(&file, curve_type);
596 assert_eq!(file.header.n_pub_out, 1);
597 assert_eq!(file.header.n_pub_in, 0);
598 assert_eq!(file.header.n_prv_in, 1);
599 assert_eq!(file.header.n_constraints, 2499);
600
601 assert_eq!(file.constraints.len(), 2499);
602 for i in 0..2499 {
603 assert_eq!(file.constraints[i].a.len(), 1);
604 assert_eq!(file.constraints[i].b.len(), 1);
605 assert_eq!(file.constraints[i].c.len(), 2);
606 }
607 }
608 check(
609 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/nconstraints.r1cs"))
610 .unwrap(),
611 Curve::Bn128,
612 );
613 check(
614 &R1CSFile::<Bls12_381>::new_from_file(abs_path(
615 "test-vectors/bls12-381/nconstraints.r1cs",
616 ))
617 .unwrap(),
618 Curve::Bls12_381,
619 );
620 }
621
622 #[test]
623 fn multiply2_bounded() {
624 basic_checks(
625 &R1CSFile::<Bn254>::new_from_file(abs_path(
626 "test-vectors/bn128/multiply2_bounded.r1cs",
627 ))
628 .unwrap(),
629 Curve::Bn128,
630 );
631 basic_checks(
632 &R1CSFile::<Bls12_381>::new_from_file(abs_path(
633 "test-vectors/bls12-381/multiply2_bounded.r1cs",
634 ))
635 .unwrap(),
636 Curve::Bls12_381,
637 );
638 }
639
640 #[test]
641 fn mimc() {
642 basic_checks(
643 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/mimc_bn128.r1cs"))
644 .unwrap(),
645 Curve::Bn128,
646 );
647 basic_checks(
648 &R1CSFile::<Bls12_381>::new_from_file(abs_path(
649 "test-vectors/bls12-381/mimc_bls12_381.r1cs",
650 ))
651 .unwrap(),
652 Curve::Bls12_381,
653 );
654 }
655
656 #[test]
657 fn mimcsponge() {
658 basic_checks(
659 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/mimcsponge_bn128.r1cs"))
660 .unwrap(),
661 Curve::Bn128,
662 );
663 basic_checks(
664 &R1CSFile::<Bls12_381>::new_from_file(abs_path(
665 "test-vectors/bls12-381/mimcsponge_bls12_381.r1cs",
666 ))
667 .unwrap(),
668 Curve::Bls12_381,
669 );
670 }
671
672 #[test]
673 fn poseidon() {
674 basic_checks(
675 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/poseidon_bn128.r1cs"))
676 .unwrap(),
677 Curve::Bn128,
678 );
679 }
680
681 #[test]
682 fn less_than_32_bits() {
683 basic_checks(
684 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/less_than_32.r1cs"))
685 .unwrap(),
686 Curve::Bn128,
687 );
688 basic_checks(
689 &R1CSFile::<Bls12_381>::new_from_file(abs_path(
690 "test-vectors/bls12-381/less_than_32.r1cs",
691 ))
692 .unwrap(),
693 Curve::Bls12_381,
694 );
695 }
696
697 #[test]
698 fn less_than_public_64_bits() {
699 basic_checks(
700 &R1CSFile::<Bn254>::new_from_file(abs_path(
701 "test-vectors/bn128/less_than_public_64.r1cs",
702 ))
703 .unwrap(),
704 Curve::Bn128,
705 );
706 basic_checks(
707 &R1CSFile::<Bls12_381>::new_from_file(abs_path(
708 "test-vectors/bls12-381/less_than_public_64.r1cs",
709 ))
710 .unwrap(),
711 Curve::Bls12_381,
712 );
713 }
714
715 #[test]
716 fn all_different_10() {
717 basic_checks(
718 &R1CSFile::<Bn254>::new_from_file(abs_path("test-vectors/bn128/all_different_10.r1cs"))
719 .unwrap(),
720 Curve::Bn128,
721 );
722 basic_checks(
723 &R1CSFile::<Bls12_381>::new_from_file(abs_path(
724 "test-vectors/bls12-381/all_different_10.r1cs",
725 ))
726 .unwrap(),
727 Curve::Bls12_381,
728 );
729 }
730}