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: addmod #88

Merged
merged 6 commits into from
Aug 16, 2023
Merged

fix: addmod #88

merged 6 commits into from
Aug 16, 2023

Conversation

enitrat
Copy link
Collaborator

@enitrat enitrat commented Aug 16, 2023

Pull Request type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no API changes)
  • Build-related changes
  • Documentation content changes
  • Other (please describe):

What is the current behavior?

Issue Number: Closes #83

What is the new behavior?

  • Fixes ADDMOD behavior

Does this introduce a breaking change?

  • Yes
  • No

Added changes to CHANGELOG.md

  • Yes
  • No

Other information

ADDMOD

I tried two different implementations for this ADDMOD opcode, leveraging the fact that (x + y) mod N <=> (x mod N) + (y mod N) mod N

The first try was using u256_wide_add, a function that I created that adds two u256s and returns a u512 to avoid overflowing on the a+b addition, and then dividing it by N and returning the remainder.

fn exec_addmod(ref self: ExecutionContext) {
        let popped = self.stack.pop_n(3);

        let n: u256 = *popped[2];
        let mut result = 0;
        if n != 0 {
            let add_res = u256_wide_add(*popped[0], *popped[1]);
            let (_, r) = u512_safe_div_rem_by_u256(add_res, n.try_into().unwrap());
            result = r;
        }

        self.stack.push(result);
    }
    
    

fn u256_wide_add(a: u256, b: u256) -> u512 {
    let (sum, overflow) = u256_overflowing_add(a, b);

    let limb0 = sum.low;
    let limb1 = sum.high;

    let limb2 = if overflow {
        1
    } else {
        0
    };

    let limb3 = 0;

    u512 { limb0, limb1, limb2, limb3 }
}

Here is the test output

❯ scarb test -f test_exec_addmod_overflow
Running tests for package: kakarot
testing kakarot ...
running 1 tests
[DEBUG]	                               	(raw: 0x3b72c

test kakarot::tests::test_instructions::test_stop_and_arithmetic_operations::test_exec_addmod_overflow ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 78 filtered out;

The other implementation is

    fn exec_addmod(ref self: ExecutionContext) {
        let popped = self.stack.pop_n(3);

        let n: u256 = *popped[2];
        let mut result = 0;
        if n != 0 {
            // (x + y) mod N <=> (x mod N) + (y mod N) mod N
            result = (*popped[0] % n) + (*popped[1] % n) % n;
        }
        self.stack.push(result);
    }






Here is the test output

❯ scarb test -f test_exec_addmod_overflow
Running tests for package: kakarot
testing kakarot ...
running 1 tests
[DEBUG]	                               	(raw: 0x3d5b8

test kakarot::tests::test_instructions::test_stop_and_arithmetic_operations::test_exec_addmod_overflow ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 78 filtered out;




This second version is ~3% more costly. Therefore, we will keep the first one with u256_wide_add.

@enitrat enitrat marked this pull request as ready for review August 16, 2023 13:06
Eikix
Eikix previously approved these changes Aug 16, 2023
Copy link
Member

@Eikix Eikix left a comment

Choose a reason for hiding this comment

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

lgtm

@Eikix
Copy link
Member

Eikix commented Aug 16, 2023

smol conflicts

Copy link
Contributor

@greged93 greged93 left a comment

Choose a reason for hiding this comment

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

nit: parenthesis for 2 comments

enitrat and others added 3 commits August 16, 2023 15:46
…s.cairo

Co-authored-by: greged93 <82421016+greged93@users.noreply.github.com>
…s.cairo

Co-authored-by: greged93 <82421016+greged93@users.noreply.github.com>
@enitrat enitrat requested a review from Eikix August 16, 2023 13:54
Copy link
Contributor

@greged93 greged93 left a comment

Choose a reason for hiding this comment

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

lgtm!

@Eikix Eikix added this pull request to the merge queue Aug 16, 2023
Merged via the queue into main with commit c1dc63c Aug 16, 2023
3 checks passed
@Eikix Eikix deleted the fix/addmod branch August 16, 2023 13:58
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.

bug: ADDMOD opcode intermediate calculations should not be subject to the 2256 modulo.
3 participants