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 <gtest/gtest.h>
9#include <vector>
10
11using namespace ::acir_format;
12
13enum class InputConstancy : uint8_t { None, Points, Scalars, Both };
14
24template <typename Builder_, InputConstancy Constancy> class MultiScalarMulTestingFunctions {
25 public:
26 using Builder = Builder_;
27 using AcirConstraint = MultiScalarMul;
30 using FF = bb::fr;
31
33 public:
34 enum class Target : uint8_t {
35 None,
36 Points, // Invalidate point inputs
37 Scalars, // Invalidate scalar inputs
38 Result // Invalidate result output
39 };
40
45
46 static std::vector<std::string> get_labels() { return { "None", "Points", "Scalars", "Result" }; }
47 };
48
49 static void generate_constraints(AcirConstraint& msm_constraint, WitnessVector& witness_values)
50 {
51 // Generate a single point and scalar for simplicity
53 bb::fq scalar_native = bb::fq::random_element();
54 GrumpkinPoint result = point * scalar_native;
55 BB_ASSERT(result != GrumpkinPoint::one()); // Ensure that tampering works correctly
56
57 // Split scalar into low and high limbs (128 bits each) as FF for witness values
58 uint256_t scalar_u256 = uint256_t(scalar_native);
59 FF scalar_lo = scalar_u256.slice(0, 128);
60 FF scalar_hi = scalar_u256.slice(128, 256);
61
62 // Determine which inputs are constants based on the Constancy template parameter
63 constexpr bool points_are_constant = (Constancy == InputConstancy::Points || Constancy == InputConstancy::Both);
64 constexpr bool scalars_are_constant =
65 (Constancy == InputConstancy::Scalars || Constancy == InputConstancy::Both);
66
67 // Helper to add points: either as witnesses or constants based on Constancy
68 auto construct_points = [&]() -> std::vector<WitnessOrConstant<FF>> {
69 if constexpr (points_are_constant) {
70 // Points are constants
71 return { WitnessOrConstant<FF>::from_constant(point.x),
72 WitnessOrConstant<FF>::from_constant(point.y),
73 WitnessOrConstant<FF>::from_constant(point.is_point_at_infinity() ? FF(1) : FF(0)) };
74 }
75 // Points are witnesses
76 std::vector<uint32_t> point_indices = add_to_witness_and_track_indices(witness_values, point);
77 return { WitnessOrConstant<FF>::from_index(point_indices[0]),
78 WitnessOrConstant<FF>::from_index(point_indices[1]),
79 WitnessOrConstant<FF>::from_index(point_indices[2]) };
80 };
81
82 // Helper to add scalars: either as witnesses or constants based on Constancy
83 auto construct_scalars = [&]() -> std::vector<WitnessOrConstant<FF>> {
84 if constexpr (scalars_are_constant) {
85 // Scalars are constants
86 return { WitnessOrConstant<FF>::from_constant(scalar_lo),
87 WitnessOrConstant<FF>::from_constant(scalar_hi) };
88 }
89 // Scalars are witnesses
90 uint32_t scalar_lo_index = static_cast<uint32_t>(witness_values.size());
91 witness_values.emplace_back(scalar_lo);
92 uint32_t scalar_hi_index = static_cast<uint32_t>(witness_values.size());
93 witness_values.emplace_back(scalar_hi);
94 return { WitnessOrConstant<FF>::from_index(scalar_lo_index),
95 WitnessOrConstant<FF>::from_index(scalar_hi_index) };
96 };
97
98 // Add points and scalars according to constancy template parameter
99 auto point_fields = construct_points();
100 auto scalar_fields = construct_scalars();
101
102 // Construct result and predicate as witnesses
103 std::vector<uint32_t> result_indices = add_to_witness_and_track_indices(witness_values, result);
104 uint32_t predicate_index = static_cast<uint32_t>(witness_values.size());
105 witness_values.emplace_back(FF::one()); // predicate
106
107 // Build the constraint
108 msm_constraint = MultiScalarMul{
109 .points = point_fields,
110 .scalars = scalar_fields,
111 .predicate = WitnessOrConstant<FF>::from_index(predicate_index),
112 .out_point_x = result_indices[0],
113 .out_point_y = result_indices[1],
114 .out_point_is_infinite = result_indices[2],
115 };
116 }
117
118 static void invalidate_witness(AcirConstraint& constraint,
119 WitnessVector& witness_values,
120 const InvalidWitness::Target& invalid_witness_target)
121 {
122 switch (invalid_witness_target) {
124 // Invalidate the point by adding 1 to x coordinate
125 if constexpr (Constancy == InputConstancy::None || Constancy == InputConstancy::Scalars) {
126 witness_values[constraint.points[0].index] += bb::fr(1);
127 } else {
128 constraint.points[0] = WitnessOrConstant<FF>::from_constant(constraint.points[0].value + bb::fr(1));
129 }
130 break;
131 }
133 // Invalidate the scalar by adding 1 to the low limb
134 if constexpr (Constancy == InputConstancy::None || Constancy == InputConstancy::Points) {
135 witness_values[constraint.scalars[0].index] += bb::fr(1);
136 } else {
137 constraint.scalars[0] = WitnessOrConstant<FF>::from_constant(constraint.scalars[0].value + bb::fr(1));
138 }
139 break;
140 }
142 // Tamper with the result by setting it to the generator point
143 witness_values[constraint.out_point_x] = GrumpkinPoint::one().x;
144 witness_values[constraint.out_point_y] = GrumpkinPoint::one().y;
145 witness_values[constraint.out_point_is_infinite] = FF::zero();
146 break;
147 }
149 default:
150 break;
151 }
152 };
153};
154
155template <typename Builder>
157 : public ::testing::Test,
158 public TestClassWithPredicate<MultiScalarMulTestingFunctions<Builder, InputConstancy::None>> {
159 protected:
161};
162
163template <typename Builder>
165 : public ::testing::Test,
166 public TestClassWithPredicate<MultiScalarMulTestingFunctions<Builder, InputConstancy::Points>> {
167 protected:
169};
170
171template <typename Builder>
173 : public ::testing::Test,
174 public TestClassWithPredicate<MultiScalarMulTestingFunctions<Builder, InputConstancy::Scalars>> {
175 protected:
177};
178
179template <typename Builder>
181 : public ::testing::Test,
182 public TestClassWithPredicate<MultiScalarMulTestingFunctions<Builder, InputConstancy::Both>> {
183 protected:
185};
186
187using BuilderTypes = testing::Types<UltraCircuitBuilder, MegaCircuitBuilder>;
188
193
195{
197 TestFixture::template test_vk_independence<Flavor>();
198}
199
201{
203 TestFixture::test_constant_true(TestFixture::InvalidWitnessTarget::Result);
204}
205
207{
209 TestFixture::test_witness_true(TestFixture::InvalidWitnessTarget::Result);
210}
211
213{
215 TestFixture::test_witness_false_slow();
216}
217
219{
221 [[maybe_unused]] std::vector<std::string> _ = TestFixture::test_invalid_witnesses();
222}
223
225{
227 TestFixture::template test_vk_independence<Flavor>();
228}
229
231{
233 TestFixture::test_constant_true(TestFixture::InvalidWitnessTarget::Result);
234}
235
237{
239 TestFixture::test_witness_true(TestFixture::InvalidWitnessTarget::Result);
240}
241
243{
245 TestFixture::test_witness_false_slow();
246}
247
249{
251 [[maybe_unused]] std::vector<std::string> _ = TestFixture::test_invalid_witnesses();
252}
253
255{
257 TestFixture::template test_vk_independence<Flavor>();
258}
259
261{
263 TestFixture::test_constant_true(TestFixture::InvalidWitnessTarget::Result);
264}
265
267{
269 TestFixture::test_witness_true(TestFixture::InvalidWitnessTarget::Result);
270}
271
273{
275 TestFixture::test_witness_false_slow();
276}
277
279{
281 [[maybe_unused]] std::vector<std::string> _ = TestFixture::test_invalid_witnesses();
282}
283
285{
287 TestFixture::template test_vk_independence<Flavor>();
288}
289
291{
293 TestFixture::test_constant_true(TestFixture::InvalidWitnessTarget::Result);
294}
295
297{
299 TestFixture::test_witness_true(TestFixture::InvalidWitnessTarget::Result);
300}
301
303{
305 TestFixture::test_witness_false_slow();
306}
307
309{
311 [[maybe_unused]] std::vector<std::string> _ = TestFixture::test_invalid_witnesses();
312}
#define BB_ASSERT(expression,...)
Definition assert.hpp:67
#define BB_DISABLE_ASSERTS()
Definition assert.hpp:32
Testing functions to generate the MultiScalarMul test suite. Constancy specifies which inputs to the ...
static void invalidate_witness(AcirConstraint &constraint, WitnessVector &witness_values, const InvalidWitness::Target &invalid_witness_target)
static void generate_constraints(AcirConstraint &msm_constraint, WitnessVector &witness_values)
constexpr bool is_point_at_infinity() const noexcept
static affine_element random_element(numeric::RNG *engine=nullptr) noexcept
Samples a random point on the curve.
static constexpr affine_element one() noexcept
group class. Represents an elliptic curve group element. Group is parametrised by Fq and Fr
Definition group.hpp:36
group_elements::affine_element< Fq, Fr, Params > affine_element
Definition group.hpp:42
constexpr uint256_t slice(uint64_t start, uint64_t end) const
TYPED_TEST(MultiScalarMulTestsNoneConstant, GenerateVKFromConstraints)
TYPED_TEST_SUITE(MultiScalarMulTestsNoneConstant, BuilderTypes)
bb::group< bb::fr, bb::fq, G1Params > g1
Definition grumpkin.hpp:45
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
field< Bn254FrParams > fr
Definition fr.hpp:174
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
::testing::Types< UltraCircuitBuilder, MegaCircuitBuilder > BuilderTypes
static constexpr field one()
static field random_element(numeric::RNG *engine=nullptr) noexcept
static constexpr field zero()