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

Implement ASSERT_LT_FELT hint #242

Merged
merged 36 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
561d5c4
Add IdsManager.GetConst
fmoletta Sep 18, 2023
e25c3f4
Integrate into logic
fmoletta Sep 18, 2023
303b2b9
[WIP] Assert 250 Bits and SPLIT_FELT
jrchatruc Sep 18, 2023
8ad2c3a
Add utils to help with fetching constants
fmoletta Sep 18, 2023
53e6b76
Add SetupConstantsForTest
fmoletta Sep 18, 2023
34cc455
Add comments
fmoletta Sep 18, 2023
164820a
Guard error case
fmoletta Sep 18, 2023
fc09cd5
Add tests for ASSERT_250_BIT
jrchatruc Sep 18, 2023
e529897
Fix typo
fmoletta Sep 18, 2023
5439620
Implement SPLIT_FELT
jrchatruc Sep 18, 2023
4b93d07
Fix util
fmoletta Sep 18, 2023
6b7d886
Merge branch 'add-constants-to-ids' of github.com:lambdaclass/cairo-v…
fmoletta Sep 18, 2023
37c674a
Add hint code
fmoletta Sep 18, 2023
9ddaeac
Implement FeltFromBigInt
fmoletta Sep 18, 2023
73703bc
Implement ASSERT_LE_FELT hint
fmoletta Sep 18, 2023
6f7fe68
Add comment
fmoletta Sep 18, 2023
a1c0625
Add test
fmoletta Sep 18, 2023
a712b47
Add the 3 assert_le_felt_exclued hints
fmoletta Sep 18, 2023
ad0cd1e
Add tests
fmoletta Sep 18, 2023
df0ef46
Fix identifier
fmoletta Sep 18, 2023
1eabf94
Add integration test
fmoletta Sep 18, 2023
64b7164
Fix type const in tests
fmoletta Sep 18, 2023
b8877e8
Merge branch 'main' of github.com:lambdaclass/cairo-vm.go into assert…
fmoletta Sep 18, 2023
a85c2c9
Fix typo
fmoletta Sep 18, 2023
f4a0cf2
Fix test
fmoletta Sep 18, 2023
03142ac
Fix bug
fmoletta Sep 18, 2023
742d51e
Remove debug print
fmoletta Sep 18, 2023
8707c24
Fix test name
fmoletta Sep 18, 2023
789fce2
Add hint + unit tests
fmoletta Sep 19, 2023
c10798a
Fix test
fmoletta Sep 19, 2023
e086b60
Add integration test
fmoletta Sep 19, 2023
93a98ad
Merge remote-tracking branch 'origin/assert-250-split-felt' into asse…
fmoletta Sep 19, 2023
cb72b52
Add newline at eof
fmoletta Sep 19, 2023
a146441
Merge branch 'main' of github.com:lambdaclass/cairo-vm.go into assert…
fmoletta Sep 20, 2023
87240d3
Remove file
fmoletta Sep 20, 2023
760cb7a
Merge branch 'main' into assert-lt-felt
fmoletta Sep 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions cairo_programs/assert_250_bit_element_array.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
%builtins range_check

from starkware.cairo.common.math import assert_250_bit
from starkware.cairo.common.alloc import alloc

func assert_250_bit_element_array{range_check_ptr: felt}(
array: felt*, array_length: felt, iterator: felt
) {
if (iterator == array_length) {
return ();
}
assert_250_bit(array[iterator]);
return assert_250_bit_element_array(array, array_length, iterator + 1);
}

func fill_array(array: felt*, base: felt, step: felt, array_length: felt, iterator: felt) {
if (iterator == array_length) {
return ();
}
assert array[iterator] = base + step * iterator;
return fill_array(array, base, step, array_length, iterator + 1);
}

func main{range_check_ptr: felt}() {
alloc_locals;
tempvar array_length = 10;
let (array: felt*) = alloc();
fill_array(array, 70000000000000000000, 300000000000000000, array_length, 0);
assert_250_bit_element_array(array, array_length, 0);
return ();
}
10 changes: 10 additions & 0 deletions cairo_programs/assert_le_felt.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

%builtins range_check
from starkware.cairo.common.math import assert_le_felt

func main{range_check_ptr: felt}() {
assert_le_felt(1, 2);
assert_le_felt(-2, -1);
assert_le_felt(2, -1);
return ();
}
49 changes: 49 additions & 0 deletions cairo_programs/assert_lt_felt.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
%builtins range_check

from starkware.cairo.common.math import assert_lt
from starkware.cairo.common.math import split_felt
from starkware.cairo.common.math import assert_lt_felt

func assert_lt_felt_manual_implementation{range_check_ptr}(a, b) {
%{
from starkware.cairo.common.math_utils import assert_integer
assert_integer(ids.a)
assert_integer(ids.b)
assert (ids.a % PRIME) < (ids.b % PRIME), \
f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'
%}
alloc_locals;
let (local a_high, local a_low) = split_felt(a);
let (b_high, b_low) = split_felt(b);

if (a_high == b_high) {
assert_lt(a_low, b_low);
return ();
}
assert_lt(a_high, b_high);
return ();
}

func main{range_check_ptr: felt}() {
let x = 5;
let y = 6;

tempvar m = 7;
tempvar n = 7 * 7;

assert_lt_felt(1, 2);
assert_lt_felt(-2, -1);
assert_lt_felt(1, -1);
assert_lt_felt(0, 1);
assert_lt_felt(x, y);
assert_lt_felt(m, n);

assert_lt_felt_manual_implementation(1, 2);
assert_lt_felt_manual_implementation(-2, -1);
assert_lt_felt_manual_implementation(1, -1);
assert_lt_felt_manual_implementation(0, 1);
assert_lt_felt_manual_implementation(x, y);
assert_lt_felt_manual_implementation(m, n);

return ();
}
42 changes: 42 additions & 0 deletions cairo_programs/split_felt.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
%builtins range_check

from starkware.cairo.common.math import assert_le
from starkware.cairo.common.math import split_felt

func split_felt_manual_implemetation{range_check_ptr}(value) -> (high: felt, low: felt) {
// Note: the following code works because PRIME - 1 is divisible by 2**128.
const MAX_HIGH = (-1) / 2 ** 128;
const MAX_LOW = 0;

// Guess the low and high parts of the integer.
let low = [range_check_ptr];
let high = [range_check_ptr + 1];
let range_check_ptr = range_check_ptr + 2;

%{
from starkware.cairo.common.math_utils import assert_integer
assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128
assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW
assert_integer(ids.value)
ids.low = ids.value & ((1 << 128) - 1)
ids.high = ids.value >> 128
%}

assert value = high * (2 ** 128) + low;
if (high == MAX_HIGH) {
assert_le(low, MAX_LOW);
} else {
assert_le(high, MAX_HIGH - 1);
}
return (high=high, low=low);
}

func main{range_check_ptr: felt}() {
let (m, n) = split_felt_manual_implemetation(5784800237655953878877368326340059594760);
assert m = 17;
assert n = 8;
let (x, y) = split_felt(5784800237655953878877368326340059594760);
assert x = 17;
assert y = 8;
return ();
}
14 changes: 14 additions & 0 deletions pkg/hints/hint_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ func (p *CairoVmHintProcessor) ExecuteHint(vm *vm.VirtualMachine, hintData *any,
return memcpy_enter_scope(data.Ids, vm, execScopes)
case VM_ENTER_SCOPE:
return vm_enter_scope(execScopes)
case ASSERT_LE_FELT:
return assertLeFelt(data.Ids, vm, execScopes, constants)
case ASSERT_LE_FELT_EXCLUDED_0:
return assertLeFeltExcluded0(vm, execScopes)
case ASSERT_LE_FELT_EXCLUDED_1:
return assertLeFeltExcluded1(vm, execScopes)
case ASSERT_LE_FELT_EXCLUDED_2:
return assertLeFeltExcluded2(vm, execScopes)
case ASSERT_LT_FELT:
return assertLtFelt(data.Ids, vm)
case ASSERT_250_BITS:
return Assert250Bit(data.Ids, vm, constants)
case SPLIT_FELT:
return SplitFelt(data.Ids, vm, constants)
default:
return errors.Errorf("Unknown Hint: %s", data.Code)
}
Expand Down
23 changes: 23 additions & 0 deletions pkg/hints/hint_utils/hint_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package hint_utils

import (
"strings"

. "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks"
"github.com/pkg/errors"
)

func GetConstantFromVarName(name string, constants *map[string]Felt) (Felt, error) {
if constants == nil {
return Felt{}, errors.Errorf("Caled GetConstantFromVarName with a nil constants map. Var Name: %s", name)
fmoletta marked this conversation as resolved.
Show resolved Hide resolved
}

for key, value := range *constants {
keySplit := strings.Split(key, ".")
if keySplit[len(keySplit)-1] == name {
return value, nil
}
}

return Felt{}, errors.Errorf("Variable name not found in constants map. Var Name: %s", name)
}
14 changes: 14 additions & 0 deletions pkg/hints/math_hint_codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,17 @@ else:
const ASSERT_NOT_EQUAL = "from starkware.cairo.lang.vm.relocatable import RelocatableValue\nboth_ints = isinstance(ids.a, int) and isinstance(ids.b, int)\nboth_relocatable = (\n isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and\n ids.a.segment_index == ids.b.segment_index)\nassert both_ints or both_relocatable, \\\n f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.'\nassert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'"

const SQRT = "from starkware.python.math_utils import isqrt\nvalue = ids.value % PRIME\nassert value < 2 ** 250, f\"value={value} is outside of the range [0, 2**250).\"\nassert 2 ** 250 < PRIME\nids.root = isqrt(value)"

const ASSERT_LE_FELT = "import itertools\n\nfrom starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\na = ids.a % PRIME\nb = ids.b % PRIME\nassert a <= b, f'a = {a} is not less than or equal to b = {b}.'\n\n# Find an arc less than PRIME / 3, and another less than PRIME / 2.\nlengths_and_indices = [(a, 0), (b - a, 1), (PRIME - 1 - b, 2)]\nlengths_and_indices.sort()\nassert lengths_and_indices[0][0] <= PRIME // 3 and lengths_and_indices[1][0] <= PRIME // 2\nexcluded = lengths_and_indices[2][1]\n\nmemory[ids.range_check_ptr + 1], memory[ids.range_check_ptr + 0] = (\n divmod(lengths_and_indices[0][0], ids.PRIME_OVER_3_HIGH))\nmemory[ids.range_check_ptr + 3], memory[ids.range_check_ptr + 2] = (\n divmod(lengths_and_indices[1][0], ids.PRIME_OVER_2_HIGH))"

const ASSERT_LE_FELT_EXCLUDED_0 = "memory[ap] = 1 if excluded != 0 else 0"

const ASSERT_LE_FELT_EXCLUDED_1 = "memory[ap] = 1 if excluded != 1 else 0"

const ASSERT_LE_FELT_EXCLUDED_2 = "assert excluded == 2"

const ASSERT_LT_FELT = "from starkware.cairo.common.math_utils import assert_integer\nassert_integer(ids.a)\nassert_integer(ids.b)\nassert (ids.a % PRIME) < (ids.b % PRIME), \\\n f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'"

const ASSERT_250_BITS = "from starkware.cairo.common.math_utils import as_int\n\n# Correctness check.\nvalue = as_int(ids.value, PRIME) % PRIME\nassert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).'\n\n# Calculation for the assertion.\nids.high, ids.low = divmod(ids.value, ids.SHIFT)"

const SPLIT_FELT = "from starkware.cairo.common.math_utils import assert_integer\nassert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128\nassert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW\nassert_integer(ids.value)\nids.low = ids.value & ((1 << 128) - 1)\nids.high = ids.value >> 128"
Loading