Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,11 @@ TEST_F(BoomerangGoblinRecursiveVerifierTests, graph_description_basic)
ASSERT_TRUE(verified);
}
auto translator_pairing_points = output.points_accumulator;
translator_pairing_points.P0.x.fix_witness();
translator_pairing_points.P0.y.fix_witness();
translator_pairing_points.P1.x.fix_witness();
translator_pairing_points.P1.y.fix_witness();
// BIGGROUP_AUDITTODO: mutable accessor needed for fix_witness()
translator_pairing_points.P0.x().fix_witness();
translator_pairing_points.P0.y().fix_witness();
translator_pairing_points.P1.x().fix_witness();
translator_pairing_points.P1.y().fix_witness();
info("Recursive Verifier: num gates = ", builder.num_gates());
auto graph = cdg::StaticAnalyzer(builder, false);
auto variables_in_one_gate = graph.get_variables_in_one_gate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,11 @@ template <typename RecursiveFlavor> class BoomerangRecursiveVerifierTest : publi
StdlibProof stdlib_inner_proof(outer_circuit, inner_proof);
VerifierOutput output = verifier.template verify_proof<DefaultIO<OuterBuilder>>(stdlib_inner_proof);
PairingObject pairing_points = output.points_accumulator;
pairing_points.P0.x.fix_witness();
pairing_points.P0.y.fix_witness();
pairing_points.P1.x.fix_witness();
pairing_points.P1.y.fix_witness();
// BIGGROUP_AUDITTODO: mutable accessor needed for fix_witness()
pairing_points.P0.x().fix_witness();
pairing_points.P0.y().fix_witness();
pairing_points.P1.x().fix_witness();
pairing_points.P1.y().fix_witness();
if constexpr (HasIPAAccumulator<OuterFlavor>) {
output.ipa_claim.set_public();
outer_circuit.ipa_proof = output.ipa_proof.get_value();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,10 @@ bool_t<Builder> ecdsa_verify_signature(const stdlib::byte_array<Builder>& hashed
Fr z(hashed_message);

// Step 1.
public_key.x.assert_is_in_field(
// BIGGROUP_AUDITTODO: mutable accessor needed for assert_is_in_field()
public_key.x().assert_is_in_field(
"ECDSA input validation: the x coordinate of the public key is bigger than the base field modulus."); // x < q
public_key.y.assert_is_in_field(
public_key.y().assert_is_in_field(
"ECDSA input validation: the y coordinate of the public key is bigger than the base field modulus."); // y < q

// Step 2.
Expand Down Expand Up @@ -137,21 +138,22 @@ bool_t<Builder> ecdsa_verify_signature(const stdlib::byte_array<Builder>& hashed
bool_t<Builder>(false), "ECDSA validation: the result of the batch multiplication is the point at infinity.");

// Step 8.
// We reduce result.x to 2^s, where s is the smallest s.t. 2^s > q. It is cheap in terms of constraints, and avoids
// possible edge cases
result.x.self_reduce();

// Transfer Fq value result.x to Fr (this is just moving from a C++ class to another)
Fr result_x_mod_r = Fr::unsafe_construct_from_limbs(result.x.binary_basis_limbs[0].element,
result.x.binary_basis_limbs[1].element,
result.x.binary_basis_limbs[2].element,
result.x.binary_basis_limbs[3].element);
// We reduce result.x() to 2^s, where s is the smallest s.t. 2^s > q. It is cheap in terms of constraints, and
// avoids possible edge cases
// BIGGROUP_AUDITTODO: mutable accessor needed for self_reduce()
result.x().self_reduce();

// Transfer Fq value result.x() to Fr (this is just moving from a C++ class to another)
Fr result_x_mod_r = Fr::unsafe_construct_from_limbs(result.x().binary_basis_limbs[0].element,
result.x().binary_basis_limbs[1].element,
result.x().binary_basis_limbs[2].element,
result.x().binary_basis_limbs[3].element);
// Copy maximum limb values from Fq to Fr: this is needed by the subtraction happening in the == operator
for (size_t idx = 0; idx < 4; idx++) {
result_x_mod_r.binary_basis_limbs[idx].maximum_value = result.x.binary_basis_limbs[idx].maximum_value;
result_x_mod_r.binary_basis_limbs[idx].maximum_value = result.x().binary_basis_limbs[idx].maximum_value;
}

// Check result.x = r mod n
// Check result.x() = r mod n
bool_t<Builder> is_signature_valid = result_x_mod_r == r;

// Logging
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
element val(native_val);
size_t idx = 0;
std::array<fr, PUBLIC_INPUTS_SIZE> limb_vals;
for (auto& limb : val.x.binary_basis_limbs) {
for (auto& limb : val._x.binary_basis_limbs) {
limb_vals[idx++] = limb.element.get_value();
}
for (auto& limb : val.y.binary_basis_limbs) {
for (auto& limb : val._y.binary_basis_limbs) {
limb_vals[idx++] = limb.element.get_value();
}
BB_ASSERT_EQ(idx, PUBLIC_INPUTS_SIZE);
Expand All @@ -82,8 +82,8 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
*/
uint32_t set_public() const
{
const uint32_t start_idx = x.set_public();
y.set_public();
const uint32_t start_idx = _x.set_public();
_y.set_public();

return start_idx;
}
Expand Down Expand Up @@ -117,13 +117,13 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
if (input.is_point_at_infinity()) {
Fq x = Fq::from_witness(ctx, NativeGroup::affine_one.x);
Fq y = Fq::from_witness(ctx, NativeGroup::affine_one.y);
out.x = x;
out.y = y;
out._x = x;
out._y = y;
} else {
Fq x = Fq::from_witness(ctx, input.x);
Fq y = Fq::from_witness(ctx, input.y);
out.x = x;
out.y = y;
out._x = x;
out._y = y;
}
out.set_point_at_infinity(witness_ct(ctx, input.is_point_at_infinity()));

Expand All @@ -141,17 +141,20 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
bool has_circuit_failed = get_context()->failed();

Fq b(get_context(), uint256_t(NativeGroup::curve_b));
Fq _b = Fq::conditional_assign(is_point_at_infinity(), Fq::zero(), b);
Fq _x = Fq::conditional_assign(is_point_at_infinity(), Fq::zero(), x);
Fq _y = Fq::conditional_assign(is_point_at_infinity(), Fq::zero(), y);
Fq adjusted_b = Fq::conditional_assign(is_point_at_infinity(), Fq::zero(), b);
Fq adjusted_x = Fq::conditional_assign(is_point_at_infinity(), Fq::zero(), _x);
Fq adjusted_y = Fq::conditional_assign(is_point_at_infinity(), Fq::zero(), _y);
if constexpr (!NativeGroup::has_a) {
// we validate y^2 = x^3 + b by setting "fix_remainder_zero = true" when calling mult_madd
Fq::mult_madd({ _x.sqr(), _y }, { _x, -_y }, { _b }, true);
Fq::mult_madd({ adjusted_x.sqr(), adjusted_y }, { adjusted_x, -adjusted_y }, { adjusted_b }, true);
} else {
Fq a(get_context(), uint256_t(NativeGroup::curve_a));
Fq _a = Fq::conditional_assign(is_point_at_infinity(), Fq::zero(), a);
Fq adjusted_a = Fq::conditional_assign(is_point_at_infinity(), Fq::zero(), a);
// we validate y^2 = x^3 + ax + b by setting "fix_remainder_zero = true" when calling mult_madd
Fq::mult_madd({ _x.sqr(), _x, _y }, { _x, _a, -_y }, { _b }, true);
Fq::mult_madd({ adjusted_x.sqr(), adjusted_x, adjusted_y },
{ adjusted_x, adjusted_a, -adjusted_y },
{ adjusted_b },
true);
}

if ((!has_circuit_failed) && (get_context()->failed())) {
Expand All @@ -165,8 +168,8 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
**/
void convert_constant_to_fixed_witness(Builder* builder)
{
this->x.convert_constant_to_fixed_witness(builder);
this->y.convert_constant_to_fixed_witness(builder);
this->_x.convert_constant_to_fixed_witness(builder);
this->_y.convert_constant_to_fixed_witness(builder);
// Origin tags should be unset after fixing the witness
unset_free_witness_tag();
}
Expand All @@ -177,8 +180,8 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
void fix_witness()
{
// Origin tags should be updated within
this->x.fix_witness();
this->y.fix_witness();
this->_x.fix_witness();
this->_y.fix_witness();

// This is now effectively a constant
unset_free_witness_tag();
Expand Down Expand Up @@ -218,8 +221,8 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
byte_array<Builder> to_byte_array() const
{
byte_array<Builder> result(get_context());
result.write(y.to_byte_array());
result.write(x.to_byte_array());
result.write(_y.to_byte_array());
result.write(_x.to_byte_array());
return result;
}

Expand All @@ -231,7 +234,7 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
element operator-() const
{
element result(*this);
result.y = -result.y;
result._y = -result._y;
return result;
}
element operator+=(const element& other)
Expand All @@ -251,7 +254,7 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
element conditional_negate(const bool_ct& predicate) const
{
element result(*this);
result.y = result.y.conditional_negate(predicate);
result._y = result._y.conditional_negate(predicate);
return result;
}

Expand All @@ -277,8 +280,8 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
BB_ASSERT_NEQ(ctx, nullptr, "biggroup::conditional_select must have a context");

element result(*this);
result.x = result.x.conditional_select(other.x, predicate);
result.y = result.y.conditional_select(other.y, predicate);
result._x = result._x.conditional_select(other._x, predicate);
result._y = result._y.conditional_select(other._y, predicate);
result._is_infinity =
bool_ct::conditional_assign(predicate, other.is_point_at_infinity(), result.is_point_at_infinity());
return result;
Expand All @@ -298,24 +301,24 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
const std::string msg = "biggroup::incomplete_assert_equal") const
{
is_point_at_infinity().assert_equal(other.is_point_at_infinity(), msg + " (infinity flag)");
x.assert_equal(other.x, msg + " (x coordinate)");
y.assert_equal(other.y, msg + " (y coordinate)");
_x.assert_equal(other._x, msg + " (x coordinate)");
_y.assert_equal(other._y, msg + " (y coordinate)");
}

element normalize() const
{
element result(*this);
result.x.reduce_mod_target_modulus();
result.y.reduce_mod_target_modulus();
result._x.reduce_mod_target_modulus();
result._y.reduce_mod_target_modulus();
return result;
}
element scalar_mul(const Fr& scalar, const size_t max_num_bits = 0) const;

element reduce() const
{
element result(*this);
result.x.self_reduce();
result.y.self_reduce();
result._x.self_reduce();
result._y.self_reduce();
return result;
}

Expand All @@ -334,8 +337,8 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {

chain_add_accumulator() = default;
explicit chain_add_accumulator(const element& input)
: x3_prev(input.x)
, y3_prev(input.y)
: x3_prev(input._x)
, y3_prev(input._y)
, is_element(true)
{}
chain_add_accumulator(const chain_add_accumulator& other) = default;
Expand All @@ -358,8 +361,8 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {

typename NativeGroup::affine_element get_value() const
{
uint512_t x_val = x.get_value() % Fq::modulus_u512;
uint512_t y_val = y.get_value() % Fq::modulus_u512;
uint512_t x_val = _x.get_value() % Fq::modulus_u512;
uint512_t y_val = _y.get_value() % Fq::modulus_u512;
auto result = typename NativeGroup::affine_element(x_val.lo, y_val.lo);
if (is_point_at_infinity().get_value()) {
result.self_set_infinity();
Expand Down Expand Up @@ -388,32 +391,39 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {

Builder* get_context() const
{
if (x.context != nullptr) {
return x.context;
if (_x.context != nullptr) {
return _x.context;
}
if (y.context != nullptr) {
return y.context;
if (_y.context != nullptr) {
return _y.context;
}
return nullptr;
}

Builder* get_context(const element& other) const
{
if (x.context != nullptr) {
return x.context;
if (_x.context != nullptr) {
return _x.context;
}
if (y.context != nullptr) {
return y.context;
if (_y.context != nullptr) {
return _y.context;
}
if (other.x.context != nullptr) {
return other.x.context;
if (other._x.context != nullptr) {
return other._x.context;
}
if (other.y.context != nullptr) {
return other.y.context;
if (other._y.context != nullptr) {
return other._y.context;
}
return nullptr;
}

// Coordinate accessors (non-owning, const reference)
const Fq& x() const { return _x; }
const Fq& y() const { return _y; }
// Non-const accessors for internal use (e.g., fix_witness in tests)
Fq& x() { return _x; }
Fq& y() { return _y; }

bool_ct is_point_at_infinity() const { return _is_infinity; }
void set_point_at_infinity(const bool_ct& is_infinity, const bool& add_to_used_witnesses = false)
{
Expand All @@ -426,23 +436,23 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {

void set_origin_tag(OriginTag tag) const
{
x.set_origin_tag(tag);
y.set_origin_tag(tag);
_x.set_origin_tag(tag);
_y.set_origin_tag(tag);
_is_infinity.set_origin_tag(tag);
}

OriginTag get_origin_tag() const
{
return OriginTag(x.get_origin_tag(), y.get_origin_tag(), _is_infinity.get_origin_tag());
return OriginTag(_x.get_origin_tag(), _y.get_origin_tag(), _is_infinity.get_origin_tag());
}

/**
* @brief Unset the free witness flag for the element's tags
*/
void unset_free_witness_tag()
{
x.unset_free_witness_tag();
y.unset_free_witness_tag();
_x.unset_free_witness_tag();
_y.unset_free_witness_tag();
_is_infinity.unset_free_witness_tag();
}

Expand All @@ -451,18 +461,17 @@ template <class Builder_, class Fq, class Fr, class NativeGroup> class element {
*/
void set_free_witness_tag()
{
x.set_free_witness_tag();
y.set_free_witness_tag();
_x.set_free_witness_tag();
_y.set_free_witness_tag();
_is_infinity.set_free_witness_tag();
}

Fq x;
Fq y;

// For testing purposes only
friend class element_test_accessor;

private:
Fq _x;
Fq _y;
bool_ct _is_infinity;

/**
Expand Down Expand Up @@ -968,7 +977,7 @@ class element_test_accessor {
template <typename C, typename Fq, typename Fr, typename G>
inline std::ostream& operator<<(std::ostream& os, element<C, Fq, Fr, G> const& v)
{
return os << "{ " << v.x << " , " << v.y << " }";
return os << "{ " << v._x << " , " << v._y << " }";
}
} // namespace bb::stdlib::element_default

Expand Down
Loading