Skip to content

Commit 263712a

Browse files
mfachalOppen
andauthored
Add NewHint#31 (#991)
* add program with div_mod_n * make mul_s_inv program execute * make mul_s_inv program execute * add pack_modn_div_modn and mul_s_inv test * add changes to changelog * fix changelog merge * fix changelog * fix changelog style --------- Co-authored-by: Mario Rugiero <[email protected]>
1 parent c319786 commit 263712a

File tree

6 files changed

+156
-7
lines changed

6 files changed

+156
-7
lines changed

CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@
66
* BugFix: Add missing `\n` character after traceback lines when the filename is missing ("Unknown Location")
77

88
* 0.11 Support
9+
* Add missing hints on cairo_secp lib [#991](https://github.com/lambdaclass/cairo-rs/pull/991):
10+
`BuiltinHintProcessor` now supports the following hints:
11+
```python
12+
from starkware.cairo.common.cairo_secp.secp_utils import pack
13+
from starkware.python.math_utils import div_mod, safe_div
14+
15+
N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
16+
x = pack(ids.x, PRIME) % N
17+
s = pack(ids.s, PRIME) % N
18+
value = res = div_mod(x, s, N)
19+
```
20+
and:
21+
```python
22+
value = k = safe_div(res * s - x, N)
23+
```
924
* Layouts update [#874](https://github.com/lambdaclass/cairo-rs/pull/874)
1025
* Keccak builtin updated [#873](https://github.com/lambdaclass/cairo-rs/pull/873), [#883](https://github.com/lambdaclass/cairo-rs/pull/883)
1126
* Changes to `ec_op` [#876](https://github.com/lambdaclass/cairo-rs/pull/876)
@@ -16,7 +31,6 @@
1631
* Added dynamic layout [#879](https://github.com/lambdaclass/cairo-rs/pull/879)
1732
* `get_segment_size` was exposed [#934](https://github.com/lambdaclass/cairo-rs/pull/934)
1833

19-
2034
* Add missing hint on cairo_secp lib [#990](https://github.com/lambdaclass/cairo-rs/pull/990):
2135

2236
`BuiltinHintProcessor` now supports the following hint:

cairo_programs/mul_s_inv.cairo

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
%builtins range_check
2+
3+
// Source: https://github.com/NilFoundation/cairo-placeholder-verification/blob/382924c6f1c4f9673a12a31d19835e00978ab241/src/signatures/ed25519.cairo
4+
5+
from starkware.cairo.common.cairo_secp.bigint import BASE, BigInt3, bigint_mul, nondet_bigint3
6+
from starkware.cairo.common.cairo_secp.constants import N0, N1, N2
7+
from starkware.cairo.common.cairo_secp.ec import EcPoint, ec_add, ec_mul
8+
9+
from starkware.cairo.common.math import assert_nn_le, assert_not_zero
10+
11+
// Computes x * s^(-1) modulo the size of the elliptic curve (N).
12+
func mul_s_inv{range_check_ptr}(x : BigInt3, s : BigInt3) -> (res : BigInt3){
13+
%{
14+
from starkware.cairo.common.cairo_secp.secp_utils import pack
15+
from starkware.python.math_utils import div_mod, safe_div
16+
17+
N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
18+
x = pack(ids.x, PRIME) % N
19+
s = pack(ids.s, PRIME) % N
20+
value = res = div_mod(x, s, N)
21+
%}
22+
let (res) = nondet_bigint3();
23+
24+
%{ value = k = safe_div(res * s - x, N) %}
25+
let (k) = nondet_bigint3();
26+
27+
let (res_s) = bigint_mul(res, s);
28+
let n = BigInt3(N0, N1, N2);
29+
let (k_n) = bigint_mul(k, n);
30+
31+
// We should now have res_s = k_n + x. Since the numbers are in unreduced form,
32+
// we should handle the carry.
33+
34+
tempvar carry1 = (res_s.d0 - k_n.d0 - x.d0) / BASE;
35+
assert [range_check_ptr + 0] = carry1 + 2 ** 127;
36+
37+
tempvar carry2 = (res_s.d1 - k_n.d1 - x.d1 + carry1) / BASE;
38+
assert [range_check_ptr + 1] = carry2 + 2 ** 127;
39+
40+
tempvar carry3 = (res_s.d2 - k_n.d2 - x.d2 + carry2) / BASE;
41+
assert [range_check_ptr + 2] = carry3 + 2 ** 127;
42+
43+
tempvar carry4 = (res_s.d3 - k_n.d3 + carry3) / BASE;
44+
assert [range_check_ptr + 3] = carry4 + 2 ** 127;
45+
46+
assert res_s.d4 - k_n.d4 + carry4 = 0;
47+
48+
let range_check_ptr = range_check_ptr + 4;
49+
50+
return (res=res);
51+
}
52+
53+
func main{range_check_ptr} () -> (){
54+
alloc_locals;
55+
let bi1 = BigInt3(0x216936D3CD6E53FEC0A4E, 0x231FDD6DC5C692CC760952, 0x5A7B2C9562D608F25D51A);
56+
let bi2 = BigInt3(0x666666666666666666666, 0x6666666666666666666666, 0x666666666666666666658);
57+
let res = mul_s_inv(bi1, bi2);
58+
assert res = res;
59+
return ();
60+
}

src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ use crate::{
3838
is_zero_assign_scope_variables, is_zero_nondet, is_zero_pack, reduce,
3939
verify_zero,
4040
},
41-
signature::{div_mod_n_packed_divmod, div_mod_n_safe_div, get_point_from_x},
41+
signature::{
42+
div_mod_n_packed_divmod, div_mod_n_safe_div, get_point_from_x,
43+
pack_modn_div_modn,
44+
},
4245
},
4346
segments::{relocate_segment, temporary_array},
4447
set::set_add,
@@ -349,7 +352,7 @@ impl HintProcessor for BuiltinHintProcessor {
349352
&hint_data.ids_data,
350353
&hint_data.ap_tracking,
351354
),
352-
hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes),
355+
hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b"),
353356
hint_code::GET_POINT_FROM_X => get_point_from_x(
354357
vm,
355358
exec_scopes,
@@ -483,6 +486,10 @@ impl HintProcessor for BuiltinHintProcessor {
483486
chained_ec_op_random_ec_point_hint(vm, &hint_data.ids_data, &hint_data.ap_tracking)
484487
}
485488
hint_code::RECOVER_Y => recover_y_hint(vm, &hint_data.ids_data, &hint_data.ap_tracking),
489+
hint_code::PACK_MODN_DIV_MODN => {
490+
pack_modn_div_modn(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
491+
}
492+
hint_code::XS_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "x", "s"),
486493
hint_code::UINT384_UNSIGNED_DIV_REM => {
487494
uint384_unsigned_div_rem(vm, &hint_data.ids_data, &hint_data.ap_tracking)
488495
}

src/hint_processor/builtin_hint_processor/hint_code.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,15 @@ from starkware.python.math_utils import recover_y
662662
ids.p.x = ids.x
663663
# This raises an exception if `x` is not on the curve.
664664
ids.p.y = recover_y(ids.x, ALPHA, BETA, FIELD_PRIME)";
665+
pub(crate) const PACK_MODN_DIV_MODN: &str =
666+
"from starkware.cairo.common.cairo_secp.secp_utils import pack
667+
from starkware.python.math_utils import div_mod, safe_div
668+
669+
N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
670+
x = pack(ids.x, PRIME) % N
671+
s = pack(ids.s, PRIME) % N
672+
value = res = div_mod(x, s, N)";
673+
pub(crate) const XS_SAFE_DIV: &str = "value = k = safe_div(res * s - x, N)";
665674

666675
// The following hints support the lib https://github.com/NethermindEth/research-basic-Cairo-operations-big-integers/blob/main/lib/uint384.cairo
667676
pub const UINT384_UNSIGNED_DIV_REM: &str = "def split(num: int, num_bits_shift: int, length: int):

src/hint_processor/builtin_hint_processor/secp/signature.rs

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,13 @@ pub fn div_mod_n_packed_divmod(
5050

5151
// Implements hint:
5252
// value = k = safe_div(res * b - a, N)
53-
pub fn div_mod_n_safe_div(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> {
54-
let a = exec_scopes.get_ref::<BigInt>("a")?;
55-
let b = exec_scopes.get_ref::<BigInt>("b")?;
53+
pub fn div_mod_n_safe_div(
54+
exec_scopes: &mut ExecutionScopes,
55+
a_alias: &str,
56+
b_alias: &str,
57+
) -> Result<(), HintError> {
58+
let a = exec_scopes.get_ref::<BigInt>(a_alias)?;
59+
let b = exec_scopes.get_ref::<BigInt>(b_alias)?;
5660
let res = exec_scopes.get_ref::<BigInt>("res")?;
5761

5862
let value = safe_div_bigint(&(res * b - a), &N)?;
@@ -103,6 +107,31 @@ pub fn get_point_from_x(
103107
exec_scopes.insert_value("value", y);
104108
Ok(())
105109
}
110+
/* Implements hint:
111+
from starkware.cairo.common.cairo_secp.secp_utils import pack
112+
from starkware.python.math_utils import div_mod, safe_div
113+
114+
N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
115+
x = pack(ids.x, PRIME) % N
116+
s = pack(ids.s, PRIME) % N
117+
value = res = div_mod(x, s, N)
118+
*/
119+
pub fn pack_modn_div_modn(
120+
vm: &mut VirtualMachine,
121+
exec_scopes: &mut ExecutionScopes,
122+
ids_data: &HashMap<String, HintReference>,
123+
ap_tracking: &ApTracking,
124+
) -> Result<(), HintError> {
125+
let x = pack(BigInt3::from_var_name("x", vm, ids_data, ap_tracking)?).mod_floor(&N);
126+
let s = pack(BigInt3::from_var_name("s", vm, ids_data, ap_tracking)?).mod_floor(&N);
127+
128+
let value = div_mod(&x, &s, &N);
129+
exec_scopes.insert_value("x", x);
130+
exec_scopes.insert_value("s", s);
131+
exec_scopes.insert_value("value", value.clone());
132+
exec_scopes.insert_value("res", value);
133+
Ok(())
134+
}
106135

107136
#[cfg(test)]
108137
mod tests {
@@ -147,7 +176,7 @@ mod tests {
147176
let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)];
148177
let mut exec_scopes = ExecutionScopes::new();
149178
assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
150-
assert_matches!(div_mod_n_safe_div(&mut exec_scopes), Ok(()));
179+
assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b"), Ok(()));
151180
}
152181

153182
#[test]
@@ -161,6 +190,8 @@ mod tests {
161190
assert_matches!(
162191
div_mod_n_safe_div(
163192
&mut exec_scopes,
193+
"a",
194+
"b"
164195
),
165196
Err(
166197
HintError::Math(MathError::SafeDivFailBigInt(
@@ -238,4 +269,25 @@ mod tests {
238269
)]
239270
);
240271
}
272+
273+
#[test]
274+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
275+
fn pack_modn_div_modn_ok() {
276+
let hint_code = hint_code::PACK_MODN_DIV_MODN;
277+
let mut vm = vm!();
278+
279+
vm.segments = segments![
280+
((1, 0), 15),
281+
((1, 1), 3),
282+
((1, 2), 40),
283+
((1, 3), 0),
284+
((1, 4), 10),
285+
((1, 5), 1)
286+
];
287+
vm.run_context.fp = 3;
288+
let ids_data = non_continuous_ids_data![("x", -3), ("s", 0)];
289+
let mut exec_scopes = ExecutionScopes::new();
290+
assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
291+
assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "x", "s"), Ok(()));
292+
}
241293
}

src/tests/cairo_run_test.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,13 @@ fn cairo_run_is_quad_residue_test() {
12811281
run_program_simple(program_data.as_slice());
12821282
}
12831283

1284+
#[test]
1285+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1286+
fn cairo_run_mul_s_inv() {
1287+
let program_data = include_bytes!("../../cairo_programs/mul_s_inv.json");
1288+
run_program_simple(program_data.as_slice());
1289+
}
1290+
12841291
#[test]
12851292
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
12861293
fn cairo_run_keccak_alternative_hint() {

0 commit comments

Comments
 (0)