|
6 | 6 |
|
7 | 7 | use ark_bn254::Bn254; |
8 | 8 | use ark_ec::{AffineRepr, pairing::Pairing}; |
9 | | -use ark_ff::Field; |
| 9 | +use ark_ff::{Field, PrimeField}; |
10 | 10 | use ark_groth16::VerifyingKey; |
11 | 11 | use ark_serialize::CanonicalSerialize; |
12 | 12 | use circuit_component_macro::component; |
13 | 13 | use num_bigint::BigUint; |
14 | 14 |
|
15 | 15 | use crate::{ |
16 | 16 | CircuitContext, WireId, |
17 | | - circuit::{CircuitInput, CircuitMode, EncodeInput, WiresObject}, |
| 17 | + circuit::{CircuitInput, CircuitMode, EncodeInput, TRUE_WIRE, WiresObject}, |
18 | 18 | gadgets::{ |
19 | | - bigint::BigIntWires, |
| 19 | + bigint::{self, BigIntWires}, |
20 | 20 | bn254::{ |
21 | 21 | G2Projective, final_exponentiation::final_exponentiation_montgomery, fq::Fq, |
22 | 22 | fq12::Fq12, fr::Fr, g1::G1Projective, |
@@ -68,26 +68,87 @@ pub fn groth16_verify<C: CircuitContext>( |
68 | 68 | vk, |
69 | 69 | } = input; |
70 | 70 |
|
71 | | - let proof_is_on_curve = { |
72 | | - let a_is_on_curve = G1Projective::is_on_curve(circuit, a); |
73 | | - let b_is_on_curve = G2Projective::is_on_curve(circuit, b); |
74 | | - let c_is_on_curve = G1Projective::is_on_curve(circuit, c); |
| 71 | + let is_valid_field_and_group = { |
| 72 | + let is_valid_fr = { |
| 73 | + let mut and_all_wires = TRUE_WIRE; |
| 74 | + public.iter().for_each(|pubinp| { |
| 75 | + let r: BigUint = ark_bn254::Fr::MODULUS.into(); |
| 76 | + let valid_pubinp = bigint::less_than_constant(circuit, pubinp, &r); |
| 77 | + let new_wire = circuit.issue_wire(); |
| 78 | + circuit.add_gate(crate::Gate { |
| 79 | + wire_a: and_all_wires, |
| 80 | + wire_b: valid_pubinp, |
| 81 | + wire_c: new_wire, |
| 82 | + gate_type: crate::GateType::And, |
| 83 | + }); |
| 84 | + and_all_wires = new_wire; |
| 85 | + }); |
| 86 | + and_all_wires |
| 87 | + }; |
| 88 | + |
| 89 | + // Verify that all group elements of input proof include valid base field elements |
| 90 | + let is_valid_fq = { |
| 91 | + let elems = [ |
| 92 | + &a.x, &a.y, &a.z, &b.x.0[0], &b.x.0[1], &b.y.0[0], &b.y.0[1], &b.z.0[0], &b.z.0[1], |
| 93 | + &c.x, &c.y, &c.z, |
| 94 | + ]; |
| 95 | + let mut and_all_wires = TRUE_WIRE; |
| 96 | + elems.iter().for_each(|pubinp| { |
| 97 | + let r: BigUint = ark_bn254::Fq::MODULUS.into(); |
| 98 | + let valid_fq = bigint::less_than_constant(circuit, pubinp, &r); |
| 99 | + let new_wire = circuit.issue_wire(); |
| 100 | + circuit.add_gate(crate::Gate { |
| 101 | + wire_a: and_all_wires, |
| 102 | + wire_b: valid_fq, |
| 103 | + wire_c: new_wire, |
| 104 | + gate_type: crate::GateType::And, |
| 105 | + }); |
| 106 | + and_all_wires = new_wire; |
| 107 | + }); |
| 108 | + and_all_wires |
| 109 | + }; |
75 | 110 |
|
76 | | - let tmp0 = circuit.issue_wire(); |
77 | | - let tmp1 = circuit.issue_wire(); |
| 111 | + let is_on_curve = { |
| 112 | + let a_is_on_curve = G1Projective::is_on_curve(circuit, a); |
| 113 | + let b_is_on_curve = G2Projective::is_on_curve(circuit, b); |
| 114 | + let c_is_on_curve = G1Projective::is_on_curve(circuit, c); |
| 115 | + |
| 116 | + // valid group check |
| 117 | + let tmp0 = circuit.issue_wire(); |
| 118 | + let is_on_curve = circuit.issue_wire(); |
| 119 | + circuit.add_gate(crate::Gate { |
| 120 | + wire_a: a_is_on_curve, |
| 121 | + wire_b: b_is_on_curve, |
| 122 | + wire_c: tmp0, |
| 123 | + gate_type: crate::GateType::And, |
| 124 | + }); |
| 125 | + circuit.add_gate(crate::Gate { |
| 126 | + wire_a: tmp0, |
| 127 | + wire_b: c_is_on_curve, |
| 128 | + wire_c: is_on_curve, |
| 129 | + gate_type: crate::GateType::And, |
| 130 | + }); |
| 131 | + is_on_curve |
| 132 | + }; |
| 133 | + |
| 134 | + // valid fq and fr |
| 135 | + let is_valid_field = circuit.issue_wire(); |
78 | 136 | circuit.add_gate(crate::Gate { |
79 | | - wire_a: a_is_on_curve, |
80 | | - wire_b: b_is_on_curve, |
81 | | - wire_c: tmp0, |
| 137 | + wire_a: is_valid_fr, |
| 138 | + wire_b: is_valid_fq, |
| 139 | + wire_c: is_valid_field, |
82 | 140 | gate_type: crate::GateType::And, |
83 | 141 | }); |
| 142 | + |
| 143 | + // valid field and group check |
| 144 | + let is_valid_field_and_group = circuit.issue_wire(); |
84 | 145 | circuit.add_gate(crate::Gate { |
85 | | - wire_a: tmp0, |
86 | | - wire_b: c_is_on_curve, |
87 | | - wire_c: tmp1, |
| 146 | + wire_a: is_valid_field, |
| 147 | + wire_b: is_on_curve, |
| 148 | + wire_c: is_valid_field_and_group, |
88 | 149 | gate_type: crate::GateType::And, |
89 | 150 | }); |
90 | | - tmp1 |
| 151 | + is_valid_field_and_group |
91 | 152 | }; |
92 | 153 |
|
93 | 154 | // Standard verification with public inputs |
@@ -135,7 +196,7 @@ pub fn groth16_verify<C: CircuitContext>( |
135 | 196 | let valid = circuit.issue_wire(); |
136 | 197 | circuit.add_gate(crate::Gate { |
137 | 198 | wire_a: finexp_match, |
138 | | - wire_b: proof_is_on_curve, |
| 199 | + wire_b: is_valid_field_and_group, |
139 | 200 | wire_c: valid, |
140 | 201 | gate_type: crate::GateType::And, |
141 | 202 | }); |
|
0 commit comments