You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

772 lines
22 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
2 years ago
  1. #![allow(non_snake_case)]
  2. #![doc = include_str!("../README.md")]
  3. #![deny(missing_docs)]
  4. #![feature(test)]
  5. #![allow(clippy::assertions_on_result_states)]
  6. extern crate ark_std;
  7. extern crate byteorder;
  8. extern crate core;
  9. extern crate digest;
  10. extern crate lazy_static;
  11. extern crate merlin;
  12. extern crate rand;
  13. extern crate sha3;
  14. extern crate test;
  15. #[macro_use]
  16. extern crate json;
  17. #[cfg(feature = "multicore")]
  18. extern crate rayon;
  19. mod commitments;
  20. mod dense_mlpoly;
  21. mod errors;
  22. mod group;
  23. mod math;
  24. mod nizk;
  25. mod parameters;
  26. mod product_tree;
  27. mod r1csinstance;
  28. mod r1csproof;
  29. mod random;
  30. mod scalar;
  31. mod sparse_mlpoly;
  32. mod sumcheck;
  33. mod timer;
  34. mod transcript;
  35. mod unipoly;
  36. use ark_ff::{BigInteger, Field, PrimeField};
  37. use ark_serialize::*;
  38. use ark_std::{One, UniformRand, Zero};
  39. use core::cmp::max;
  40. use errors::{ProofVerifyError, R1CSError};
  41. use merlin::Transcript;
  42. use r1csinstance::{
  43. R1CSCommitment, R1CSCommitmentGens, R1CSDecommitment, R1CSEvalProof, R1CSInstance,
  44. };
  45. use r1csproof::{R1CSGens, R1CSProof};
  46. use random::RandomTape;
  47. use scalar::Scalar;
  48. use std::borrow::Borrow;
  49. use timer::Timer;
  50. use transcript::{AppendToTranscript, ProofTranscript};
  51. /// `ComputationCommitment` holds a public preprocessed NP statement (e.g., R1CS)
  52. pub struct ComputationCommitment {
  53. comm: R1CSCommitment,
  54. }
  55. /// `ComputationDecommitment` holds information to decommit `ComputationCommitment`
  56. pub struct ComputationDecommitment {
  57. decomm: R1CSDecommitment,
  58. }
  59. /// `Assignment` holds an assignment of values to either the inputs or variables in an `Instance`
  60. #[derive(Clone)]
  61. pub struct Assignment {
  62. assignment: Vec<Scalar>,
  63. }
  64. impl Assignment {
  65. /// Constructs a new `Assignment` from a vector
  66. pub fn new(assignment: &Vec<Vec<u8>>) -> Result<Assignment, R1CSError> {
  67. let bytes_to_scalar = |vec: &Vec<Vec<u8>>| -> Result<Vec<Scalar>, R1CSError> {
  68. let mut vec_scalar: Vec<Scalar> = Vec::new();
  69. for v in vec {
  70. let val = Scalar::from_random_bytes(v.as_slice());
  71. if val.is_some() == true {
  72. vec_scalar.push(val.unwrap());
  73. } else {
  74. return Err(R1CSError::InvalidScalar);
  75. }
  76. }
  77. Ok(vec_scalar)
  78. };
  79. let assignment_scalar = bytes_to_scalar(assignment);
  80. // check for any parsing errors
  81. if assignment_scalar.is_err() {
  82. return Err(R1CSError::InvalidScalar);
  83. }
  84. Ok(Assignment {
  85. assignment: assignment_scalar.unwrap(),
  86. })
  87. }
  88. /// pads Assignment to the specified length
  89. fn pad(&self, len: usize) -> VarsAssignment {
  90. // check that the new length is higher than current length
  91. assert!(len > self.assignment.len());
  92. let padded_assignment = {
  93. let mut padded_assignment = self.assignment.clone();
  94. padded_assignment.extend(vec![Scalar::zero(); len - self.assignment.len()]);
  95. padded_assignment
  96. };
  97. VarsAssignment {
  98. assignment: padded_assignment,
  99. }
  100. }
  101. }
  102. /// `VarsAssignment` holds an assignment of values to variables in an `Instance`
  103. pub type VarsAssignment = Assignment;
  104. /// `InputsAssignment` holds an assignment of values to variables in an `Instance`
  105. pub type InputsAssignment = Assignment;
  106. /// `Instance` holds the description of R1CS matrices and a hash of the matrices
  107. #[derive(Debug)]
  108. pub struct Instance {
  109. inst: R1CSInstance,
  110. digest: Vec<u8>,
  111. }
  112. impl Instance {
  113. /// Constructs a new `Instance` and an associated satisfying assignment
  114. pub fn new(
  115. num_cons: usize,
  116. num_vars: usize,
  117. num_inputs: usize,
  118. A: &[(usize, usize, Vec<u8>)],
  119. B: &[(usize, usize, Vec<u8>)],
  120. C: &[(usize, usize, Vec<u8>)],
  121. ) -> Result<Instance, R1CSError> {
  122. let (num_vars_padded, num_cons_padded) = {
  123. let num_vars_padded = {
  124. let mut num_vars_padded = num_vars;
  125. // ensure that num_inputs + 1 <= num_vars
  126. num_vars_padded = max(num_vars_padded, num_inputs + 1);
  127. // ensure that num_vars_padded a power of two
  128. if num_vars_padded.next_power_of_two() != num_vars_padded {
  129. num_vars_padded = num_vars_padded.next_power_of_two();
  130. }
  131. num_vars_padded
  132. };
  133. let num_cons_padded = {
  134. let mut num_cons_padded = num_cons;
  135. // ensure that num_cons_padded is at least 2
  136. if num_cons_padded == 0 || num_cons_padded == 1 {
  137. num_cons_padded = 2;
  138. }
  139. // ensure that num_cons_padded is power of 2
  140. if num_cons.next_power_of_two() != num_cons {
  141. num_cons_padded = num_cons.next_power_of_two();
  142. }
  143. num_cons_padded
  144. };
  145. (num_vars_padded, num_cons_padded)
  146. };
  147. let bytes_to_scalar =
  148. |tups: &[(usize, usize, Vec<u8>)]| -> Result<Vec<(usize, usize, Scalar)>, R1CSError> {
  149. let mut mat: Vec<(usize, usize, Scalar)> = Vec::new();
  150. for (row, col, val_bytes) in tups {
  151. // row must be smaller than num_cons
  152. if *row >= num_cons {
  153. return Err(R1CSError::InvalidIndex);
  154. }
  155. // col must be smaller than num_vars + 1 + num_inputs
  156. if *col >= num_vars + 1 + num_inputs {
  157. return Err(R1CSError::InvalidIndex);
  158. }
  159. let val = Scalar::from_random_bytes(&val_bytes.as_slice());
  160. if val.is_some() == true {
  161. // if col >= num_vars, it means that it is referencing a 1 or input in the satisfying
  162. // assignment
  163. if *col >= num_vars {
  164. mat.push((*row, *col + num_vars_padded - num_vars, val.unwrap()));
  165. } else {
  166. mat.push((*row, *col, val.unwrap()));
  167. }
  168. } else {
  169. return Err(R1CSError::InvalidScalar);
  170. }
  171. }
  172. // pad with additional constraints up until num_cons_padded if the original constraints were 0 or 1
  173. // we do not need to pad otherwise because the dummy constraints are implicit in the sum-check protocol
  174. if num_cons == 0 || num_cons == 1 {
  175. for i in tups.len()..num_cons_padded {
  176. mat.push((i, num_vars, Scalar::zero()));
  177. }
  178. }
  179. Ok(mat)
  180. };
  181. let A_scalar = bytes_to_scalar(A);
  182. if A_scalar.is_err() {
  183. return Err(A_scalar.err().unwrap());
  184. }
  185. let B_scalar = bytes_to_scalar(B);
  186. if B_scalar.is_err() {
  187. return Err(B_scalar.err().unwrap());
  188. }
  189. let C_scalar = bytes_to_scalar(C);
  190. if C_scalar.is_err() {
  191. return Err(C_scalar.err().unwrap());
  192. }
  193. let inst = R1CSInstance::new(
  194. num_cons_padded,
  195. num_vars_padded,
  196. num_inputs,
  197. &A_scalar.unwrap(),
  198. &B_scalar.unwrap(),
  199. &C_scalar.unwrap(),
  200. );
  201. let digest = inst.get_digest();
  202. Ok(Instance { inst, digest })
  203. }
  204. /// Checks if a given R1CSInstance is satisfiable with a given variables and inputs assignments
  205. pub fn is_sat(
  206. &self,
  207. vars: &VarsAssignment,
  208. inputs: &InputsAssignment,
  209. ) -> Result<bool, R1CSError> {
  210. if vars.assignment.len() > self.inst.get_num_vars() {
  211. return Err(R1CSError::InvalidNumberOfInputs);
  212. }
  213. if inputs.assignment.len() != self.inst.get_num_inputs() {
  214. return Err(R1CSError::InvalidNumberOfInputs);
  215. }
  216. // we might need to pad variables
  217. let padded_vars = {
  218. let num_padded_vars = self.inst.get_num_vars();
  219. let num_vars = vars.assignment.len();
  220. if num_padded_vars > num_vars {
  221. vars.pad(num_padded_vars)
  222. } else {
  223. vars.clone()
  224. }
  225. };
  226. Ok(
  227. self
  228. .inst
  229. .is_sat(&padded_vars.assignment, &inputs.assignment),
  230. )
  231. }
  232. /// Constructs a new synthetic R1CS `Instance` and an associated satisfying assignment
  233. pub fn produce_synthetic_r1cs(
  234. num_cons: usize,
  235. num_vars: usize,
  236. num_inputs: usize,
  237. ) -> (Instance, VarsAssignment, InputsAssignment) {
  238. let (inst, vars, inputs) = R1CSInstance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
  239. let digest = inst.get_digest();
  240. (
  241. Instance { inst, digest },
  242. VarsAssignment { assignment: vars },
  243. InputsAssignment { assignment: inputs },
  244. )
  245. }
  246. }
  247. /// `SNARKGens` holds public parameters for producing and verifying proofs with the Spartan SNARK
  248. pub struct SNARKGens {
  249. gens_r1cs_sat: R1CSGens,
  250. gens_r1cs_eval: R1CSCommitmentGens,
  251. }
  252. impl SNARKGens {
  253. /// Constructs a new `SNARKGens` given the size of the R1CS statement
  254. /// `num_nz_entries` specifies the maximum number of non-zero entries in any of the three R1CS matrices
  255. pub fn new(num_cons: usize, num_vars: usize, num_inputs: usize, num_nz_entries: usize) -> Self {
  256. let num_vars_padded = {
  257. let mut num_vars_padded = max(num_vars, num_inputs + 1);
  258. if num_vars_padded != num_vars_padded.next_power_of_two() {
  259. num_vars_padded = num_vars_padded.next_power_of_two();
  260. }
  261. num_vars_padded
  262. };
  263. let gens_r1cs_sat = R1CSGens::new(b"gens_r1cs_sat", num_cons, num_vars_padded);
  264. let gens_r1cs_eval = R1CSCommitmentGens::new(
  265. b"gens_r1cs_eval",
  266. num_cons,
  267. num_vars_padded,
  268. num_inputs,
  269. num_nz_entries,
  270. );
  271. SNARKGens {
  272. gens_r1cs_sat,
  273. gens_r1cs_eval,
  274. }
  275. }
  276. }
  277. /// `SNARK` holds a proof produced by Spartan SNARK
  278. #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)]
  279. pub struct SNARK {
  280. r1cs_sat_proof: R1CSProof,
  281. inst_evals: (Scalar, Scalar, Scalar),
  282. r1cs_eval_proof: R1CSEvalProof,
  283. }
  284. impl SNARK {
  285. fn protocol_name() -> &'static [u8] {
  286. b"Spartan SNARK proof"
  287. }
  288. /// A public computation to create a commitment to an R1CS instance
  289. pub fn encode(
  290. inst: &Instance,
  291. gens: &SNARKGens,
  292. ) -> (ComputationCommitment, ComputationDecommitment) {
  293. let timer_encode = Timer::new("SNARK::encode");
  294. let (comm, decomm) = inst.inst.commit(&gens.gens_r1cs_eval);
  295. timer_encode.stop();
  296. (
  297. ComputationCommitment { comm },
  298. ComputationDecommitment { decomm },
  299. )
  300. }
  301. /// A method to produce a SNARK proof of the satisfiability of an R1CS instance
  302. pub fn prove(
  303. inst: &Instance,
  304. comm: &ComputationCommitment,
  305. decomm: &ComputationDecommitment,
  306. vars: VarsAssignment,
  307. inputs: &InputsAssignment,
  308. gens: &SNARKGens,
  309. transcript: &mut Transcript,
  310. ) -> Self {
  311. let timer_prove = Timer::new("SNARK::prove");
  312. // we create a Transcript object seeded with a random Scalar
  313. // to aid the prover produce its randomness
  314. let mut random_tape = RandomTape::new(b"proof");
  315. transcript.append_protocol_name(SNARK::protocol_name());
  316. comm.comm.append_to_transcript(b"comm", transcript);
  317. let (r1cs_sat_proof, rx, ry) = {
  318. let (proof, rx, ry) = {
  319. // we might need to pad variables
  320. let padded_vars = {
  321. let num_padded_vars = inst.inst.get_num_vars();
  322. let num_vars = vars.assignment.len();
  323. if num_padded_vars > num_vars {
  324. vars.pad(num_padded_vars)
  325. } else {
  326. vars
  327. }
  328. };
  329. R1CSProof::prove(
  330. &inst.inst,
  331. padded_vars.assignment,
  332. &inputs.assignment,
  333. &gens.gens_r1cs_sat,
  334. transcript,
  335. &mut random_tape,
  336. )
  337. };
  338. let mut proof_encoded: Vec<u8> = Vec::new();
  339. proof.serialize(&mut proof_encoded).unwrap();
  340. Timer::print(&format!("len_r1cs_sat_proof {:?}", proof_encoded.len()));
  341. (proof, rx, ry)
  342. };
  343. // We send evaluations of A, B, C at r = (rx, ry) as claims
  344. // to enable the verifier complete the first sum-check
  345. let timer_eval = Timer::new("eval_sparse_polys");
  346. let inst_evals = {
  347. let (Ar, Br, Cr) = inst.inst.evaluate(&rx, &ry);
  348. Ar.append_to_transcript(b"Ar_claim", transcript);
  349. Br.append_to_transcript(b"Br_claim", transcript);
  350. Cr.append_to_transcript(b"Cr_claim", transcript);
  351. (Ar, Br, Cr)
  352. };
  353. timer_eval.stop();
  354. let r1cs_eval_proof = {
  355. let proof = R1CSEvalProof::prove(
  356. &decomm.decomm,
  357. &rx,
  358. &ry,
  359. &inst_evals,
  360. &gens.gens_r1cs_eval,
  361. transcript,
  362. &mut random_tape,
  363. );
  364. let mut proof_encoded: Vec<u8> = Vec::new();
  365. proof.serialize(&mut proof_encoded).unwrap();
  366. Timer::print(&format!("len_r1cs_eval_proof {:?}", proof_encoded.len()));
  367. proof
  368. };
  369. timer_prove.stop();
  370. SNARK {
  371. r1cs_sat_proof,
  372. inst_evals,
  373. r1cs_eval_proof,
  374. }
  375. }
  376. /// A method to verify the SNARK proof of the satisfiability of an R1CS instance
  377. pub fn verify(
  378. &self,
  379. comm: &ComputationCommitment,
  380. input: &InputsAssignment,
  381. transcript: &mut Transcript,
  382. gens: &SNARKGens,
  383. ) -> Result<(), ProofVerifyError> {
  384. let timer_verify = Timer::new("SNARK::verify");
  385. transcript.append_protocol_name(SNARK::protocol_name());
  386. // append a commitment to the computation to the transcript
  387. comm.comm.append_to_transcript(b"comm", transcript);
  388. let timer_sat_proof = Timer::new("verify_sat_proof");
  389. assert_eq!(input.assignment.len(), comm.comm.get_num_inputs());
  390. let (rx, ry) = self.r1cs_sat_proof.verify(
  391. comm.comm.get_num_vars(),
  392. comm.comm.get_num_cons(),
  393. &input.assignment,
  394. &self.inst_evals,
  395. transcript,
  396. &gens.gens_r1cs_sat,
  397. )?;
  398. timer_sat_proof.stop();
  399. let timer_eval_proof = Timer::new("verify_eval_proof");
  400. let (Ar, Br, Cr) = &self.inst_evals;
  401. Ar.append_to_transcript(b"Ar_claim", transcript);
  402. Br.append_to_transcript(b"Br_claim", transcript);
  403. Cr.append_to_transcript(b"Cr_claim", transcript);
  404. self.r1cs_eval_proof.verify(
  405. &comm.comm,
  406. &rx,
  407. &ry,
  408. &self.inst_evals,
  409. &gens.gens_r1cs_eval,
  410. transcript,
  411. )?;
  412. timer_eval_proof.stop();
  413. timer_verify.stop();
  414. Ok(())
  415. }
  416. }
  417. /// `NIZKGens` holds public parameters for producing and verifying proofs with the Spartan NIZK
  418. pub struct NIZKGens {
  419. gens_r1cs_sat: R1CSGens,
  420. }
  421. impl NIZKGens {
  422. /// Constructs a new `NIZKGens` given the size of the R1CS statement
  423. pub fn new(num_cons: usize, num_vars: usize, num_inputs: usize) -> Self {
  424. let num_vars_padded = {
  425. let mut num_vars_padded = max(num_vars, num_inputs + 1);
  426. if num_vars_padded != num_vars_padded.next_power_of_two() {
  427. num_vars_padded = num_vars_padded.next_power_of_two();
  428. }
  429. num_vars_padded
  430. };
  431. let gens_r1cs_sat = R1CSGens::new(b"gens_r1cs_sat", num_cons, num_vars_padded);
  432. NIZKGens { gens_r1cs_sat }
  433. }
  434. }
  435. /// `NIZK` holds a proof produced by Spartan NIZK
  436. #[derive(CanonicalSerialize, CanonicalDeserialize, Debug)]
  437. pub struct NIZK {
  438. r1cs_sat_proof: R1CSProof,
  439. r: (Vec<Scalar>, Vec<Scalar>),
  440. }
  441. impl NIZK {
  442. fn protocol_name() -> &'static [u8] {
  443. b"Spartan NIZK proof"
  444. }
  445. /// A method to produce a NIZK proof of the satisfiability of an R1CS instance
  446. pub fn prove(
  447. inst: &Instance,
  448. vars: VarsAssignment,
  449. input: &InputsAssignment,
  450. gens: &NIZKGens,
  451. transcript: &mut Transcript,
  452. ) -> Self {
  453. let timer_prove = Timer::new("NIZK::prove");
  454. // we create a Transcript object seeded with a random Scalar
  455. // to aid the prover produce its randomness
  456. let mut random_tape = RandomTape::new(b"proof");
  457. transcript.append_protocol_name(NIZK::protocol_name());
  458. transcript.append_message(b"R1CSInstanceDigest", &inst.digest);
  459. let (r1cs_sat_proof, rx, ry) = {
  460. // we might need to pad variables
  461. let padded_vars = {
  462. let num_padded_vars = inst.inst.get_num_vars();
  463. let num_vars = vars.assignment.len();
  464. if num_padded_vars > num_vars {
  465. vars.pad(num_padded_vars)
  466. } else {
  467. vars
  468. }
  469. };
  470. let (proof, rx, ry) = R1CSProof::prove(
  471. &inst.inst,
  472. padded_vars.assignment,
  473. &input.assignment,
  474. &gens.gens_r1cs_sat,
  475. transcript,
  476. &mut random_tape,
  477. );
  478. let mut proof_encoded = Vec::new();
  479. proof.serialize(&mut proof_encoded).unwrap();
  480. Timer::print(&format!("len_r1cs_sat_proof {:?}", proof_encoded.len()));
  481. (proof, rx, ry)
  482. };
  483. timer_prove.stop();
  484. NIZK {
  485. r1cs_sat_proof,
  486. r: (rx, ry),
  487. }
  488. }
  489. /// A method to verify a NIZK proof of the satisfiability of an R1CS instance
  490. pub fn verify(
  491. &self,
  492. inst: &Instance,
  493. input: &InputsAssignment,
  494. transcript: &mut Transcript,
  495. gens: &NIZKGens,
  496. ) -> Result<(), ProofVerifyError> {
  497. let timer_verify = Timer::new("NIZK::verify");
  498. transcript.append_protocol_name(NIZK::protocol_name());
  499. transcript.append_message(b"R1CSInstanceDigest", &inst.digest);
  500. // We send evaluations of A, B, C at r = (rx, ry) as claims
  501. // to enable the verifier complete the first sum-check
  502. let timer_eval = Timer::new("eval_sparse_polys");
  503. let (claimed_rx, claimed_ry) = &self.r;
  504. let inst_evals = inst.inst.evaluate(claimed_rx, claimed_ry);
  505. timer_eval.stop();
  506. let timer_sat_proof = Timer::new("verify_sat_proof");
  507. assert_eq!(input.assignment.len(), inst.inst.get_num_inputs());
  508. let (rx, ry) = self.r1cs_sat_proof.verify(
  509. inst.inst.get_num_vars(),
  510. inst.inst.get_num_cons(),
  511. &input.assignment,
  512. &inst_evals,
  513. transcript,
  514. &gens.gens_r1cs_sat,
  515. )?;
  516. // verify if claimed rx and ry are correct
  517. assert_eq!(rx, *claimed_rx);
  518. assert_eq!(ry, *claimed_ry);
  519. timer_sat_proof.stop();
  520. timer_verify.stop();
  521. Ok(())
  522. }
  523. }
  524. #[cfg(test)]
  525. mod tests {
  526. use super::*;
  527. use ark_ff::PrimeField;
  528. #[test]
  529. pub fn check_snark() {
  530. let num_vars = 256;
  531. let num_cons = num_vars;
  532. let num_inputs = 10;
  533. // produce public generators
  534. let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_cons);
  535. // produce a synthetic R1CSInstance
  536. let (inst, vars, inputs) = Instance::produce_synthetic_r1cs(num_cons, num_vars, num_inputs);
  537. // create a commitment to R1CSInstance
  538. let (comm, decomm) = SNARK::encode(&inst, &gens);
  539. // produce a proof
  540. let mut prover_transcript = Transcript::new(b"example");
  541. let proof = SNARK::prove(
  542. &inst,
  543. &comm,
  544. &decomm,
  545. vars,
  546. &inputs,
  547. &gens,
  548. &mut prover_transcript,
  549. );
  550. // verify the proof
  551. let mut verifier_transcript = Transcript::new(b"example");
  552. assert!(proof
  553. .verify(&comm, &inputs, &mut verifier_transcript, &gens)
  554. .is_ok());
  555. }
  556. #[test]
  557. pub fn check_r1cs_invalid_index() {
  558. let num_cons = 4;
  559. let num_vars = 8;
  560. let num_inputs = 1;
  561. let zero: [u8; 32] = [
  562. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  563. 0,
  564. ];
  565. let A = vec![(0, 0, zero.to_vec())];
  566. let B = vec![(100, 1, zero.to_vec())];
  567. let C = vec![(1, 1, zero.to_vec())];
  568. let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C);
  569. assert!(inst.is_err());
  570. assert_eq!(inst.err(), Some(R1CSError::InvalidIndex));
  571. }
  572. #[test]
  573. pub fn check_r1cs_invalid_scalar() {
  574. let num_cons = 4;
  575. let num_vars = 8;
  576. let num_inputs = 1;
  577. let zero: [u8; 32] = [
  578. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  579. 0,
  580. ];
  581. let larger_than_mod = [
  582. 3, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8, 216,
  583. 57, 51, 72, 125, 157, 41, 83, 167, 237, 115,
  584. ];
  585. let A = vec![(0, 0, zero.to_vec())];
  586. let B = vec![(1, 1, larger_than_mod.to_vec())];
  587. let C = vec![(1, 1, zero.to_vec())];
  588. let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C);
  589. assert!(inst.is_err());
  590. assert_eq!(inst.err(), Some(R1CSError::InvalidScalar));
  591. }
  592. #[test]
  593. fn test_padded_constraints() {
  594. // parameters of the R1CS instance
  595. let num_cons = 1;
  596. let num_vars = 0;
  597. let num_inputs = 3;
  598. let num_non_zero_entries = 3;
  599. // We will encode the above constraints into three matrices, where
  600. // the coefficients in the matrix are in the little-endian byte order
  601. let mut A: Vec<(usize, usize, Vec<u8>)> = Vec::new();
  602. let mut B: Vec<(usize, usize, Vec<u8>)> = Vec::new();
  603. let mut C: Vec<(usize, usize, Vec<u8>)> = Vec::new();
  604. // Create a^2 + b + 13
  605. A.push((0, num_vars + 2, (Scalar::one().into_repr().to_bytes_le()))); // 1*a
  606. B.push((0, num_vars + 2, Scalar::one().into_repr().to_bytes_le())); // 1*a
  607. C.push((0, num_vars + 1, Scalar::one().into_repr().to_bytes_le())); // 1*z
  608. C.push((
  609. 0,
  610. num_vars,
  611. (-Scalar::from(13u64)).into_repr().to_bytes_le(),
  612. )); // -13*1
  613. C.push((0, num_vars + 3, (-Scalar::one()).into_repr().to_bytes_le())); // -1*b
  614. // Var Assignments (Z_0 = 16 is the only output)
  615. let vars = vec![Scalar::zero().into_repr().to_bytes_le(); num_vars];
  616. // create an InputsAssignment (a = 1, b = 2)
  617. let mut inputs = vec![Scalar::zero().into_repr().to_bytes_le(); num_inputs];
  618. inputs[0] = Scalar::from(16u64).into_repr().to_bytes_le();
  619. inputs[1] = Scalar::from(1u64).into_repr().to_bytes_le();
  620. inputs[2] = Scalar::from(2u64).into_repr().to_bytes_le();
  621. let assignment_inputs = InputsAssignment::new(&inputs).unwrap();
  622. let assignment_vars = VarsAssignment::new(&vars).unwrap();
  623. // Check if instance is satisfiable
  624. let inst = Instance::new(num_cons, num_vars, num_inputs, &A, &B, &C).unwrap();
  625. let res = inst.is_sat(&assignment_vars, &assignment_inputs);
  626. assert!(res.unwrap(), "should be satisfied");
  627. // SNARK public params
  628. let gens = SNARKGens::new(num_cons, num_vars, num_inputs, num_non_zero_entries);
  629. // create a commitment to the R1CS instance
  630. let (comm, decomm) = SNARK::encode(&inst, &gens);
  631. // produce a SNARK
  632. let mut prover_transcript = Transcript::new(b"snark_example");
  633. let proof = SNARK::prove(
  634. &inst,
  635. &comm,
  636. &decomm,
  637. assignment_vars.clone(),
  638. &assignment_inputs,
  639. &gens,
  640. &mut prover_transcript,
  641. );
  642. // verify the SNARK
  643. let mut verifier_transcript = Transcript::new(b"snark_example");
  644. assert!(proof
  645. .verify(&comm, &assignment_inputs, &mut verifier_transcript, &gens)
  646. .is_ok());
  647. // NIZK public params
  648. let gens = NIZKGens::new(num_cons, num_vars, num_inputs);
  649. // produce a NIZK
  650. let mut prover_transcript = Transcript::new(b"nizk_example");
  651. let proof = NIZK::prove(
  652. &inst,
  653. assignment_vars,
  654. &assignment_inputs,
  655. &gens,
  656. &mut prover_transcript,
  657. );
  658. // verify the NIZK
  659. let mut verifier_transcript = Transcript::new(b"nizk_example");
  660. assert!(proof
  661. .verify(&inst, &assignment_inputs, &mut verifier_transcript, &gens)
  662. .is_ok());
  663. }
  664. }