Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
ada5a2b
Add hint code for UINT348_UNSIGNED_DIV_REM
fmoletta Apr 11, 2023
d1b7e84
Add file for uint348 files
fmoletta Apr 11, 2023
c409d01
Add pack & split for uint348
fmoletta Apr 12, 2023
93c6f4e
Move comment
fmoletta Apr 12, 2023
82dbf2b
Implement uint348_unsigned_div_rem hint
fmoletta Apr 12, 2023
df9deb2
Add integration test
fmoletta Apr 12, 2023
7b2f5d9
Add integration test
fmoletta Apr 12, 2023
b1a3fbb
Add unit tests
fmoletta Apr 12, 2023
110605a
Add hint on split_128
fmoletta Apr 12, 2023
8cc3ce7
Test split_128 hint
fmoletta Apr 12, 2023
378788d
Add add_no_uint384_hint
fmoletta Apr 12, 2023
271a38c
Fix hint + add tests
fmoletta Apr 12, 2023
ed7de28
Add hint code for UINT348_UNSIGNED_DIV_REM_EXPAND
fmoletta Apr 12, 2023
be408c3
Msc fixes
fmoletta Apr 12, 2023
8c6fb8c
Add integration test
fmoletta Apr 12, 2023
512a80e
Reduce Uint384_expand representation to the 3 used limbs
fmoletta Apr 12, 2023
089398e
Add unit test
fmoletta Apr 12, 2023
6852a87
Add hint code for UINT384_SQRT
fmoletta Apr 13, 2023
e3e05be
Add implementation for hint on sqrt
fmoletta Apr 13, 2023
faf4765
Integration test
fmoletta Apr 13, 2023
d30d404
Add unit tests
fmoletta Apr 13, 2023
aa9ce34
Merge branch 'main' of github.com:lambdaclass/cairo-rs into uint348-h…
fmoletta Apr 13, 2023
f257b56
Fix missing directive
fmoletta Apr 13, 2023
4218e80
Run cairo-format
fmoletta Apr 13, 2023
e1d0100
Add changelog entry
fmoletta Apr 13, 2023
51c7dc3
Spelling
fmoletta Apr 13, 2023
f340a3a
Add hint code + Uint768 type
fmoletta Apr 13, 2023
08ebafb
Implement hint unsigned_div_rem_uint768_by_uint384
fmoletta Apr 13, 2023
3f8bdfb
Update src/hint_processor/builtin_hint_processor/uint384.rs
fmoletta Apr 13, 2023
43f3977
Update src/hint_processor/builtin_hint_processor/uint384.rs
fmoletta Apr 13, 2023
0045914
Update src/hint_processor/builtin_hint_processor/uint384.rs
fmoletta Apr 13, 2023
4f89202
Make hint code more readable
fmoletta Apr 13, 2023
c4b7f6e
Add integration test
fmoletta Apr 13, 2023
f0400b9
Add test
fmoletta Apr 13, 2023
a0368e2
Add unit test
fmoletta Apr 13, 2023
ce01868
Add changelog entry + fmt
fmoletta Apr 13, 2023
bd3214a
Fix plural
fmoletta Apr 13, 2023
f6359ad
Merge branch 'uint348-hints' into uint384-hints-extended
fmoletta Apr 13, 2023
96bc852
cargo fmt
fmoletta Apr 13, 2023
bf5a22c
Add first draft of get_square_root
fmoletta Apr 13, 2023
1ada5b3
Fix test
fmoletta Apr 14, 2023
764e28a
Fix syntax
fmoletta Apr 14, 2023
b259bd0
Fix test
fmoletta Apr 14, 2023
ffe9508
Add necessary lib fns
fmoletta Apr 14, 2023
24e06fe
Merge branch 'main' into uint348-hints
fmoletta Apr 14, 2023
6861479
fix fmt
fmoletta Apr 14, 2023
4f094b4
Fix test value
fmoletta Apr 14, 2023
4059972
Merge branch 'uint348-hints' into uint384-hints-extended
fmoletta Apr 14, 2023
ec67ecb
Merge branch 'uint384-hints-extended' into field-arithmetic-hints
fmoletta Apr 14, 2023
18011e0
Add test program
fmoletta Apr 14, 2023
afe1cca
Add hint to execute_hint
fmoletta Apr 14, 2023
355b836
Fix wrong hint being tested
fmoletta Apr 14, 2023
9c159ef
Implement sqrt
fmoletta Apr 14, 2023
9c5db20
Add test fix file
fmoletta Apr 14, 2023
e9982da
Fix _sqrt_mod_tonelli_shanks implementation
fmoletta Apr 17, 2023
c3be7b3
Expand integration test
fmoletta Apr 17, 2023
376cd3d
Add unit test
fmoletta Apr 17, 2023
6906494
Add proptests
fmoletta Apr 17, 2023
40ad285
Merge branch 'main' of github.com:lambdaclass/cairo-rs into uint384-h…
fmoletta Apr 17, 2023
fee4a04
Fix merge conflict
fmoletta Apr 17, 2023
3284a6d
Fix merge conflict
fmoletta Apr 17, 2023
0032e0a
Merge branch 'uint384-hints-extended' into field-arithmetic-hints
fmoletta Apr 17, 2023
b61d958
Add changelog entry
fmoletta Apr 17, 2023
fc9573f
Use no-std compatible rng when std is not enabled
fmoletta Apr 17, 2023
ed1c58c
Clippy
fmoletta Apr 17, 2023
c469789
Add misc tests
fmoletta Apr 17, 2023
d744a6f
Remove vec use
fmoletta Apr 17, 2023
3f79a21
Remove merge conflict from changelog
fmoletta Apr 17, 2023
37bdc30
Use seeded rng instead of from_entropy
fmoletta Apr 17, 2023
03eb74c
Catch potential zero divison errors
fmoletta Apr 17, 2023
63032a4
Catch potential zero divison errors
fmoletta Apr 17, 2023
585fdeb
Merge branch 'main' of github.com:lambdaclass/cairo-rs into uint384-h…
fmoletta Apr 17, 2023
8836c52
Prevent zero divison error in is_quad_residue fn
fmoletta Apr 17, 2023
1964998
Add tests case when no successes
fmoletta Apr 17, 2023
798cd34
Add tests case when success_gx
fmoletta Apr 17, 2023
886f648
Add some tests
fmoletta Apr 17, 2023
389d39a
Merge branch 'uint384-hints-extended' into field-arithmetic-hints
fmoletta Apr 17, 2023
117a5c8
Fix test value
fmoletta Apr 17, 2023
786bdd7
Fix test value
fmoletta Apr 18, 2023
11014ff
Add unit test for specific case
fmoletta Apr 18, 2023
367a4f7
Add specific case unit test
fmoletta Apr 18, 2023
803b700
Catch prime being 0
fmoletta Apr 18, 2023
3341550
Add prime check to sqrt_prime_power + Fix proptest values + unify rng…
fmoletta Apr 18, 2023
43ee65c
Use `trailing_zeros` instead of sympy trailing implementation
fmoletta Apr 18, 2023
2afda64
Fix proptest format
fmoletta Apr 18, 2023
826484c
Remove unused feature from tml
fmoletta Apr 18, 2023
fa6b0da
Merge branch 'main' of github.com:lambdaclass/cairo-rs into field-ari…
fmoletta Apr 19, 2023
168a059
Clean test file
fmoletta Apr 19, 2023
d5717d0
Fix merge conflict
fmoletta Apr 19, 2023
dff6f06
Fix bug in add_no_uint384_check
fmoletta Apr 19, 2023
36b4e62
Add benchmark file
fmoletta Apr 19, 2023
65e515f
Merge branch 'main' into field-arithmetic-hints
fmoletta Apr 19, 2023
b022b88
Remove duplicated file
fmoletta Apr 19, 2023
4e75245
Merge branch 'field-arithmetic-hints' of github.com:lambdaclass/cairo…
fmoletta Apr 19, 2023
b5f7e77
Fix cairo file
fmoletta Apr 19, 2023
8856f0b
Fix wasm tests
fmoletta Apr 19, 2023
017e8d0
Move proptest to dev-dependencies
fmoletta Apr 19, 2023
c955075
Revert "Move proptest to dev-dependencies"
fmoletta Apr 20, 2023
35b2724
Revert change + use feature directive for proptest import
fmoletta Apr 20, 2023
607eee3
Merge branch 'main' of github.com:lambdaclass/cairo-rs into field-ari…
fmoletta Apr 20, 2023
9ffb530
fmt
fmoletta Apr 20, 2023
e5e7915
Merge branch 'main' into field-arithmetic-hints
fmoletta Apr 20, 2023
d75c541
Update src/hint_processor/builtin_hint_processor/field_arithmetic.rs
fmoletta Apr 20, 2023
df2c60f
Remove unused import
fmoletta Apr 20, 2023
4bd40cf
Merge branch 'main' of github.com:lambdaclass/cairo-rs into field-ari…
fmoletta Apr 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
52 changes: 52 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,57 @@

#### Upcoming Changes

* Implement hints on field_arithmetic lib[#985](https://github.com/lambdaclass/cairo-rs/pull/983)

`BuiltinHintProcessor` now supports the following hint:

```python
%{
from starkware.python.math_utils import is_quad_residue, sqrt

def split(num: int, num_bits_shift: int = 128, length: int = 3):
a = []
for _ in range(length):
a.append( num & ((1 << num_bits_shift) - 1) )
num = num >> num_bits_shift
return tuple(a)

def pack(z, num_bits_shift: int = 128) -> int:
limbs = (z.d0, z.d1, z.d2)
return sum(limb << (num_bits_shift * i) for i, limb in enumerate(limbs))


generator = pack(ids.generator)
x = pack(ids.x)
p = pack(ids.p)

success_x = is_quad_residue(x, p)
root_x = sqrt(x, p) if success_x else None

success_gx = is_quad_residue(generator*x, p)
root_gx = sqrt(generator*x, p) if success_gx else None

# Check that one is 0 and the other is 1
if x != 0:
assert success_x + success_gx ==1

# `None` means that no root was found, but we need to transform these into a felt no matter what
if root_x == None:
root_x = 0
if root_gx == None:
root_gx = 0
ids.success_x = int(success_x)
split_root_x = split(root_x)
split_root_gx = split(root_gx)
ids.sqrt_x.d0 = split_root_x[0]
ids.sqrt_x.d1 = split_root_x[1]
ids.sqrt_x.d2 = split_root_x[2]
ids.sqrt_gx.d0 = split_root_gx[0]
ids.sqrt_gx.d1 = split_root_gx[1]
ids.sqrt_gx.d2 = split_root_gx[2]
%}
```

* Add missing hint on uint256_improvements lib [#1016](https://github.com/lambdaclass/cairo-rs/pull/1016):

`BuiltinHintProcessor` now supports the following hint:
Expand Down Expand Up @@ -85,6 +136,7 @@
* The new version carries an 85% reduction in execution time for ECDSA signature verification

* BREAKING CHANGE: refactor `Program` to optimize `Program::clone` [#999](https://github.com/lambdaclass/cairo-rs/pull/999)

* Breaking change: many fields that were (unnecessarily) public become hidden by the refactor.

* BREAKING CHANGE: Add _builtin suffix to builtin names e.g.: output -> output_builtin [#1005](https://github.com/lambdaclass/cairo-rs/pull/1005)
Expand Down
55 changes: 54 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ hooks = []

[dependencies]
mimalloc = { version = "0.1.29", default-features = false, optional = true }
num-bigint = { version = "0.4", features = ["serde"], default-features = false }
num-bigint = { version = "0.4", features = ["serde", "rand"], default-features = false }
rand = { version = "0.8.3", features = ["small_rng"], default-features = false }
num-traits = { version = "0.2", default-features = false }
num-integer = { version = "0.1.45", default-features = false }
num-prime = {version = "0.4.3", features = ["big-int"], default-features = false }
serde = { version = "1.0", features = ["derive"], default-features = false }
serde_bytes = { version = "0.11.9", default-features = false, features = [
"alloc",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin
from starkware.cairo.common.bool import TRUE
from cairo_programs.uint384 import uint384_lib, Uint384, Uint384_expand
from cairo_programs.uint384_extension import uint384_extension_lib
from cairo_programs.field_arithmetic import field_arithmetic


func run_get_square{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(prime: Uint384, generator: Uint384, num: Uint384, iterations: felt) {
alloc_locals;
if (iterations == 0) {
return ();
}

let (square) = field_arithmetic.mul(num, num, prime);

let (success, root_1) = field_arithmetic.get_square_root(square, prime, generator);
assert success = 1;

// We calculate this before in order to prevent revoked range_check_ptr reference due to branching
let (root_2) = uint384_lib.sub(prime, root_1);
let (is_first_root) = uint384_lib.eq(root_1, num);

if ( is_first_root != TRUE) {
assert root_2 = num;
}

return run_get_square(prime, generator, square, iterations -1);
}

func main{range_check_ptr: felt, bitwise_ptr: BitwiseBuiltin*}() {
let p = Uint384(18446744069414584321, 0, 0); // Goldilocks Prime
let x = Uint384(5, 0, 0);
let g = Uint384(7, 0, 0);
run_get_square(p, g, x, 100);
return ();
}
171 changes: 171 additions & 0 deletions cairo_programs/field_arithmetic.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Code taken from https://github.com/NethermindEth/research-basic-Cairo-operations-big-integers/blob/fbf532651959f27037d70cd70ec6dbaf987f535c/lib/field_arithmetic.cairo
from starkware.cairo.common.bitwise import bitwise_and, bitwise_or, bitwise_xor
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin
from starkware.cairo.common.math import assert_in_range, assert_le, assert_nn_le, assert_not_zero
from starkware.cairo.common.math_cmp import is_le
from starkware.cairo.common.pow import pow
from starkware.cairo.common.registers import get_ap, get_fp_and_pc
from cairo_programs.uint384 import uint384_lib, Uint384, Uint384_expand, SHIFT, HALF_SHIFT
from cairo_programs.uint384_extension import uint384_extension_lib, Uint768

// Functions for operating elements in a finite field F_p (i.e. modulo a prime p), with p of at most 384 bits
namespace field_arithmetic {
// Computes a * b modulo p
func mul{range_check_ptr}(a: Uint384, b: Uint384, p: Uint384) -> (res: Uint384) {
let (low: Uint384, high: Uint384) = uint384_lib.mul_d(a, b);
let full_mul_result: Uint768 = Uint768(low.d0, low.d1, low.d2, high.d0, high.d1, high.d2);
let (
quotient: Uint768, remainder: Uint384
) = uint384_extension_lib.unsigned_div_rem_uint768_by_uint384(full_mul_result, p);
return (remainder,);
}

// Computes a**2 modulo p
func square{range_check_ptr}(a: Uint384, p: Uint384) -> (res: Uint384) {
let (low: Uint384, high: Uint384) = uint384_lib.square_e(a);
let full_mul_result: Uint768 = Uint768(low.d0, low.d1, low.d2, high.d0, high.d1, high.d2);
let (
quotient: Uint768, remainder: Uint384
) = uint384_extension_lib.unsigned_div_rem_uint768_by_uint384(full_mul_result, p);
return (remainder,);
}

// Finds a square of x in F_p, i.e. x ≅ y**2 (mod p) for some y
// To do so, the following is done in a hint:
// 0. Assume x is not 0 mod p
// 1. Check if x is a square, if yes, find a square root r of it
// 2. If (and only if not), then gx *is* a square (for g a generator of F_p^*), so find a square root r of it
// 3. Check in Cairo that r**2 = x (mod p) or r**2 = gx (mod p), respectively
// NOTE: The function assumes that 0 <= x < p
func get_square_root{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(
x: Uint384, p: Uint384, generator: Uint384
) -> (success: felt, res: Uint384) {
alloc_locals;

// TODO: Create an equality function within field_arithmetic to avoid overflow bugs
let (is_zero) = uint384_lib.eq(x, Uint384(0, 0, 0));
if (is_zero == 1) {
return (1, Uint384(0, 0, 0));
}

local success_x: felt;
local sqrt_x: Uint384;
local sqrt_gx: Uint384;

// Compute square roots in a hint
%{
from starkware.python.math_utils import is_quad_residue, sqrt

def split(num: int, num_bits_shift: int = 128, length: int = 3):
a = []
for _ in range(length):
a.append( num & ((1 << num_bits_shift) - 1) )
num = num >> num_bits_shift
return tuple(a)

def pack(z, num_bits_shift: int = 128) -> int:
limbs = (z.d0, z.d1, z.d2)
return sum(limb << (num_bits_shift * i) for i, limb in enumerate(limbs))


generator = pack(ids.generator)
x = pack(ids.x)
p = pack(ids.p)

success_x = is_quad_residue(x, p)
root_x = sqrt(x, p) if success_x else None

success_gx = is_quad_residue(generator*x, p)
root_gx = sqrt(generator*x, p) if success_gx else None

# Check that one is 0 and the other is 1
if x != 0:
assert success_x + success_gx ==1

# `None` means that no root was found, but we need to transform these into a felt no matter what
if root_x == None:
root_x = 0
if root_gx == None:
root_gx = 0
ids.success_x = int(success_x)
split_root_x = split(root_x)
split_root_gx = split(root_gx)
ids.sqrt_x.d0 = split_root_x[0]
ids.sqrt_x.d1 = split_root_x[1]
ids.sqrt_x.d2 = split_root_x[2]
ids.sqrt_gx.d0 = split_root_gx[0]
ids.sqrt_gx.d1 = split_root_gx[1]
ids.sqrt_gx.d2 = split_root_gx[2]
%}

// Verify that the values computed in the hint are what they are supposed to be
let (gx: Uint384) = mul(generator, x, p);
if (success_x == 1) {
uint384_lib.check(sqrt_x);
let (is_valid) = uint384_lib.lt(sqrt_x, p);
assert is_valid = 1;
let (sqrt_x_squared: Uint384) = mul(sqrt_x, sqrt_x, p);
// Note these checks may fail if the input x does not satisfy 0<= x < p
// TODO: Create a equality function within field_arithmetic to avoid overflow bugs
let (check_x) = uint384_lib.eq(x, sqrt_x_squared);
assert check_x = 1;
return (1, sqrt_x);
} else {
// In this case success_gx = 1
uint384_lib.check(sqrt_gx);
let (is_valid) = uint384_lib.lt(sqrt_gx, p);
assert is_valid = 1;
let (sqrt_gx_squared: Uint384) = mul(sqrt_gx, sqrt_gx, p);
let (check_gx) = uint384_lib.eq(gx, sqrt_gx_squared);
assert check_gx = 1;
// No square roots were found
// Note that Uint384(0, 0, 0) is not a square root here, but something needs to be returned
return (0, Uint384(0, 0, 0));
}
}

}

func test_field_arithmetics_extension_operations{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}() {
// Test get_square

//Small prime
let p_a = Uint384(7, 0, 0);
let x_a = Uint384(2, 0, 0);
let generator_a = Uint384(3, 0, 0);
let (s_a, r_a) = field_arithmetic.get_square_root(x_a, p_a, generator_a);
assert s_a = 1;

assert r_a.d0 = 3;
assert r_a.d1 = 0;
assert r_a.d2 = 0;

// Goldilocks Prime
let p_b = Uint384(18446744069414584321, 0, 0); // Goldilocks Prime
let x_b = Uint384(25, 0, 0);
let generator_b = Uint384(7, 0, 0);
let (s_b, r_b) = field_arithmetic.get_square_root(x_b, p_b, generator_b);
assert s_b = 1;

assert r_b.d0 = 5;
assert r_b.d1 = 0;
assert r_b.d2 = 0;

// Prime 2**101-99
let p_c = Uint384(77371252455336267181195165, 32767, 0);
let x_c = Uint384(96059601, 0, 0);
let generator_c = Uint384(3, 0, 0);
let (s_c, r_c) = field_arithmetic.get_square_root(x_c, p_c, generator_c);
assert s_c = 1;

assert r_c.d0 = 9801;
assert r_c.d1 = 0;
assert r_c.d2 = 0;

return ();
}

func main{range_check_ptr: felt, bitwise_ptr: BitwiseBuiltin*}() {
test_field_arithmetics_extension_operations();
return ();
}
Loading