Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle properly invalid witness assignment in ec add #7690

Merged
merged 3 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,12 @@ void create_ec_add_constraint(Builder& builder, const EcAdd& input, bool has_val
{
// Input to cycle_group points
using cycle_group_ct = bb::stdlib::cycle_group<Builder>;
using bool_ct = bb::stdlib::bool_t<Builder>;

auto x1 = to_field_ct(input.input1_x, builder);
auto y1 = to_field_ct(input.input1_y, builder);
auto x2 = to_field_ct(input.input2_x, builder);
auto input1_point = to_grumpkin_point(
input.input1_x, input.input1_y, input.input1_infinite, has_valid_witness_assignments, builder);
auto input2_point = to_grumpkin_point(
input.input2_x, input.input2_y, input.input2_infinite, has_valid_witness_assignments, builder);

auto y2 = to_field_ct(input.input2_y, builder);

auto infinite1 = bool_ct(to_field_ct(input.input1_infinite, builder));

auto infinite2 = bool_ct(to_field_ct(input.input2_infinite, builder));

if (!has_valid_witness_assignments) {
auto g1 = bb::grumpkin::g1::affine_one;
// We need to have correct values representing points on the curve
if (!x1.is_constant()) {
builder.variables[x1.witness_index] = g1.x;
}
if (!y1.is_constant()) {
builder.variables[y1.witness_index] = g1.y;
}
if (!infinite1.is_constant()) {
builder.variables[infinite1.witness_index] = bb::fr(0);
}
if (!x2.is_constant()) {
builder.variables[x2.witness_index] = g1.x;
}
if (!y2.is_constant()) {
builder.variables[y2.witness_index] = g1.y;
}
if (!infinite2.is_constant()) {
builder.variables[infinite2.witness_index] = bb::fr(0);
}
}
cycle_group_ct input1_point(x1, y1, infinite1);
cycle_group_ct input2_point(x2, y2, infinite2);
// Addition
cycle_group_ct result = input1_point + input2_point;
cycle_group_ct standard_result = result.get_standard_form();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,50 +18,18 @@ void create_multi_scalar_mul_constraint(Builder& builder,
using cycle_group_ct = stdlib::cycle_group<Builder>;
using cycle_scalar_ct = typename stdlib::cycle_group<Builder>::cycle_scalar;
using field_ct = stdlib::field_t<Builder>;
using bool_ct = stdlib::bool_t<Builder>;

std::vector<cycle_group_ct> points;
std::vector<cycle_scalar_ct> scalars;

for (size_t i = 0; i < input.points.size(); i += 3) {
// Instantiate the input point/variable base as `cycle_group_ct`
field_ct point_x;
field_ct point_y;
bool_ct infinite;
cycle_group_ct input_point = to_grumpkin_point(
input.points[i], input.points[i + 1], input.points[i + 2], has_valid_witness_assignments, builder);

point_x = to_field_ct(input.points[i], builder);
point_y = to_field_ct(input.points[i + 1], builder);
infinite = bool_ct(to_field_ct(input.points[i + 2], builder));

// When we do not have the witness assignments, we set is_infinite value to true if it is not constant
// else default values would give a point which is not on the curve and this will fail verification
if (!has_valid_witness_assignments) {
if (!input.points[i + 2].is_constant) {
builder.variables[input.points[i + 2].index] = fr(1);
} else if (input.points[i + 2].value == fr::zero() &&
!(input.points[i].is_constant || input.points[i + 1].is_constant)) {
// else, if is_infinite is false, but the coordinates (x, y) are witness
// then we set their value so to a curve point.
auto g1 = bb::grumpkin::g1::affine_one;
builder.variables[input.points[i].index] = g1.x;
builder.variables[input.points[i + 1].index] = g1.y;
}
}

cycle_group_ct input_point(point_x, point_y, infinite);
// Reconstruct the scalar from the low and high limbs
field_ct scalar_low_as_field;
field_ct scalar_high_as_field;
if (input.scalars[2 * (i / 3)].is_constant) {
scalar_low_as_field = field_ct(input.scalars[2 * (i / 3)].value);
} else {
scalar_low_as_field = field_ct::from_witness_index(&builder, input.scalars[2 * (i / 3)].index);
}
if (input.scalars[2 * (i / 3) + 1].is_constant) {
scalar_high_as_field = field_ct(input.scalars[2 * (i / 3) + 1].value);
} else {
scalar_high_as_field = field_ct::from_witness_index(&builder, input.scalars[2 * (i / 3) + 1].index);
}
// Reconstruct the scalar from the low and high limbs
field_ct scalar_low_as_field = to_field_ct(input.scalars[2 * (i / 3)], builder);
field_ct scalar_high_as_field = to_field_ct(input.scalars[2 * (i / 3) + 1], builder);
cycle_scalar_ct scalar(scalar_low_as_field, scalar_high_as_field);

// Add the point and scalar to the vectors
Expand All @@ -70,6 +38,7 @@ void create_multi_scalar_mul_constraint(Builder& builder,
}
// Call batch_mul to multiply the points and scalars and sum the results
auto output_point = cycle_group_ct::batch_mul(points, scalars).get_standard_form();

// Add the constraints and handle constant values
if (output_point.is_point_at_infinity().is_constant()) {
builder.fix_witness(input.out_point_is_infinite, output_point.is_point_at_infinity().get_value());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "witness_constant.hpp"
#include "barretenberg/ecc/curves/bn254/fr.hpp"

namespace acir_format {

using namespace bb;
using namespace bb::stdlib;
template <typename Builder, typename FF>
bb::stdlib::cycle_group<Builder> to_grumpkin_point(const WitnessOrConstant<FF>& input_x,
const WitnessOrConstant<FF>& input_y,
const WitnessOrConstant<FF>& input_infinite,
bool has_valid_witness_assignments,
Builder& builder)
{
using bool_ct = bb::stdlib::bool_t<Builder>;
auto point_x = to_field_ct(input_x, builder);
auto point_y = to_field_ct(input_y, builder);
auto infinite = bool_ct(to_field_ct(input_infinite, builder));

// When we do not have the witness assignments, we set is_infinite value to true if it is not constant
// else default values would give a point which is not on the curve and this will fail verification
if (!has_valid_witness_assignments) {
if (!input_infinite.is_constant) {
builder.variables[input_infinite.index] = fr(1);
} else if (input_infinite.value == fr::zero() && !(input_x.is_constant || input_y.is_constant)) {
// else, if is_infinite is false, but the coordinates (x, y) are witness (and not constant)
// then we set their value to an arbitrary valid curve point (in our case G1).
auto g1 = bb::grumpkin::g1::affine_one;
builder.variables[input_x.index] = g1.x;
builder.variables[input_y.index] = g1.y;
}
}
cycle_group<Builder> input_point(point_x, point_y, infinite);
return input_point;
}

template bb::stdlib::cycle_group<UltraCircuitBuilder> to_grumpkin_point(const WitnessOrConstant<fr>& input_x,
const WitnessOrConstant<fr>& input_y,
const WitnessOrConstant<fr>& input_infinite,
bool has_valid_witness_assignments,
UltraCircuitBuilder& builder);
template bb::stdlib::cycle_group<MegaCircuitBuilder> to_grumpkin_point(const WitnessOrConstant<fr>& input_x,
const WitnessOrConstant<fr>& input_y,
const WitnessOrConstant<fr>& input_infinite,
bool has_valid_witness_assignments,
MegaCircuitBuilder& builder);

} // namespace acir_format
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once
#include "barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp"
#include "barretenberg/serialize/msgpack.hpp"
#include "barretenberg/stdlib/primitives/field/field.hpp"
#include "barretenberg/stdlib/primitives/group/cycle_group.hpp"

namespace acir_format {
template <typename FF> struct WitnessOrConstant {
Expand Down Expand Up @@ -30,4 +32,11 @@ bb::stdlib::field_t<Builder> to_field_ct(const WitnessOrConstant<FF>& input, Bui
return field_ct::from_witness_index(&builder, input.index);
}

template <typename Builder, typename FF>
bb::stdlib::cycle_group<Builder> to_grumpkin_point(const WitnessOrConstant<FF>& input_x,
const WitnessOrConstant<FF>& input_y,
const WitnessOrConstant<FF>& input_infinite,
bool has_valid_witness_assignments,
Builder& builder);

} // namespace acir_format
Loading