Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
multi_scalar_mul.test.cpp
Go to the documentation of this file.
2#include "acir_format.hpp"
7
8#include <cstdint>
9#include <gtest/gtest.h>
10#include <vector>
11
12namespace acir_format::tests {
13
14using namespace bb;
15
16class MSMTests : public ::testing::Test {
17 protected:
19};
21
22// Create a simple multi scalar mul with constant/witness inputs
23// constant_point false => witness indexes 4,5,6
24// constant_scalar false => witness indexes 7,8
25MultiScalarMul generate_msm(bool constant_point, bool constant_scalar)
26{
27 MultiScalarMul result;
28 result.out_point_x = 1;
29 result.out_point_y = 2;
30 result.out_point_is_infinite = 3;
31 if (constant_point) {
33 .index = 0,
34 .value = fr(1),
35 .is_constant = true,
36 },
38 .index = 0,
39 .value = fr("0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c"),
40 .is_constant = true,
41 },
43 .index = 0,
44 .value = fr(0),
45 .is_constant = true,
46 } };
47 } else {
49 .index = 4,
50 .value = fr(0),
51 .is_constant = false,
52 },
54 .index = 5,
55 .value = fr(0),
56 .is_constant = false,
57 },
59 .index = 6,
60 .value = fr(0),
61 .is_constant = false,
62 } };
63 }
64 if (constant_scalar) {
66 .index = 0,
67 .value = fr(
68 std::string("0x000000000000000000000000000000000000000000000000000000616c696365")),
69 .is_constant = true,
70 },
72 .index = 0,
73 .value = fr(0),
74 .is_constant = true,
75 } };
76 } else {
78 .index = 7,
79 .value = fr(0),
80 .is_constant = false,
81 },
83 .index = 8,
84 .value = fr(0),
85 .is_constant = false,
86 } };
87 }
88 return result;
89}
90
91// Creates a circuit containing the 'msm_constrain' with the provided witness values
92// Check if the circuit is valid
93// Return (true, true) if the circuit is valid.
94static std::pair<bool, bool> check_msm(MultiScalarMul& msm_constrain, WitnessVector& witness)
95{
96 AcirFormat constraint_system{
97 .varnum = static_cast<uint32_t>(witness.size()),
98 .num_acir_opcodes = 1,
99 .public_inputs = {},
100 .multi_scalar_mul_constraints = { msm_constrain },
101 .original_opcode_indices = create_empty_original_opcode_indices(),
102 };
103 mock_opcode_indices(constraint_system);
104 // The tests need to disable asserts because of tests using bad inputs
105 // that are not on the curve.
107 AcirProgram program{ constraint_system, witness };
108 auto builder = create_circuit(program);
109
111 result.first = CircuitChecker::check(builder);
112 result.second = !builder.failed();
113 info(builder.err());
114 return result;
115}
116
117// These tests are testing a simple MSM constraint with 0 or 1 predicate:
118// TestMSMConstantPredicate: constant inputs, false predicate
119// TestMSMConstant: constant inputs, true predicate
120// TestMSMWitnessPredicate: witness inputs, false predicate
121// TestMSMWitness: witness inputs, true predicate
122// TestMSMConstantBad: bad constant inputes, check_circuit is expected to fail
123// TestMSMConstantPredicateBad: bad constant inputs, false predicate, circuit is expected to succeed
124// TestMSMWitnessPredicateBad: bad witness inputs, false predicate, circuit is expected to succeed
125// TestMSMWitnessBad: bad witness inputs, true predicate, check_circuit is expected to fail
126
131TEST_F(MSMTests, TestMSMConstantPredicate)
132{
133 MultiScalarMul msm_constrain = generate_msm(true, true);
134 WitnessVector witness{
135
136 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
137 fr("0x0bff8247aa94b08d1c680d7a3e10831bd8c8cf2ea2c756b0d1d89acdcad877ad"),
138 fr("0x2a5d7253a6ed48462fedb2d350cc768d13956310f54e73a8a47914f34a34c5c4"),
139 fr(0),
140 };
141 // Create a predicate witness or constant which takes the index of the last witness in the array
142 auto predicate = WitnessOrConstant<fr>::from_index(static_cast<uint32_t>(witness.size()));
143 witness.push_back(fr(0));
144
145 msm_constrain.predicate = predicate;
146 auto check = check_msm(msm_constrain, witness);
147 EXPECT_TRUE(check.first);
148 EXPECT_TRUE(check.second);
149}
150
155TEST_F(MSMTests, TestMSMConstant)
156{
157 MultiScalarMul msm_constrain = generate_msm(true, true);
158 WitnessVector witness{
159
160 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
161 fr("0x0bff8247aa94b08d1c680d7a3e10831bd8c8cf2ea2c756b0d1d89acdcad877ad"),
162 fr("0x2a5d7253a6ed48462fedb2d350cc768d13956310f54e73a8a47914f34a34c5c4"),
163 fr(0),
164 };
165 // Create a predicate witness or constant which takes the index of the last witness in the array
166 auto predicate = WitnessOrConstant<fr>::from_index(static_cast<uint32_t>(witness.size()));
167 witness.push_back(fr(1));
168
169 msm_constrain.predicate = predicate;
170 auto check = check_msm(msm_constrain, witness);
171 EXPECT_TRUE(check.first);
172 EXPECT_TRUE(check.second);
173}
174
175TEST_F(MSMTests, TestMSMWitnessPredicate)
176{
177 MultiScalarMul msm_constrain = generate_msm(false, false);
178 WitnessVector witness{
179 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
180 // output
181 fr("0x0bff8247aa94b08d1c680d7a3e10831bd8c8cf2ea2c756b0d1d89acdcad877ad"),
182 fr("0x2a5d7253a6ed48462fedb2d350cc768d13956310f54e73a8a47914f34a34c5c4"),
183 fr(0),
184 // point
185 fr(1),
186 fr("0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c"),
187 fr(0),
188
189 // scalar
190 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
191 fr(0),
192
193 };
194 // Create a predicate witness or constant which takes the index of the last witness in the array
195 auto predicate = WitnessOrConstant<fr>::from_index(static_cast<uint32_t>(witness.size()));
196 witness.push_back(fr(0));
197 msm_constrain.predicate = predicate;
198 auto check = check_msm(msm_constrain, witness);
199 EXPECT_TRUE(check.first);
200 EXPECT_TRUE(check.second);
201}
202
203TEST_F(MSMTests, TestMSMWitness)
204{
205 MultiScalarMul msm_constrain = generate_msm(false, false);
206 WitnessVector witness{
207 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
208 // output
209 fr("0x0bff8247aa94b08d1c680d7a3e10831bd8c8cf2ea2c756b0d1d89acdcad877ad"),
210 fr("0x2a5d7253a6ed48462fedb2d350cc768d13956310f54e73a8a47914f34a34c5c4"),
211 fr(0),
212 // point
213 fr(1),
214 fr("0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c"),
215 fr(0),
216
217 // scalar
218 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
219 fr(0),
220
221 };
222 // Create a predicate witness or constant which takes the index of the last witness in the array
223 auto predicate = WitnessOrConstant<fr>::from_index(static_cast<uint32_t>(witness.size()));
224 witness.push_back(fr(1));
225 msm_constrain.predicate = predicate;
226 auto check = check_msm(msm_constrain, witness);
227 EXPECT_TRUE(check.first);
228 EXPECT_TRUE(check.second);
229}
230
231TEST_F(MSMTests, TestMSMConstantBad)
232{
233 MultiScalarMul msm_constrain = generate_msm(true, true);
234 WitnessVector witness{
235
236 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
237 fr("0x0bff8247aa94b08d1c680d7a3e10831bd8c8cf2ea2c756b0d1d89acdcad877ad"),
238 fr("0x2a5d7253a6ed48462fedb2d350cc768d13956310f54e73a8a47914f34a34c5c4"),
239 fr(0),
240 };
241 // Create a predicate witness or constant which takes the index of the last witness in the array
242 auto predicate = WitnessOrConstant<fr>::from_index(static_cast<uint32_t>(witness.size()));
243 witness.push_back(fr(1));
244
245 msm_constrain.predicate = predicate;
246 // Modify the MSM inputs to be invalid
247 msm_constrain.points[0].value = fr(0);
248
249 auto check = check_msm(msm_constrain, witness);
250 EXPECT_FALSE(check.first);
251 EXPECT_FALSE(check.second);
252}
253
254TEST_F(MSMTests, TestMSMConstantPredicateBad)
255{
256 MultiScalarMul msm_constrain = generate_msm(true, true);
257 WitnessVector witness{
258
259 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
260 fr("0x0bff8247aa94b08d1c680d7a3e10831bd8c8cf2ea2c756b0d1d89acdcad877ad"),
261 fr("0x2a5d7253a6ed48462fedb2d350cc768d13956310f54e73a8a47914f34a34c5c4"),
262 fr(0),
263 };
264 // Create a predicate witness or constant which takes the index of the last witness in the array
265 auto predicate = WitnessOrConstant<fr>::from_index(static_cast<uint32_t>(witness.size()));
266 witness.push_back(fr(0));
267
268 msm_constrain.predicate = predicate;
269 // Modify the MSM inputs to be invalid
270 msm_constrain.points[0].value = fr(0);
271 msm_constrain.points[1].value = fr(2);
272 auto check = check_msm(msm_constrain, witness);
273 EXPECT_TRUE(check.first);
274 EXPECT_TRUE(check.second);
275}
276
277TEST_F(MSMTests, TestMSMWitnessPredicateBad)
278{
279 MultiScalarMul msm_constrain = generate_msm(false, false);
280 WitnessVector witness{
281 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
282 // output
283 fr("0x0bff8247aa94b08d1c680d7a3e10831bd8c8cf2ea2c756b0d1d89acdcad877ad"),
284 fr("0x2a5d7253a6ed48462fedb2d350cc768d13956310f54e73a8a47914f34a34c5c4"),
285 fr(0),
286 // point
287 fr(1),
288 fr("0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272d"), // bad input
289 fr(0),
290
291 // scalar
292 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
293 fr(0),
294
295 };
296 // Create a predicate witness or constant which takes the index of the last witness in the array
297 auto predicate = WitnessOrConstant<fr>::from_index(static_cast<uint32_t>(witness.size()));
298 witness.push_back(fr(0));
299 msm_constrain.predicate = predicate;
300 auto check = check_msm(msm_constrain, witness);
301 EXPECT_TRUE(check.first);
302 EXPECT_TRUE(check.second);
303}
304
305TEST_F(MSMTests, TestMSMWitnessBad)
306{
307 MultiScalarMul msm_constrain = generate_msm(false, false);
308 WitnessVector witness{
309 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
310 // output
311 fr("0x0bff8247aa94b08d1c680d7a3e10831bd8c8cf2ea2c756b0d1d89acdcad877ad"),
312 fr("0x2a5d7253a6ed48462fedb2d350cc768d13956310f54e73a8a47914f34a34c5c4"),
313 fr(0),
314 // point
315 fr(1),
316 fr("0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272d"), // bad point
317 fr(0),
318
319 // scalar
320 fr("0x000000000000000000000000000000000000000000000000000000616c696365"),
321 fr(0),
322
323 };
324 // Create a predicate witness or constant which takes the index of the last witness in the array
325 auto predicate = WitnessOrConstant<fr>::from_index(static_cast<uint32_t>(witness.size()));
326 witness.push_back(fr(1));
327 msm_constrain.predicate = predicate;
328 auto check = check_msm(msm_constrain, witness);
329 EXPECT_FALSE(check.first);
330 EXPECT_FALSE(check.second);
331}
332
333} // namespace acir_format::tests
acir_format::AcirFormatOriginalOpcodeIndices create_empty_original_opcode_indices()
void mock_opcode_indices(acir_format::AcirFormat &constraint_system)
#define BB_DISABLE_ASSERTS()
Definition assert.hpp:32
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
void info(Args... args)
Definition log.hpp:74
AluTraceBuilder builder
Definition alu.test.cpp:123
field< Bn254FrParams > fr
MultiScalarMul generate_msm(bool constant_point, bool constant_scalar)
UltraCircuitBuilder create_circuit(AcirProgram &program, const ProgramMetadata &metadata)
Specialization for creating an Ultra circuit from an acir program.
bb::SlabVector< bb::fr > WitnessVector
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
Entry point for Barretenberg command-line interface.
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:188
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::vector< WitnessOrConstant< bb::fr > > scalars
WitnessOrConstant< bb::fr > predicate
std::vector< WitnessOrConstant< bb::fr > > points
static WitnessOrConstant from_index(uint32_t index)