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

Complete add for AffineGagdet + fix serialization to field elements #172

Closed
wants to merge 5 commits into from

Conversation

nicholas-mainardi
Copy link

@nicholas-mainardi nicholas-mainardi commented Feb 22, 2022

This PR partially addresses issue #36 (partially #125 too), providing a first implementation for complete addition for the AffineGadget, both for Jacobian and Projective curves. The algorithm is based on the zcash solution for complete arithmetic over weierstrass curves. Nonetheless, although the zcash solution works for weierstrass curves of prime order with a=0 (i.e., y^2 = x^3+b), the algorithm implemented in this PR should work for generic weierstrass curves of prime order (i.e., y^2 = x^3+ax+b), without increasing the number of constraints. Note that the algorithm requires to represent infinity point as (0,0) rather than (0,1), which was the conventional representation previously employed in the AffineGadget.

Besides that, this PR addresses an inconsistency bug between the serialization to field elements of the infinity point between the AffineGadget and the underlying Jacobian/Projective curves. The serialization of the infinity point in such curves is changed to always serialize the affine point (0,0), which is never in the curve unless b=0 (which however is quite unlikely to be ever needed in our case as it means that the curve has non-prime order).

Copy link
Collaborator

@DanieleDiBenedetto DanieleDiBenedetto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine for me. Let's just remember that changing the zero representation for the gadget might affect some dependent circuits (must check that)

@@ -125,6 +126,60 @@ impl<F: PrimeField> FpGadget<F> {
}
}

impl<F: PrimeField> TryInto<Boolean> for FpGadget<F> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's write a comment saying explicitly that this is intended to be used when we are sure that the 'self' FpGadget cannot have other values than 0 or 1 (for instance, because enforced by other constraints); i.e. this function doesn't explicitly enforce 'self' being 0 or 1 with the usual Boolean constraint.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. It was not completely what this function should do.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will add a detailed comment

@DanieleDiBenedetto DanieleDiBenedetto requested review from DDT92 and removed request for UlrichHaboeck75 March 30, 2022 08:18
algebra/src/to_field_vec.rs Show resolved Hide resolved
algebra/src/to_field_vec.rs Show resolved Hide resolved
algebra/src/to_field_vec.rs Show resolved Hide resolved
@@ -125,6 +126,60 @@ impl<F: PrimeField> FpGadget<F> {
}
}

impl<F: PrimeField> TryInto<Boolean> for FpGadget<F> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. It was not completely what this function should do.


// compute lambda_diff = (y2-y1)/(x2-x1+is_same_x), the value for lambda to be used in case x1 != x2
let y2_minus_y1 = other.y.sub(cs.ns(|| "y2 - y1"), &self.y)?;
let x2_minus_x1_plus_x_same = x2_minus_x1.add(cs.ns(|| "x2 - x1 + x_is_same"), &is_same_x)?;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be
let x2_minus_x1_plus_is_same_x = x2_minus_x1.add(cs.ns(|| "x2 - x1 + is_same_x").

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks

lambda_diff.mul_equals(cs.ns(|| "enforce lambda_diff = (y2-y1) div (x2-x1+is_same_x"), &x2_minus_x1_plus_x_same, &y2_minus_y1)?;

// compute lambda_same = (3x1^2+a)/(2y1), the value for lambda to be used in case x1 = x2.
// in case y1 = 0, which happens only when self is the identity, the constraint
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not true for a general curve.
The points with y-coordinate equal to 0 are the zero point plus the points with order 2.
In the case of Tweedle (a=0, b not a cube), these points are not defined over the prime field. But, if you have a general curve (and the algorithm looks to be general since we do not assume a = 0) then the number of points can be a multiple of 2. In this last case you have points of order 2 and then non-trivial points with y = 0.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Observation by @UlrichHaboeck75 This is not a problem, because the witness points are always chosen in a prime order subgroup of the elliptic curve.
Anyway it could be specified in the comment.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I modify the comment to specify that in our case we consider only curves with prime order, and in such curves there cannot be other oints with y=0 besides the point at infinity


// compute lambda_same = (3x1^2+a)/(2y1), the value for lambda to be used in case x1 = x2.
// in case y1 = 0, which happens only when self is the identity, the constraint
// 2y1*lambda_same = 3x1^2+a cannot be satisfied, unless a == 0.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean that it cannot be satisfied?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean that when self is the identity, then x1=0 and y1=0, therefore there exists no value for lambda_same which would satisfy the constraint 2y1*lambda_same = 3x1^2+a, unless a=0. I will try to make the comment clearer.

let x1_minus_x3 = self.x.sub(cs.ns(|| "x1-x3"), &x3)?;
let y3 = lambda.mul(cs.ns(|| "lambda*(x1-x3)"), &x1_minus_x3)?.sub(cs.ns(|| "y3=lambda*(x1-x3)-y1"), &self.y)?;

// compute a flag is_sum_zero which is true iff self+other == identity
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is not precise: two points are opposite if and only if the x-coordinate is the same and the y-coordinate is the opposite.
The piece of code below is correct.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue of the comment does not seem clear to me, the comment just state that is_sum_zero = self + other == identity without delving into the relationship between the coordinates of the 2 points when this happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants