-
Notifications
You must be signed in to change notification settings - Fork 151
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 field division by handling division by zero #969
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #969 +/- ##
==========================================
+ Coverage 71.65% 71.66% +0.01%
==========================================
Files 156 156
Lines 34235 34316 +81
==========================================
+ Hits 24531 24593 +62
- Misses 9704 9723 +19 ☔ View full report in Codecov by Sentry. |
…et a denominator equal to zero
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot to flush the review, sorry.
} else if E::defining_equation(unsafe { &(&x / &z).unwrap_unchecked() }, unsafe { | ||
&(&y / &z).unwrap_unchecked() | ||
}) == FieldElement::zero() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably use regular unwrap
here.
It may be useful to compute the inverse of z
only once (not necessary to do now) and multiply later as well.
if z == FieldElement::zero() { | ||
let point = Self::new([x, y, z]) | ||
.map_err(|_| DeserializationError::FieldFromBytesError)?; | ||
if point.is_neutral_element() { | ||
Ok(point) | ||
} else { | ||
Err(DeserializationError::FieldFromBytesError) | ||
} | ||
} else if E::defining_equation(unsafe { &(&x / &z).unwrap_unchecked() }, unsafe { | ||
&(&y / &z).unwrap_unchecked() | ||
}) == FieldElement::zero() | ||
{ | ||
Self::new([x, y, z]).map_err(|_| DeserializationError::FieldFromBytesError) | ||
} else { | ||
Err(DeserializationError::FieldFromBytesError) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think something like this might be cleaner (assuming inv
gives us the inverse and returns a Result<_>
:
if z == FieldElement::zero() { | |
let point = Self::new([x, y, z]) | |
.map_err(|_| DeserializationError::FieldFromBytesError)?; | |
if point.is_neutral_element() { | |
Ok(point) | |
} else { | |
Err(DeserializationError::FieldFromBytesError) | |
} | |
} else if E::defining_equation(unsafe { &(&x / &z).unwrap_unchecked() }, unsafe { | |
&(&y / &z).unwrap_unchecked() | |
}) == FieldElement::zero() | |
{ | |
Self::new([x, y, z]).map_err(|_| DeserializationError::FieldFromBytesError) | |
} else { | |
Err(DeserializationError::FieldFromBytesError) | |
} | |
let Some(z_inv) = z.inv() else { | |
let point = Self::new([x, y, z]) | |
.map_err(|_| DeserializationError::FieldFromBytesError)?; | |
return if point.is_neutral_element() { | |
Ok(point) | |
} else { | |
Err(DeserializationError::FieldFromBytesError) | |
}; | |
}; | |
if E::defining_equation(&(&x * &z_inv), &(&y * &z_inv)) == FieldElement::zero() | |
{ | |
Self::new([x, y, z]).map_err(|_| DeserializationError::FieldFromBytesError) | |
} else { | |
Err(DeserializationError::FieldFromBytesError) | |
} |
This version has no unwrap
s and yet exploits that past the inverse calculation we know z != 0
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solved in 6f0e40d
.map_err(|_| ProverError::DivisionByZero) | ||
.unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the intent here was to remove the unwrap
:
.map_err(|_| ProverError::DivisionByZero) | |
.unwrap(); | |
.map_err(|_| ProverError::DivisionByZero)?; |
Fix field division by handling division by zero
Description
This PR fixes a potential division by zero error in the
div
function forFieldElement
which could cause apanic
. Instead of performing direct division, the implementation now returns aResult<FieldElement<L>, FieldError>
, ensuring error handling when division by zero occurs.