7#include <gtest/gtest.h>
45 static std::vector<std::string>
get_labels() {
return {
"None",
"Points",
"Scalars",
"Result" }; }
60 FF scalar_lo = scalar_u256.
slice(0, 128);
61 FF scalar_hi = scalar_u256.
slice(128, 256);
65 constexpr bool scalars_are_constant =
70 auto construct_points = [&]() -> std::vector<WitnessOrConstant<FF>> {
71 if constexpr (points_are_constant) {
72 return { WitnessOrConstant<FF>::from_constant(point.
x), WitnessOrConstant<FF>::from_constant(point.
y) };
74 std::vector<uint32_t> point_indices = add_to_witness_and_track_indices(witness_values, point);
75 return { WitnessOrConstant<FF>::from_index(point_indices[0]),
76 WitnessOrConstant<FF>::from_index(point_indices[1]) };
80 auto construct_scalars = [&]() -> std::vector<WitnessOrConstant<FF>> {
81 if constexpr (scalars_are_constant) {
83 return { WitnessOrConstant<FF>::from_constant(scalar_lo),
84 WitnessOrConstant<FF>::from_constant(scalar_hi) };
87 uint32_t scalar_lo_index =
static_cast<uint32_t
>(witness_values.size());
88 witness_values.emplace_back(scalar_lo);
89 uint32_t scalar_hi_index =
static_cast<uint32_t
>(witness_values.size());
90 witness_values.emplace_back(scalar_hi);
91 return { WitnessOrConstant<FF>::from_index(scalar_lo_index),
92 WitnessOrConstant<FF>::from_index(scalar_hi_index) };
96 auto point_fields = construct_points();
97 auto scalar_fields = construct_scalars();
100 std::vector<uint32_t> result_indices = add_to_witness_and_track_indices(witness_values, result);
101 uint32_t predicate_index =
static_cast<uint32_t
>(witness_values.size());
102 witness_values.emplace_back(
FF::one());
105 msm_constraint = MultiScalarMul{
106 .points = point_fields,
107 .scalars = scalar_fields,
108 .predicate = WitnessOrConstant<FF>::from_index(predicate_index),
109 .out_point_x = result_indices[0],
110 .out_point_y = result_indices[1],
117 switch (invalid_witness_target) {
121 witness_values[constraint.points[0].index] +=
bb::fr(1);
123 constraint.points[0] = WitnessOrConstant<FF>::from_constant(constraint.points[0].value +
bb::fr(1));
130 witness_values[constraint.scalars[0].index] +=
bb::fr(1);
132 constraint.scalars[0] = WitnessOrConstant<FF>::from_constant(constraint.scalars[0].value +
bb::fr(1));
147 return { constraint, witness_values };
151template <
typename Builder>
153 :
public ::testing::Test,
154 public TestClassWithPredicate<MultiScalarMulTestingFunctions<Builder, InputConstancy::None>> {
159template <
typename Builder>
161 :
public ::testing::Test,
162 public TestClassWithPredicate<MultiScalarMulTestingFunctions<Builder, InputConstancy::Points>> {
167template <
typename Builder>
169 :
public ::testing::Test,
170 public TestClassWithPredicate<MultiScalarMulTestingFunctions<Builder, InputConstancy::Scalars>> {
175template <
typename Builder>
177 :
public ::testing::Test,
178 public TestClassWithPredicate<MultiScalarMulTestingFunctions<Builder, InputConstancy::Both>> {
183using BuilderTypes = testing::Types<UltraCircuitBuilder, MegaCircuitBuilder>;
193 TestFixture::template test_vk_independence<Flavor>();
199 TestFixture::test_constant_true(TestFixture::InvalidWitnessTarget::Result);
205 TestFixture::test_witness_true(TestFixture::InvalidWitnessTarget::Result);
211 TestFixture::test_witness_false_slow();
217 [[maybe_unused]] std::vector<std::string> _ = TestFixture::test_invalid_witnesses();
223 TestFixture::template test_vk_independence<Flavor>();
229 TestFixture::test_constant_true(TestFixture::InvalidWitnessTarget::Result);
235 TestFixture::test_witness_true(TestFixture::InvalidWitnessTarget::Result);
241 TestFixture::test_witness_false_slow();
247 [[maybe_unused]] std::vector<std::string> _ = TestFixture::test_invalid_witnesses();
253 TestFixture::template test_vk_independence<Flavor>();
259 TestFixture::test_constant_true(TestFixture::InvalidWitnessTarget::Result);
265 TestFixture::test_witness_true(TestFixture::InvalidWitnessTarget::Result);
271 TestFixture::test_witness_false_slow();
277 [[maybe_unused]] std::vector<std::string> _ = TestFixture::test_invalid_witnesses();
283 TestFixture::template test_vk_independence<Flavor>();
289 TestFixture::test_constant_true(TestFixture::InvalidWitnessTarget::Result);
295 TestFixture::test_witness_true(TestFixture::InvalidWitnessTarget::Result);
301 TestFixture::test_witness_false_slow();
307 [[maybe_unused]] std::vector<std::string> _ = TestFixture::test_invalid_witnesses();
330 return { u.
slice(0, 128), u.
slice(128, 256) };
343 uint32_t xi =
static_cast<uint32_t
>(witness.size());
344 witness.emplace_back(pt.
x);
345 uint32_t yi =
static_cast<uint32_t
>(witness.size());
346 witness.emplace_back(pt.
y);
353 uint32_t lo_idx =
static_cast<uint32_t
>(witness.size());
354 witness.emplace_back(s.
lo);
355 uint32_t hi_idx =
static_cast<uint32_t
>(witness.size());
356 witness.emplace_back(s.
hi);
357 return { lo_idx, hi_idx };
364 WitnessVector witness;
368 uint32_t pred_idx =
static_cast<uint32_t
>(witness.size());
369 witness.emplace_back(
MsmFF(1));
372 .points = { WitnessOrConstant<MsmFF>::from_index(p[0]), WitnessOrConstant<MsmFF>::from_index(p[1]) },
373 .scalars = { WitnessOrConstant<MsmFF>::from_index(s[0]), WitnessOrConstant<MsmFF>::from_index(s[1]) },
374 .predicate = WitnessOrConstant<MsmFF>::from_index(pred_idx),
378 return { c, witness };
384 AcirFormat cs = constraint_to_acir_format(constraint);
385 AcirProgram program{ cs, witness };
386 auto builder = create_circuit<Builder>(program, ProgramMetadata{});
401 auto [constraint, witness] =
404 auto [ok, err] = TestFixture::run_circuit(constraint, witness);
405 EXPECT_TRUE(ok) <<
"0 * P = infinity should produce a valid circuit";
443 auto [constraint, witness] = TestFixture::make_msm(
446 auto [ok, err] = TestFixture::run_circuit(constraint, witness);
447 EXPECT_FALSE(ok) <<
"scalar == Grumpkin scalar modulus must not produce a satisfiable circuit";
457 msm_scalar_from_u256(grumpkin_scalar_modulus +
uint256_t(1)),
460 auto [ok, err] = TestFixture::run_circuit(constraint, witness);
461 EXPECT_FALSE(ok) <<
"scalar == Grumpkin scalar modulus + 1 must not produce a satisfiable circuit";
473 msm_scalar_from_u256(grumpkin_scalar_modulus -
uint256_t(1)),
476 auto [ok, err] = TestFixture::run_circuit(constraint, witness);
477 EXPECT_TRUE(ok) <<
"scalar == Grumpkin scalar modulus - 1 (largest in-field scalar) should prove. err: " << err;
489 auto [constraint, witness] = TestFixture::make_msm(
492 auto [ok, err] = TestFixture::run_circuit(constraint, witness);
493 EXPECT_FALSE(ok) <<
"scalar == 2^254 - 1 (> Grumpkin modulus) must not produce a satisfiable circuit";
505 auto [constraint, witness] =
508 auto [ok, err] = TestFixture::run_circuit(constraint, witness);
509 EXPECT_FALSE(ok) <<
"scalar hi limb of 127 bits (value 2^254) must not produce a satisfiable circuit";
524 auto [constraint, witness] = TestFixture::make_msm(
526 auto [ok, err] = TestFixture::run_circuit(constraint, witness);
527 EXPECT_TRUE(ok) <<
"canonical scalar should prove the MSM result. err: " << err;
533 msm_scalar_from_u256(
uint256_t(5) + grumpkin_scalar_modulus),
535 auto [ok, err] = TestFixture::run_circuit(constraint, witness);
536 EXPECT_FALSE(ok) <<
"scalar s + r must not reprove the output of scalar s";
#define BB_ASSERT(expression,...)
#define BB_DISABLE_ASSERTS()
static std::pair< bool, std::string > run_circuit(MultiScalarMul constraint, WitnessVector witness)
static void SetUpTestSuite()
static std::array< uint32_t, 2 > push_scalar(WitnessVector &witness, const MsmScalar &s)
static std::pair< MultiScalarMul, WitnessVector > make_msm(MsmAcirPoint point, MsmScalar scalar, MsmAcirPoint result)
static std::array< uint32_t, 2 > push_point(WitnessVector &witness, const MsmAcirPoint &pt)
static std::vector< Target > get_all()
static std::vector< std::string > get_labels()
Testing functions to generate the MultiScalarMul test suite. Constancy specifies which inputs to the ...
static ProgramMetadata generate_metadata()
static void generate_constraints(AcirConstraint &msm_constraint, WitnessVector &witness_values)
MultiScalarMul AcirConstraint
static std::pair< AcirConstraint, WitnessVector > invalidate_witness(AcirConstraint constraint, WitnessVector witness_values, const InvalidWitness::Target &invalid_witness_target)
static void SetUpTestSuite()
static void SetUpTestSuite()
static void SetUpTestSuite()
static void SetUpTestSuite()
static bool check(const Builder &circuit)
Check the witness satisifies the circuit.
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
group_elements::affine_element< Fq, Fr, Params > affine_element
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
std::filesystem::path bb_crs_path()
void init_file_crs_factory(const std::filesystem::path &path)
field< Bn254FqParams > fq
field< Bn254FrParams > fr
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
::testing::Types< UltraCircuitBuilder, MegaCircuitBuilder > BuilderTypes
static MsmAcirPoint infinity()
static MsmAcirPoint from_native(const MsmGrumpkinPoint &p)
static MsmScalar from_native(const bb::fq &s)
static constexpr field one()
static constexpr uint256_t modulus
static field random_element(numeric::RNG *engine=nullptr) noexcept