@@ -8,6 +8,9 @@ use lambdaworks_math::field::element::FieldElement;
8
8
use lambdaworks_math:: field:: traits:: { HasDefaultTranscript , IsField } ;
9
9
use lambdaworks_math:: traits:: ByteConversion ;
10
10
11
+ pub use prover:: prove;
12
+ pub use verifier:: verify;
13
+
11
14
pub trait Channel < F : IsField > {
12
15
fn append_felt ( & mut self , element : & FieldElement < F > ) ;
13
16
fn draw_felt ( & mut self ) -> FieldElement < F > ;
@@ -26,3 +29,318 @@ where
26
29
self . sample_field_element ( )
27
30
}
28
31
}
32
+
33
+ #[ cfg( test) ]
34
+ mod tests {
35
+ use super :: * ;
36
+ use lambdaworks_math:: field:: fields:: u64_prime_field:: U64PrimeField ;
37
+ use lambdaworks_math:: polynomial:: dense_multilinear_poly:: DenseMultilinearPolynomial ;
38
+ use verifier:: VerifierRoundResult ;
39
+
40
+ // Using a small prime field with modulus 101.
41
+ const MODULUS : u64 = 101 ;
42
+ type F = U64PrimeField < MODULUS > ;
43
+ type FE = FieldElement < F > ;
44
+
45
+ #[ test]
46
+ fn test_protocol ( ) {
47
+ let poly = DenseMultilinearPolynomial :: new ( vec ! [
48
+ FE :: from( 3 ) ,
49
+ FE :: from( 5 ) ,
50
+ FE :: from( 7 ) ,
51
+ FE :: from( 11 ) ,
52
+ ] ) ;
53
+
54
+ let ( claimed_sum, proof_polys) = prove ( poly. clone ( ) ) ;
55
+
56
+ let result = verify ( poly. num_vars ( ) , claimed_sum, proof_polys, Some ( poly) ) ;
57
+
58
+ assert ! ( result. unwrap_or( false ) , "Valid proof should be accepted" ) ;
59
+ }
60
+
61
+ #[ test]
62
+ fn test_interactive_sumcheck ( ) {
63
+ let poly = DenseMultilinearPolynomial :: new ( vec ! [
64
+ FE :: from( 1 ) ,
65
+ FE :: from( 2 ) ,
66
+ FE :: from( 1 ) ,
67
+ FE :: from( 4 ) ,
68
+ ] ) ;
69
+
70
+ let mut prover = prover:: Prover :: new ( poly. clone ( ) ) ;
71
+ let c_1 = prover. c_1 ( ) ;
72
+ println ! ( "\n Initial claimed sum c₁: {:?}" , c_1) ;
73
+ let mut transcript = DefaultTranscript :: < F > :: default ( ) ;
74
+ let mut verifier = verifier:: Verifier :: new ( poly. num_vars ( ) , Some ( poly) , c_1) ;
75
+
76
+ // Round 0
77
+ println ! ( "\n -- Round 0 --" ) ;
78
+ let univar0 = prover. poly . to_univariate ( ) ;
79
+ println ! (
80
+ "Univariate polynomial g₀(x) coefficients: {:?}" ,
81
+ univar0. coefficients
82
+ ) ;
83
+ let eval_0 = univar0. evaluate ( & FieldElement :: < F > :: zero ( ) ) ;
84
+ let eval_1 = univar0. evaluate ( & FieldElement :: < F > :: one ( ) ) ;
85
+ println ! (
86
+ "g₀(0) = {:?}, g₀(1) = {:?}, sum = {:?}" ,
87
+ eval_0,
88
+ eval_1,
89
+ eval_0 + eval_1
90
+ ) ;
91
+ let res0 = verifier. do_round ( univar0, & mut transcript) . unwrap ( ) ;
92
+ let r0 = if let VerifierRoundResult :: NextRound ( chal) = res0 {
93
+ println ! ( "Challenge r₀: {:?}" , chal) ;
94
+ chal
95
+ } else {
96
+ panic ! ( "Expected NextRound result" ) ;
97
+ } ;
98
+
99
+ // Round 1
100
+ println ! ( "\n -- Round 1 (Final) --" ) ;
101
+ let univar1 = prover. round ( r0) ;
102
+ println ! (
103
+ "Univariate polynomial g₁(x) coefficients: {:?}" ,
104
+ univar1. coefficients
105
+ ) ;
106
+ let eval_0 = univar1. evaluate ( & FieldElement :: < F > :: zero ( ) ) ;
107
+ let eval_1 = univar1. evaluate ( & FieldElement :: < F > :: one ( ) ) ;
108
+ println ! (
109
+ "g₁(0) = {:?}, g₁(1) = {:?}, sum = {:?}" ,
110
+ eval_0,
111
+ eval_1,
112
+ eval_0 + eval_1
113
+ ) ;
114
+ let res1 = verifier. do_round ( univar1, & mut transcript) . unwrap ( ) ;
115
+ if let VerifierRoundResult :: Final ( ok) = res1 {
116
+ println ! (
117
+ "\n Final verification result: {}" ,
118
+ if ok { "ACCEPTED" } else { "REJECTED" }
119
+ ) ;
120
+ assert ! ( ok, "Final round verification failed" ) ;
121
+ } else {
122
+ panic ! ( "Expected Final result" ) ;
123
+ }
124
+ }
125
+
126
+ /// Test based on a textbook example for a 3-variable polynomial
127
+ #[ test]
128
+ fn test_from_book ( ) {
129
+ // 3-variable polynomial with evaluations:
130
+ // (0,0,0)=1, (1,0,0)=2, (0,1,0)=3, (1,1,0)=4,
131
+ // (0,0,1)=5, (1,0,1)=6, (0,1,1)=7, (1,1,1)=8.
132
+ let poly = DenseMultilinearPolynomial :: new ( vec ! [
133
+ FE :: from( 1 ) ,
134
+ FE :: from( 2 ) ,
135
+ FE :: from( 3 ) ,
136
+ FE :: from( 4 ) ,
137
+ FE :: from( 5 ) ,
138
+ FE :: from( 6 ) ,
139
+ FE :: from( 7 ) ,
140
+ FE :: from( 8 ) ,
141
+ ] ) ;
142
+ // Total sum (claimed sum) is 36.
143
+ let mut prover = prover:: Prover :: new ( poly. clone ( ) ) ;
144
+ let c_1 = prover. c_1 ( ) ;
145
+ println ! ( "\n Initial claimed sum c₁: {:?}" , c_1) ;
146
+ let mut transcript = DefaultTranscript :: < F > :: default ( ) ;
147
+ let mut verifier = verifier:: Verifier :: new ( poly. num_vars ( ) , Some ( poly) , c_1) ;
148
+
149
+ // Round 0
150
+ let mut g = prover. poly . to_univariate ( ) ;
151
+ println ! ( "\n -- Round 0 --" ) ;
152
+ println ! (
153
+ "Univariate polynomial g₀(x) coefficients: {:?}" ,
154
+ g. coefficients
155
+ ) ;
156
+ let eval_0 = g. evaluate ( & FieldElement :: < F > :: zero ( ) ) ;
157
+ let eval_1 = g. evaluate ( & FieldElement :: < F > :: one ( ) ) ;
158
+ println ! (
159
+ "g₀(0) = {:?}, g₀(1) = {:?}, sum = {:?}" ,
160
+ eval_0,
161
+ eval_1,
162
+ eval_0 + eval_1
163
+ ) ;
164
+ let res0 = verifier. do_round ( g, & mut transcript) . unwrap ( ) ;
165
+ let mut current_challenge = if let VerifierRoundResult :: NextRound ( chal) = res0 {
166
+ println ! ( "Challenge r₀: {:?}" , chal) ;
167
+ chal
168
+ } else {
169
+ panic ! ( "Expected NextRound result" ) ;
170
+ } ;
171
+
172
+ // Continue rounds until final.
173
+ let mut round = 1 ;
174
+ while verifier. round < verifier. n {
175
+ println ! (
176
+ "\n -- Round {} {}" ,
177
+ round,
178
+ if round == verifier. n - 1 {
179
+ "(Final)"
180
+ } else {
181
+ ""
182
+ }
183
+ ) ;
184
+ g = prover. round ( current_challenge) ;
185
+ println ! (
186
+ "Univariate polynomial g{}(x) coefficients: {:?}" ,
187
+ round, g. coefficients
188
+ ) ;
189
+ let eval_0 = g. evaluate ( & FieldElement :: < F > :: zero ( ) ) ;
190
+ let eval_1 = g. evaluate ( & FieldElement :: < F > :: one ( ) ) ;
191
+ println ! (
192
+ "g{}(0) = {:?}, g{}(1) = {:?}, sum = {:?}" ,
193
+ round,
194
+ eval_0,
195
+ round,
196
+ eval_1,
197
+ eval_0 + eval_1
198
+ ) ;
199
+ let res = verifier. do_round ( g, & mut transcript) . unwrap ( ) ;
200
+ match res {
201
+ VerifierRoundResult :: NextRound ( chal) => {
202
+ println ! ( "Challenge r{}: {:?}" , round, chal) ;
203
+ current_challenge = chal;
204
+ }
205
+ VerifierRoundResult :: Final ( ok) => {
206
+ println ! (
207
+ "\n Final verification result: {}" ,
208
+ if ok { "ACCEPTED" } else { "REJECTED" }
209
+ ) ;
210
+ assert ! ( ok, "Final round verification failed" ) ;
211
+ break ;
212
+ }
213
+ }
214
+ round += 1 ;
215
+ }
216
+ }
217
+
218
+ #[ test]
219
+ fn test_from_book_ported ( ) {
220
+ // 3-variable polynomial: f(x₀,x₁,x₂)=2*x₀ + x₀*x₂ + x₁*x₂.
221
+ // Evaluations (little-endian): [0, 2, 0, 2, 0, 3, 1, 4]. Total sum = 12.
222
+ let poly = DenseMultilinearPolynomial :: new ( vec ! [
223
+ FE :: from( 0 ) ,
224
+ FE :: from( 2 ) ,
225
+ FE :: from( 0 ) ,
226
+ FE :: from( 2 ) ,
227
+ FE :: from( 0 ) ,
228
+ FE :: from( 3 ) ,
229
+ FE :: from( 1 ) ,
230
+ FE :: from( 4 ) ,
231
+ ] ) ;
232
+ let mut prover = prover:: Prover :: new ( poly. clone ( ) ) ;
233
+ let c_1 = prover. c_1 ( ) ;
234
+ println ! ( "\n Initial claimed sum c₁: {:?}" , c_1) ;
235
+ let mut transcript = DefaultTranscript :: < F > :: default ( ) ;
236
+ let mut verifier = verifier:: Verifier :: new ( poly. num_vars ( ) , Some ( poly) , c_1) ;
237
+
238
+ // Round 0:
239
+ println ! ( "\n -- Round 0 --" ) ;
240
+ let univar0 = prover. poly . to_univariate ( ) ;
241
+ println ! (
242
+ "Univariate polynomial g₀(x) coefficients: {:?}" ,
243
+ univar0. coefficients
244
+ ) ;
245
+ let eval_0 = univar0. evaluate ( & FieldElement :: < F > :: zero ( ) ) ;
246
+ let eval_1 = univar0. evaluate ( & FieldElement :: < F > :: one ( ) ) ;
247
+ println ! (
248
+ "g₀(0) = {:?}, g₀(1) = {:?}, sum = {:?}" ,
249
+ eval_0,
250
+ eval_1,
251
+ eval_0 + eval_1
252
+ ) ;
253
+ let res0 = verifier. do_round ( univar0, & mut transcript) . unwrap ( ) ;
254
+ let r0 = if let VerifierRoundResult :: NextRound ( chal) = res0 {
255
+ println ! ( "Challenge r₀: {:?}" , chal) ;
256
+ chal
257
+ } else {
258
+ panic ! ( "Expected NextRound result" ) ;
259
+ } ;
260
+
261
+ // Round 1:
262
+ println ! ( "\n -- Round 1 --" ) ;
263
+ let univar1 = prover. round ( r0) ;
264
+ println ! (
265
+ "Univariate polynomial g₁(x) coefficients: {:?}" ,
266
+ univar1. coefficients
267
+ ) ;
268
+ let eval_0 = univar1. evaluate ( & FieldElement :: < F > :: zero ( ) ) ;
269
+ let eval_1 = univar1. evaluate ( & FieldElement :: < F > :: one ( ) ) ;
270
+ println ! (
271
+ "g₁(0) = {:?}, g₁(1) = {:?}, sum = {:?}" ,
272
+ eval_0,
273
+ eval_1,
274
+ eval_0 + eval_1
275
+ ) ;
276
+ let res1 = verifier. do_round ( univar1, & mut transcript) . unwrap ( ) ;
277
+ let r1 = if let VerifierRoundResult :: NextRound ( chal) = res1 {
278
+ println ! ( "Challenge r₁: {:?}" , chal) ;
279
+ chal
280
+ } else {
281
+ panic ! ( "Expected NextRound result" ) ;
282
+ } ;
283
+
284
+ // Round 2 (final round):
285
+ println ! ( "\n -- Round 2 (Final) --" ) ;
286
+ let univar2 = prover. round ( r1) ;
287
+ println ! (
288
+ "Univariate polynomial g₂(x) coefficients: {:?}" ,
289
+ univar2. coefficients
290
+ ) ;
291
+ let eval_0 = univar2. evaluate ( & FieldElement :: < F > :: zero ( ) ) ;
292
+ let eval_1 = univar2. evaluate ( & FieldElement :: < F > :: one ( ) ) ;
293
+ println ! (
294
+ "g₂(0) = {:?}, g₂(1) = {:?}, sum = {:?}" ,
295
+ eval_0,
296
+ eval_1,
297
+ eval_0 + eval_1
298
+ ) ;
299
+ let res2 = verifier. do_round ( univar2, & mut transcript) . unwrap ( ) ;
300
+ if let VerifierRoundResult :: Final ( ok) = res2 {
301
+ println ! (
302
+ "\n Final verification result: {}" ,
303
+ if ok { "ACCEPTED" } else { "REJECTED" }
304
+ ) ;
305
+ assert ! ( ok, "Final round verification failed" ) ;
306
+ } else {
307
+ panic ! ( "Expected Final result" ) ;
308
+ }
309
+ }
310
+
311
+ #[ test]
312
+ fn failing_verification_test ( ) {
313
+ let poly = DenseMultilinearPolynomial :: new ( vec ! [
314
+ FE :: from( 1 ) ,
315
+ FE :: from( 2 ) ,
316
+ FE :: from( 1 ) ,
317
+ FE :: from( 4 ) ,
318
+ ] ) ;
319
+ let prover = prover:: Prover :: new ( poly. clone ( ) ) ;
320
+ // Deliberately use an incorrect claimed sum.
321
+ let incorrect_c1 = FE :: from ( 999 ) ;
322
+ println ! ( "\n Initial (incorrect) claimed sum c₁: {:?}" , incorrect_c1) ;
323
+ let mut transcript = DefaultTranscript :: < F > :: default ( ) ;
324
+ let mut verifier = verifier:: Verifier :: new ( poly. num_vars ( ) , Some ( poly) , incorrect_c1) ;
325
+
326
+ println ! ( "\n -- Round 0 --" ) ;
327
+ let univar0 = prover. poly . to_univariate ( ) ;
328
+ println ! (
329
+ "Univariate polynomial g₀(x) coefficients: {:?}" ,
330
+ univar0. coefficients
331
+ ) ;
332
+ let eval_0 = univar0. evaluate ( & FieldElement :: < F > :: zero ( ) ) ;
333
+ let eval_1 = univar0. evaluate ( & FieldElement :: < F > :: one ( ) ) ;
334
+ println ! (
335
+ "g₀(0) = {:?}, g₀(1) = {:?}, sum = {:?}" ,
336
+ eval_0,
337
+ eval_1,
338
+ eval_0 + eval_1
339
+ ) ;
340
+ let res0 = verifier. do_round ( univar0, & mut transcript) ;
341
+ if let Err ( e) = & res0 {
342
+ println ! ( "\n Expected verification error: {:?}" , e) ;
343
+ }
344
+ assert ! ( res0. is_err( ) , "Expected verification error" ) ;
345
+ }
346
+ }
0 commit comments