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

feat(hints): add NewHint#23 #996

Merged
merged 11 commits into from
Apr 18, 2023
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@
* after each step
* ExecutionResource operations: add and substract [#774](https://github.com/lambdaclass/cairo-rs/pull/774), multiplication [#908](https://github.com/lambdaclass/cairo-rs/pull/908) , and `AddAssign` [#914](https://github.com/lambdaclass/cairo-rs/pull/914)

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

`BuiltinHintProcessor` now supports the following hint:
```python
from starkware.python.math_utils import div_mod

value = x_inv = div_mod(1, x, SECP_P)
```


* Add missing hint on cairo_secp lib [#984]:

Expand Down
59 changes: 59 additions & 0 deletions cairo_programs/is_zero.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
%builtins range_check

from starkware.cairo.common.cairo_secp.bigint import BigInt3, UnreducedBigInt3, nondet_bigint3
from starkware.cairo.common.cairo_secp.field import unreduced_mul, verify_zero

// Returns 1 if x == 0 (mod secp256k1_prime), and 0 otherwise.
//
// Completeness assumption: x's limbs are in the range (-BASE, 2*BASE).
// Soundness assumption: x's limbs are in the range (-2**107.49, 2**107.49).
func is_zero{range_check_ptr}(x: BigInt3) -> (res: felt) {
%{
from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack

x = pack(ids.x, PRIME) % SECP_P
%}
if (nondet %{ x == 0 %} != 0) {
verify_zero(UnreducedBigInt3(d0=x.d0, d1=x.d1, d2=x.d2));
return (res=1);
}

%{
from starkware.python.math_utils import div_mod

value = x_inv = div_mod(1, x, SECP_P)
%}
let (x_inv) = nondet_bigint3();
let (x_x_inv) = unreduced_mul(x, x_inv);

// Check that x * x_inv = 1 to verify that x != 0.
verify_zero(UnreducedBigInt3(d0=x_x_inv.d0 - 1, d1=x_x_inv.d1, d2=x_x_inv.d2));
return (res=0);
}

func test_is_zero{range_check_ptr}() -> () {
let zero = BigInt3(0, 0, 0);

let (res: felt) = is_zero(zero);
assert res = 1;

let one = BigInt3(1, 0, 0);

let (res: felt) = is_zero(one);
assert res = 0;

let secp256k1_prime = BigInt3(
77371252455336262886226991, 77371252455336267181195263, 19342813113834066795298815
);

let (res: felt) = is_zero(secp256k1_prime);
assert res = 1;

return ();
}

func main{range_check_ptr}() -> () {
test_is_zero();

return ();
}
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,9 @@ impl HintProcessor for BuiltinHintProcessor {
is_zero_pack(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::IS_ZERO_NONDET => is_zero_nondet(vm, exec_scopes),
hint_code::IS_ZERO_ASSIGN_SCOPE_VARS => is_zero_assign_scope_variables(exec_scopes),
hint_code::IS_ZERO_ASSIGN_SCOPE_VARS_V1 | hint_code::IS_ZERO_ASSIGN_SCOPE_VARS_V2 => {
is_zero_assign_scope_variables(exec_scopes)
}
hint_code::DIV_MOD_N_PACKED_DIVMOD => div_mod_n_packed_divmod(
vm,
exec_scopes,
Expand Down
6 changes: 5 additions & 1 deletion src/hint_processor/builtin_hint_processor/hint_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,11 +432,15 @@ pub(crate) const IS_ZERO_NONDET: &str = "memory[ap] = to_felt_or_relocatable(x =
pub(crate) const IS_ZERO_PACK: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack

x = pack(ids.x, PRIME) % SECP_P"#;
pub(crate) const IS_ZERO_ASSIGN_SCOPE_VARS: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P
pub(crate) const IS_ZERO_ASSIGN_SCOPE_VARS_V1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P
from starkware.python.math_utils import div_mod

value = x_inv = div_mod(1, x, SECP_P)"#;

pub(crate) const IS_ZERO_ASSIGN_SCOPE_VARS_V2: &str = r#"from starkware.python.math_utils import div_mod
MegaRedHand marked this conversation as resolved.
Show resolved Hide resolved

value = x_inv = div_mod(1, x, SECP_P)"#;

pub(crate) const DIV_MOD_N_PACKED_DIVMOD: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import N, pack
from starkware.python.math_utils import div_mod, safe_div

Expand Down
64 changes: 35 additions & 29 deletions src/hint_processor/builtin_hint_processor/secp/field_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,38 +476,44 @@ mod tests {
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn is_zero_assign_scope_variables_ok() {
let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P\nfrom starkware.python.math_utils import div_mod\n\nvalue = x_inv = div_mod(1, x, SECP_P)";
let mut vm = vm_with_range_check!();
let hint_codes = vec![
"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P\nfrom starkware.python.math_utils import div_mod\n\nvalue = x_inv = div_mod(1, x, SECP_P)",
"from starkware.python.math_utils import div_mod\n\nvalue = x_inv = div_mod(1, x, SECP_P)"
];

//Initialize vm scope with variable `x`
let mut exec_scopes = ExecutionScopes::new();
exec_scopes.assign_or_update_variable(
"x",
any_box!(bigint_str!(
"52621538839140286024584685587354966255185961783273479086367"
)),
);
//Execute the hint
assert_matches!(
run_hint!(vm, HashMap::new(), hint_code, &mut exec_scopes),
Ok(())
);
for hint_code in hint_codes {
let mut vm = vm_with_range_check!();

//Check 'value' is defined in the vm scope
assert_matches!(
exec_scopes.get::<BigInt>("value"),
Ok(x) if x == bigint_str!(
"19429627790501903254364315669614485084365347064625983303617500144471999752609"
)
);
//Initialize vm scope with variable `x`
let mut exec_scopes = ExecutionScopes::new();
exec_scopes.assign_or_update_variable(
"x",
any_box!(bigint_str!(
"52621538839140286024584685587354966255185961783273479086367"
)),
);
//Execute the hint
assert_matches!(
run_hint!(vm, HashMap::new(), hint_code, &mut exec_scopes),
Ok(())
);

//Check 'value' is defined in the vm scope
assert_matches!(
exec_scopes.get::<BigInt>("value"),
Ok(x) if x == bigint_str!(
"19429627790501903254364315669614485084365347064625983303617500144471999752609"
)
);

//Check 'x_inv' is defined in the vm scope
assert_matches!(
exec_scopes.get::<BigInt>("x_inv"),
Ok(x) if x == bigint_str!(
"19429627790501903254364315669614485084365347064625983303617500144471999752609"
)
);
//Check 'x_inv' is defined in the vm scope
assert_matches!(
exec_scopes.get::<BigInt>("x_inv"),
Ok(x) if x == bigint_str!(
"19429627790501903254364315669614485084365347064625983303617500144471999752609"
)
);
}
}

#[test]
Expand Down
7 changes: 7 additions & 0 deletions src/tests/cairo_run_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1308,3 +1308,10 @@ fn cairo_run_ed25519_ec() {
let program_data = include_bytes!("../../cairo_programs/ed25519_ec.json");
run_program_simple(program_data.as_slice());
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn cairo_run_is_zero() {
let program_data = include_bytes!("../../cairo_programs/is_zero.json");
run_program_simple(program_data.as_slice());
}