@@ -18,8 +18,10 @@ TEST(ECCVMCircuitBuilderTests, BaseCase)
1818 typename G1 ::element a = generators[0 ];
1919 typename G1 ::element b = generators[1 ];
2020 typename G1 ::element c = generators[2 ];
21+ typename G1 ::element point_at_infinity = G1 ::point_at_infinity;
2122 Fr x = Fr::random_element (&engine);
2223 Fr y = Fr::random_element (&engine);
24+ Fr zero_scalar = 0 ;
2325
2426 std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
2527
@@ -29,14 +31,49 @@ TEST(ECCVMCircuitBuilderTests, BaseCase)
2931 op_queue->mul_accumulate (b, y);
3032 op_queue->add_accumulate (a);
3133 op_queue->mul_accumulate (b, x);
34+ op_queue->no_op ();
35+ op_queue->add_accumulate (b);
3236 op_queue->eq_and_reset ();
3337 op_queue->add_accumulate (c);
3438 op_queue->mul_accumulate (a, x);
39+ op_queue->mul_accumulate (point_at_infinity, x);
3540 op_queue->mul_accumulate (b, x);
3641 op_queue->eq_and_reset ();
3742 op_queue->mul_accumulate (a, x);
3843 op_queue->mul_accumulate (b, x);
44+ op_queue->mul_accumulate (point_at_infinity, zero_scalar);
3945 op_queue->mul_accumulate (c, x);
46+ op_queue->eq_and_reset ();
47+ op_queue->mul_accumulate (point_at_infinity, zero_scalar);
48+ op_queue->mul_accumulate (point_at_infinity, x);
49+ op_queue->mul_accumulate (point_at_infinity, zero_scalar);
50+ op_queue->add_accumulate (a);
51+ op_queue->eq_and_reset ();
52+ op_queue->add_accumulate (a);
53+ op_queue->add_accumulate (point_at_infinity);
54+ op_queue->eq_and_reset ();
55+ op_queue->add_accumulate (point_at_infinity);
56+ op_queue->eq_and_reset ();
57+ op_queue->mul_accumulate (point_at_infinity, x);
58+ op_queue->mul_accumulate (point_at_infinity, -x);
59+ op_queue->eq_and_reset ();
60+ op_queue->add_accumulate (a);
61+ op_queue->mul_accumulate (point_at_infinity, x);
62+ op_queue->mul_accumulate (point_at_infinity, -x);
63+ op_queue->add_accumulate (a);
64+ op_queue->add_accumulate (a);
65+ op_queue->eq_and_reset ();
66+
67+ ECCVMCircuitBuilder circuit{ op_queue };
68+ bool result = ECCVMTraceChecker::check (circuit);
69+ EXPECT_EQ (result, true );
70+ }
71+
72+ TEST (ECCVMCircuitBuilderTests, NoOp)
73+ {
74+ std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
75+
76+ op_queue->no_op ();
4077
4178 ECCVMCircuitBuilder circuit{ op_queue };
4279 bool result = ECCVMTraceChecker::check (circuit, &engine);
@@ -72,6 +109,109 @@ TEST(ECCVMCircuitBuilderTests, Mul)
72109 EXPECT_EQ (result, true );
73110}
74111
112+ TEST (ECCVMCircuitBuilderTests, MulInfinity)
113+ {
114+ std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
115+
116+ auto generators = G1::derive_generators (" test generators" , 3 );
117+ typename G1 ::element a = generators[0 ];
118+ Fr x = Fr::random_element (&engine);
119+ G1 ::element b = -a * x;
120+ // G1::affine_element c = G1::affine_point_at_infinity;
121+ op_queue->add_accumulate (b);
122+ op_queue->mul_accumulate (a, x);
123+ op_queue->eq_and_reset ();
124+ ECCVMCircuitBuilder circuit{ op_queue };
125+ bool result = ECCVMTraceChecker::check (circuit);
126+ EXPECT_EQ (result, true );
127+ }
128+
129+ // Validate we do not trigger edge cases of addition formulae when we have identical mul inputs
130+ TEST (ECCVMCircuitBuilderTests, MulOverIdenticalInputs)
131+ {
132+ std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
133+
134+ auto generators = G1::derive_generators (" test generators" , 3 );
135+ typename G1 ::element a = generators[0 ];
136+ Fr x = Fr::random_element (&engine);
137+ op_queue->mul_accumulate (a, x);
138+ op_queue->mul_accumulate (a, x);
139+ op_queue->eq_and_reset ();
140+ ECCVMCircuitBuilder circuit{ op_queue };
141+ bool result = ECCVMTraceChecker::check (circuit);
142+ EXPECT_EQ (result, true );
143+ }
144+
145+ TEST (ECCVMCircuitBuilderTests, MSMProducesInfinity)
146+ {
147+ std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
148+
149+ auto generators = G1::derive_generators (" test generators" , 3 );
150+ typename G1 ::element a = generators[0 ];
151+ Fr x = Fr::random_element (&engine);
152+ op_queue->add_accumulate (a);
153+ op_queue->mul_accumulate (a, x);
154+ op_queue->mul_accumulate (a, -x);
155+ op_queue->eq_and_reset ();
156+ ECCVMCircuitBuilder circuit{ op_queue };
157+ bool result = ECCVMTraceChecker::check (circuit);
158+ EXPECT_EQ (result, true );
159+ }
160+
161+ TEST (ECCVMCircuitBuilderTests, MSMOverPointAtInfinity)
162+ {
163+ std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
164+
165+ auto generators = G1::derive_generators (" test generators" , 3 );
166+ typename G1 ::element point_at_infinity = G1 ::point_at_infinity;
167+ typename G1 ::element b = generators[0 ];
168+ Fr x = Fr::random_element (&engine);
169+ Fr zero_scalar = 0 ;
170+
171+ // validate including points at infinity in a multiscalar multiplication does not effect result
172+ {
173+ op_queue->mul_accumulate (b, x);
174+ op_queue->mul_accumulate (point_at_infinity, x);
175+ op_queue->eq_and_reset ();
176+ ECCVMCircuitBuilder circuit{ op_queue };
177+ bool result = ECCVMTraceChecker::check (circuit);
178+ EXPECT_EQ (result, true );
179+ }
180+ // validate multiplying a point at infinity by nonzero scalar produces point at infinity
181+ {
182+ op_queue->mul_accumulate (point_at_infinity, x);
183+ op_queue->eq_and_reset ();
184+ ECCVMCircuitBuilder circuit{ op_queue };
185+ bool result = ECCVMTraceChecker::check (circuit);
186+ EXPECT_EQ (result, true );
187+ }
188+ // validate multiplying a point by zero produces point at infinity
189+ {
190+ op_queue->mul_accumulate (b, zero_scalar);
191+ op_queue->eq_and_reset ();
192+ ECCVMCircuitBuilder circuit{ op_queue };
193+ bool result = ECCVMTraceChecker::check (circuit);
194+ EXPECT_EQ (result, true );
195+ }
196+ // validate multiplying a point at infinity by zero produces a point at infinity
197+ {
198+ op_queue->mul_accumulate (point_at_infinity, zero_scalar);
199+ op_queue->eq_and_reset ();
200+ ECCVMCircuitBuilder circuit{ op_queue };
201+ bool result = ECCVMTraceChecker::check (circuit);
202+ EXPECT_EQ (result, true );
203+ }
204+ // validate an MSM made entirely of points at infinity / zero scalars produces a point at infinity
205+ {
206+ op_queue->mul_accumulate (point_at_infinity, x);
207+ op_queue->mul_accumulate (b, zero_scalar);
208+ op_queue->eq_and_reset ();
209+ ECCVMCircuitBuilder circuit{ op_queue };
210+ bool result = ECCVMTraceChecker::check (circuit);
211+ EXPECT_EQ (result, true );
212+ }
213+ }
214+
75215TEST (ECCVMCircuitBuilderTests, ShortMul)
76216{
77217 std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
@@ -243,3 +383,67 @@ TEST(ECCVMCircuitBuilderTests, MSM)
243383 bool result = ECCVMTraceChecker::check (circuit, &engine);
244384 EXPECT_EQ (result, true );
245385}
386+
387+ TEST (ECCVMCircuitBuilderTests, EqAgainstPointAtInfinity)
388+ {
389+ std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
390+
391+ auto generators = G1::derive_generators (" test generators" , 3 );
392+ typename G1 ::element a = generators[0 ];
393+ a.self_set_infinity ();
394+
395+ op_queue->add_accumulate (a);
396+ op_queue->eq_and_reset ();
397+
398+ ECCVMCircuitBuilder circuit{ op_queue };
399+ bool result = ECCVMTraceChecker::check (circuit);
400+ EXPECT_EQ (result, true );
401+ }
402+
403+ TEST (ECCVMCircuitBuilderTests, AddPointAtInfinity)
404+ {
405+ std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
406+
407+ auto generators = G1::derive_generators (" test generators" , 3 );
408+ typename G1 ::element a = generators[0 ];
409+ typename G1 ::element b = generators[0 ];
410+ b.self_set_infinity ();
411+
412+ op_queue->add_accumulate (a);
413+ op_queue->add_accumulate (b);
414+ op_queue->eq_and_reset ();
415+
416+ ECCVMCircuitBuilder circuit{ op_queue };
417+ bool result = ECCVMTraceChecker::check (circuit);
418+ EXPECT_EQ (result, true );
419+ }
420+
421+ TEST (ECCVMCircuitBuilderTests, AddProducesPointAtInfinity)
422+ {
423+ std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
424+
425+ auto generators = G1::derive_generators (" test generators" , 3 );
426+ typename G1 ::element a = generators[0 ];
427+
428+ op_queue->add_accumulate (a);
429+ op_queue->add_accumulate (-a);
430+ op_queue->eq_and_reset ();
431+ ECCVMCircuitBuilder circuit{ op_queue };
432+ bool result = ECCVMTraceChecker::check (circuit);
433+ EXPECT_EQ (result, true );
434+ }
435+
436+ TEST (ECCVMCircuitBuilderTests, AddProducesDouble)
437+ {
438+ std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
439+
440+ auto generators = G1::derive_generators (" test generators" , 3 );
441+ typename G1 ::element a = generators[0 ];
442+
443+ op_queue->add_accumulate (a);
444+ op_queue->add_accumulate (a);
445+ op_queue->eq_and_reset ();
446+ ECCVMCircuitBuilder circuit{ op_queue };
447+ bool result = ECCVMTraceChecker::check (circuit);
448+ EXPECT_EQ (result, true );
449+ }
0 commit comments