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: bugs on border cases of udiv_mod #76

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

Pablo-Dallegri
Copy link

Description

Problem*

Failures when attempting to prove certain udiv_mod operations.

Summary*

🪲 Unsigned integer division fails if the numerator can be represented with less bits than the divisor, due to an underflow on the subtraction at:

let mut bit_difference = remainder_u60.get_msb() - divisor_u60.get_msb();

🐞 Unsigned integer division also fails in cases were the least significant limb of the remainder is 2¹²⁰-1, due to a miscalculation of borrow flags, halting the proving at:

validate_gt::<_, MOD_BITS>(divisor, remainder);

🔧 This PR adds tests for both cases, and proposes fixes.

Additional Context

These bugs where found while developing in the context of NRG#2, and tests were reduced to minimal examples.

PR Checklist*

  • I have tested the changes locally.
  • I have formatted the changes with Prettier and/or cargo fmt on default settings.

@Pablo-Dallegri Pablo-Dallegri changed the title Bug fixes for udiv_mod fix: bugs on border cases of udiv_mod Dec 12, 2024
@TomAFrench TomAFrench requested a review from kashbrti December 13, 2024 17:38
for _ in 0..(N * 120) {
if (remainder_u60.gte(b) == false) {
break;
if (divisor_u60.gte(remainder_u60 + U60Repr::one())) {
Copy link
Contributor

@kashbrti kashbrti Dec 16, 2024

Choose a reason for hiding this comment

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

are these just formatter changes?

Copy link
Member

Choose a reason for hiding this comment

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

They're from the if statement causing extra indentation.

@@ -171,34 +171,38 @@ pub(crate) unconstrained fn __udiv_mod<let N: u32>(
let mut divisor_u60: U60Repr<N, 2> = U60Repr::from(divisor);
let b = divisor_u60;

let mut bit_difference = remainder_u60.get_msb() - divisor_u60.get_msb();
Copy link
Contributor

Choose a reason for hiding this comment

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

I see how this line can cause issues when the denominator has more bits in its u60 representation. Thanks for catching this!

@@ -171,34 +171,38 @@ pub(crate) unconstrained fn __udiv_mod<let N: u32>(
let mut divisor_u60: U60Repr<N, 2> = U60Repr::from(divisor);
let b = divisor_u60;

let mut bit_difference = remainder_u60.get_msb() - divisor_u60.get_msb();
if !remainder_u60.gte(divisor_u60) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if there would be a better way to catch this, without using the if statement. @TomAFrench would it be more efficient to look at the index where the msb of the denominator is rather than using the if statement?
regardless the change should fix this issue.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah it looks like it would be better to get the two msbs and compare these directly.

Copy link
Contributor

Choose a reason for hiding this comment

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

@Pablo-Dallegri would you like to tackle this yourself or should I try to make the change before merging the PR?

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