Skip to content

Commit

Permalink
Add REDUCE_V2 hint (#1420)
Browse files Browse the repository at this point in the history
* Rename hint REDUCE -> REDUCE_V1 && implement REDUCE_V2

* Add integration test

* Rename hint REDUCE -> REDUCE_V1 in fuzzer

* update CHANGELOG.md

* unit test

* Add unit test for error
  • Loading branch information
pefontana authored Aug 28, 2023
1 parent 4267138 commit 5f7a147
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

#### Upcoming Changes

* Add REDUCE_V2 hint [#1420](https://github.com/lambdaclass/cairo-vm/pull/1420):
* Implement REDUCE_V2 hint
* Rename hint REDUCE -> REDUCE_V1

* BREAKING: Add `disable_trace_padding` to `CairoRunConfig`[#1233](https://github.com/lambdaclass/cairo-rs/pull/1233)

* feat: Implement `CairoRunner.get_cairo_pie`[#1375](https://github.com/lambdaclass/cairo-vm/pull/1375/files)
Expand Down
38 changes: 38 additions & 0 deletions cairo_programs/reduce.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,45 @@ func test_reduce_ed25519{range_check_ptr}() {
return ();
}

func reduce_v2{range_check_ptr}(x: UnreducedBigInt3) -> (reduced_x: BigInt3) {
let orig_x = x;
%{ from starkware.cairo.common.cairo_secp.secp256r1_utils import SECP256R1_P as SECP_P %}
%{
from starkware.cairo.common.cairo_secp.secp_utils import pack
value = pack(ids.x, PRIME) % SECP_P
%}
let (reduced_x: BigInt3) = nondet_bigint3();
verify_zero(
UnreducedBigInt3(
d0=orig_x.d0 - reduced_x.d0,
d1=orig_x.d1 - reduced_x.d1,
d2=orig_x.d2 - reduced_x.d2
)
);
return (reduced_x=reduced_x);
}
func main{range_check_ptr}() {
test_reduce_ed25519();
// reduce_v2 tests
let x = UnreducedBigInt3(0, 0, 0);
let (reduce_v2_a) = reduce_v2(x);
assert reduce_v2_a = BigInt3(
0, 0, 0
);
let y = UnreducedBigInt3(12354, 745634534, 81298789312879123);
let (reduce_v2_b) = reduce_v2(y);
assert reduce_v2_b = BigInt3(
12354, 745634534, 81298789312879123
);
let z = UnreducedBigInt3(12354812987893128791212331231233, 7453123123123123312634534, 8129224990312325879);
let (reduce_v2_c) = reduce_v2(z);
assert reduce_v2_c = BigInt3(
16653320122975184709085185, 7453123123123123312794216, 8129224990312325879
);
return ();
}
2 changes: 1 addition & 1 deletion fuzzer/src/fuzz_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const HINTS_CODE: [&str; 184] = [
VERIFY_ZERO_V2,
VERIFY_ZERO_V3,
VERIFY_ZERO_EXTERNAL_SECP,
REDUCE,
REDUCE_V1,
REDUCE_ED25519,
UNSAFE_KECCAK,
UNSAFE_KECCAK_FINALIZE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ use crate::{
},
field_utils::{
is_zero_assign_scope_variables, is_zero_assign_scope_variables_external_const,
is_zero_nondet, is_zero_pack, is_zero_pack_external_secp, reduce, verify_zero,
verify_zero_with_external_const,
is_zero_nondet, is_zero_pack, is_zero_pack_external_secp, reduce_v1, reduce_v2,
verify_zero, verify_zero_with_external_const,
},
signature::{
div_mod_n_packed_divmod, div_mod_n_packed_external_n, div_mod_n_safe_div,
Expand Down Expand Up @@ -329,8 +329,11 @@ impl HintProcessorLogic for BuiltinHintProcessor {
hint_code::NONDET_BIGINT3_V1 | hint_code::NONDET_BIGINT3_V2 => {
nondet_bigint3(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::REDUCE => {
reduce(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
hint_code::REDUCE_V1 => {
reduce_v1(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::REDUCE_V2 => {
reduce_v2(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
}
hint_code::REDUCE_ED25519 => {
ed25519_reduce(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
Expand Down
5 changes: 4 additions & 1 deletion vm/src/hint_processor/builtin_hint_processor/hint_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,10 +532,13 @@ q, r = divmod(pack(ids.val, PRIME), SECP_P)
assert r == 0, f"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}."
ids.q = q % PRIME"#;

pub const REDUCE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
pub const REDUCE_V1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
value = pack(ids.x, PRIME) % SECP_P"#;

pub const REDUCE_V2: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack
value = pack(ids.x, PRIME) % SECP_P"#;

pub const REDUCE_ED25519: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack
SECP_P=2**255-19
Expand Down
78 changes: 76 additions & 2 deletions vm/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Implements hint:
value = pack(ids.x, PRIME) % SECP_P
%}
*/
pub fn reduce(
pub fn reduce_v1(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
Expand All @@ -90,6 +90,25 @@ pub fn reduce(
Ok(())
}

/*
Implements hint:
%{
from starkware.cairo.common.cairo_secp.secp_utils import pack
value = pack(ids.x, PRIME) % SECP_P
%}
*/
pub fn reduce_v2(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
let secp_p = exec_scopes.get_ref("SECP_P")?;
let value = Uint384::from_var_name("x", vm, ids_data, ap_tracking)?.pack86();
exec_scopes.insert_value("value", value.mod_floor(secp_p));
Ok(())
}

/*
Implements hint:
%{
Expand Down Expand Up @@ -191,7 +210,7 @@ pub fn is_zero_assign_scope_variables_external_const(
#[cfg(test)]
mod tests {
use super::*;
use crate::hint_processor::builtin_hint_processor::hint_code;
use crate::hint_processor::builtin_hint_processor::hint_code::{self, REDUCE_V2};
use crate::stdlib::string::ToString;

use crate::{
Expand Down Expand Up @@ -395,6 +414,61 @@ mod tests {
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn run_reduce_v2_ok() {
let hint_code = REDUCE_V2;
let mut vm = vm_with_range_check!();
add_segments!(vm, 3);

//Initialize fp
vm.run_context.fp = 25;

//Create hint data
let ids_data = non_continuous_ids_data![("x", -5)];

vm.segments = segments![
((1, 20), ("132181232131231239112312312313213083892150", 10)),
((1, 21), ("12354812987893128791212331231233", 10)),
((1, 22), ("654867675805132187", 10))
];

let mut exec_scopes = ExecutionScopes::new();
exec_scopes.insert_value("SECP_P", SECP_P.clone());
//Execute the hint
assert_matches!(run_hint!(vm, ids_data, 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!(
"3920241379018821570896271640300310233395357371896837069219347149797814"
)
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn run_reduce_v2_with_no_secp() {
let hint_code = REDUCE_V2;
let mut vm = vm_with_range_check!();
add_segments!(vm, 3);

//Initialize fp
vm.run_context.fp = 25;

//Create hint data
let ids_data = non_continuous_ids_data![("x", -5)];

vm.segments = segments![((1, 20), 1), ((1, 21), 1), ((1, 22), 1)];

let mut exec_scopes = ExecutionScopes::new();
// Skip the SECP definition, so the hint fails
// exec_scopes.insert_value("SECP_P", SECP_P.clone());
//Execute the hint
assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Err(_));
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn run_is_zero_pack_ok() {
Expand Down

1 comment on commit 5f7a147

@github-actions
Copy link

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.30.

Benchmark suite Current: 5f7a147 Previous: 4267138 Ratio
add_u64_with_felt/1 3 ns/iter (± 0) 2 ns/iter (± 0) 1.50
add_u64_with_felt/2 3 ns/iter (± 0) 2 ns/iter (± 0) 1.50
add_u64_with_felt/3 2 ns/iter (± 0) 1 ns/iter (± 0) 2
add_u64_with_felt/4 2 ns/iter (± 0) 1 ns/iter (± 0) 2
add_u64_with_felt/5 2 ns/iter (± 0) 1 ns/iter (± 0) 2
add_u64_with_felt/6 4 ns/iter (± 0) 2 ns/iter (± 0) 2
add_u64_with_felt/7 4 ns/iter (± 0) 2 ns/iter (± 0) 2
add_u64_with_felt/8 3 ns/iter (± 0) 2 ns/iter (± 0) 1.50

This comment was automatically generated by workflow using github-action-benchmark.

CC: @unbalancedparentheses

Please sign in to comment.