22from elliptic_curves .models .bilinear_pairings import BilinearPairingCurve
33from elliptic_curves .data_structures .vk import PreparedVerifyingKey
44from elliptic_curves .data_structures .zkscript import ZkScriptProof
5+ from elliptic_curves .util .zkscript import (
6+ multi_scalar_multiplication_with_fixed_bases_gradients ,
7+ unrolled_multiplication_gradients ,
8+ )
59
610
711class PreparedProof :
12+ """Prepared proof encapsulating the pre-computed data required to prove that a Groth16 proof is valid.
13+
14+ Args:
15+ proof: The proof.
16+ curve: The curve over which Groth16 is instantiated.
17+ public_statements (list[int]): The public statements for which the proof has been created (w/o the initial 1).
18+ gradients_b: The gradients required to compute proof.b * curve.miller_loop_engine.exp_miller_loop.
19+ gradients_minus_gamma: The gradients required to compute minus_gamma * curve.miller_loop_engine.exp_miller_loop.
20+ gradients_minus_delta: The gradients required to compute minus_delta * curve.miller_loop_engine.exp_miller_loop.
21+ inverse_miller_loop: The inverse of miller_loop([proof.a, sum(vk.gamma_abc), proof.c], [proof.b, -vk.gamma, -vk.delta]).
22+ msm_key: Instance of MsmWithFixedBasesGradients to compute sum_(i=1)^l public_statement[i-1] * vk.gamma_abc[i].
23+ gradient_gamma_abc_zero: The gradient to compute vk.gamma_abc[0] + sum_(i=1)^l public_statement[i-1] * vk.gamma_abc[i].
24+ """
25+
826 def __init__ (
927 self ,
1028 proof ,
@@ -14,8 +32,8 @@ def __init__(
1432 gradients_minus_gamma ,
1533 gradients_minus_delta ,
1634 inverse_miller_loop ,
17- gradients_msm ,
18- gradients_public_statements ,
35+ msm_key ,
36+ gradient_gamma_abc_zero ,
1937 ):
2038 self .proof = proof
2139 self .curve = curve
@@ -24,12 +42,14 @@ def __init__(
2442 self .gradients_minus_gamma = gradients_minus_gamma
2543 self .gradients_minus_delta = gradients_minus_delta
2644 self .inverse_miller_loop = inverse_miller_loop
27- self .gradients_msm = gradients_msm
28- self .gradients_public_statements = gradients_public_statements
45+ self .msm_key = msm_key
46+ self .gradient_gamma_abc_zero = gradient_gamma_abc_zero
2947 return
3048
3149
3250class Proof :
51+ """Class encapsulating a Groth16 proof."""
52+
3353 def __init__ (self , curve : BilinearPairingCurve , a : G1Point , b : G2Point , c : G1Point ):
3454 self .curve = curve
3555 self .a = a
@@ -39,6 +59,7 @@ def __init__(self, curve: BilinearPairingCurve, a: G1Point, b: G2Point, c: G1Poi
3959 def prepare (
4060 self , prepared_vk : PreparedVerifyingKey , public_statements : list [int ]
4161 ) -> PreparedProof :
62+ """Turn an instance of `Self` into an instance of `PreparedProof`."""
4263 public_statements_extended = [1 , * public_statements ]
4364
4465 # Compute \sum_(i=0)^l a_i * gamma_abc[i]
@@ -47,66 +68,46 @@ def prepare(
4768 len (prepared_vk .vk .gamma_abc ) == n_pub + 1
4869 ), "Wrong number of public inputs"
4970
50- sum_gamma_abc = prepared_vk .vk .gamma_abc [0 ]
51- for i in range (1 , n_pub + 1 ):
71+ sum_gamma_abc = prepared_vk .vk .gamma_abc [1 ].multiply (
72+ public_statements_extended [1 ]
73+ )
74+ for i in range (2 , n_pub + 1 ):
5275 sum_gamma_abc += prepared_vk .vk .gamma_abc [i ].multiply (
5376 public_statements_extended [i ]
5477 )
5578
5679 # Gradients for the pairing
57- gradients_b = self .b .gradients (self .curve .miller_loop_engine .exp_miller_loop )
80+ gradients_b = unrolled_multiplication_gradients (
81+ self .curve .miller_loop_engine .val_miller_loop ,
82+ self .b ,
83+ self .curve .miller_loop_engine .exp_miller_loop ,
84+ )
5885
5986 # Inverse of the Miller loop output
6087 inverse_miller_loop = self .curve .miller_loop (
61- [self .a , sum_gamma_abc , self .c ],
88+ [self .a , sum_gamma_abc + prepared_vk . vk . gamma_abc [ 0 ] , self .c ],
6289 [self .b , prepared_vk .minus_gamma , prepared_vk .minus_delta ],
6390 ).invert ()
6491
65- # Compute gradients for partial sums: gradients between a_i * gamma_abc[i] and \sum_(j=0)^(i-1) a_j * gamma_abc[j]
66- gradients_msm = []
67- for i in range (n_pub , 0 , - 1 ):
68- sum_gamma_abc -= prepared_vk .vk .gamma_abc [i ].multiply (
69- public_statements_extended [i ]
70- )
71- if (
72- sum_gamma_abc .is_infinity ()
73- or prepared_vk .vk .gamma_abc [i ]
74- .multiply (public_statements_extended [i ])
75- .is_infinity ()
76- ):
77- gradients_msm .append ([])
78- else :
79- gradient = sum_gamma_abc .gradient (
80- prepared_vk .vk .gamma_abc [i ].multiply (public_statements_extended [i ])
81- )
82- gradients_msm .append (gradient )
83-
84- # Gradients for multiplications pub[i] * gamma_abc[i]
85- gradients_public_statements = []
86- for i in range (1 , n_pub + 1 ):
87- if public_statements_extended [i ] == 0 :
88- gradients_public_statements .append ([])
89- else :
90- # Binary expansion of pub[i]
91- exp_pub_i = [
92- int (bin (public_statements_extended [i ])[j ])
93- for j in range (2 , len (bin (public_statements_extended [i ])))
94- ][::- 1 ]
95-
96- gradients_public_statements .append (
97- prepared_vk .vk .gamma_abc [i ].gradients (exp_pub_i )
98- )
92+ # Gradient for addition of gamma_abc[0]
93+ gradient_gamma_abc_zero = sum_gamma_abc .gradient (prepared_vk .vk .gamma_abc [0 ])
94+
95+ # Gradients for msm
96+ msm_key = multi_scalar_multiplication_with_fixed_bases_gradients (
97+ public_statements ,
98+ prepared_vk .vk .gamma_abc [1 :],
99+ )
99100
100101 return PreparedProof (
101102 self ,
102103 self .curve ,
103104 public_statements ,
104105 gradients_b ,
105- prepared_vk .gradients_minus_delta ,
106+ prepared_vk .gradients_minus_gamma ,
106107 prepared_vk .gradients_minus_delta ,
107108 inverse_miller_loop ,
108- gradients_msm ,
109- gradients_public_statements ,
109+ msm_key ,
110+ gradient_gamma_abc_zero ,
110111 )
111112
112113 def prepare_for_zkscript (
@@ -115,55 +116,35 @@ def prepare_for_zkscript(
115116 public_statements : list [int ],
116117 prepared_proof : PreparedProof | None = None ,
117118 ) -> ZkScriptProof :
119+ """Turn an instance of `Self` into an instance of `ZkScriptProof`."""
118120 prepared_proof = (
119121 prepared_proof
120122 if prepared_proof is not None
121123 else self .prepare (prepared_vk , public_statements )
122124 )
123125
124- gradients_msm = []
125- for gradient in prepared_proof .gradients_msm :
126- try :
127- gradients_msm .append (gradient .to_list ())
128- except Exception as _ :
129- gradients_msm .append ([])
130-
131- gradients_public_statements = []
132- for gradients in prepared_proof .gradients_public_statements :
133- try :
134- gradients_public_statements .append (
135- [
136- list (map (lambda s : s .to_list (), gradient ))
137- for gradient in gradients
138- ]
139- )
140- except Exception as _ :
141- gradients_public_statements .append ([])
126+ gradients_multiplications , gradients_additions = (
127+ prepared_proof .msm_key .as_data ()
128+ )
142129
143130 return ZkScriptProof (
144131 self .a .to_list (),
145132 self .b .to_list (),
146133 self .c .to_list (),
147134 public_statements ,
148- [
149- list (map (lambda s : s .to_list (), gradient ))
150- for gradient in prepared_proof .gradients_b
151- ],
152- [
153- list (map (lambda s : s .to_list (), gradient ))
154- for gradient in prepared_vk .gradients_minus_gamma
155- ],
156- [
157- list (map (lambda s : s .to_list (), gradient ))
158- for gradient in prepared_vk .gradients_minus_delta
159- ],
135+ prepared_proof .gradients_b .as_data (),
136+ prepared_vk .gradients_minus_gamma .as_data (),
137+ prepared_vk .gradients_minus_delta .as_data (),
160138 prepared_proof .inverse_miller_loop .to_list (),
161- gradients_msm ,
162- gradients_public_statements ,
139+ gradients_multiplications ,
140+ gradients_additions ,
141+ prepared_proof .gradient_gamma_abc_zero .to_list (),
163142 )
164143
165144
166145class ProofGeneric :
146+ """Generic proof class encapsulating the curve over which Groth16 proof is instantiated."""
147+
167148 def __init__ (self , curve : BilinearPairingCurve ):
168149 self .curve = curve
169150
0 commit comments