From 696e0f912ab948245b754e25e3a91eee8901e2a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Fri, 14 Apr 2023 17:30:16 -0300
Subject: [PATCH 01/13] Add NewHint#26

---
 cairo_programs/ed25519_field.cairo            | 54 +++++++++++++++++++
 .../builtin_hint_processor_definition.rs      |  2 +-
 .../builtin_hint_processor/hint_code.rs       |  6 +++
 .../secp/field_utils.rs                       | 53 ++++++++----------
 4 files changed, 82 insertions(+), 33 deletions(-)

diff --git a/cairo_programs/ed25519_field.cairo b/cairo_programs/ed25519_field.cairo
index 955de5f811..95c6db2b65 100644
--- a/cairo_programs/ed25519_field.cairo
+++ b/cairo_programs/ed25519_field.cairo
@@ -51,6 +51,51 @@ func verify_zero{range_check_ptr}(val: UnreducedBigInt3) {
     return ();
 }
 
+// Source: https://github.com/myBraavos/efficient-secp256r1/blob/73cca4d53730cb8b2dcf34e36c7b8f34b96b3230/src/secp256r1/ec.cairo#L106
+func verify_zero_alt{range_check_ptr}(val: UnreducedBigInt3) {
+    let x = val;
+    // Used just to import pack in scope
+    %{
+        from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
+
+        value = pack(ids.x, PRIME) % SECP_P
+    %}
+    nondet_bigint3();
+
+    let q = [ap];
+    %{
+        from starkware.cairo.common.cairo_secp.secp_utils import pack
+
+        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
+    %}
+    let q_biased = [ap + 1];
+    q_biased = q + 2 ** 127, ap++;
+    [range_check_ptr] = q_biased, ap++;
+
+    tempvar r1 = (val.d0 + q * SECP_REM) / BASE;
+    assert [range_check_ptr + 1] = r1 + 2 ** 127;
+    // This implies r1 * BASE = val.d0 + q * SECP_REM (as integers).
+
+    tempvar r2 = (val.d1 + r1) / BASE;
+    assert [range_check_ptr + 2] = r2 + 2 ** 127;
+    // This implies r2 * BASE = val.d1 + r1 (as integers).
+    // Therefore, r2 * BASE**2 = val.d1 * BASE + r1 * BASE.
+
+    assert val.d2 = q * (BASE / 4) - r2;
+    // This implies q * BASE / 4 = val.d2 + r2 (as integers).
+    // Therefore,
+    //   q * BASE**3 / 4 = val.d2 * BASE**2 + r2 * BASE ** 2 =
+    //   val.d2 * BASE**2 + val.d1 * BASE + r1 * BASE =
+    //   val.d2 * BASE**2 + val.d1 * BASE + val.d0 + q * SECP_REM =
+    //   val + q * SECP_REM.
+    // Hence, val = q * (BASE**3 / 4 - SECP_REM) = q * (2**256 - SECP_REM).
+
+    let range_check_ptr = range_check_ptr + 3;
+    return ();
+}
+
 func test_verify_zero{range_check_ptr: felt}() {
     let val = UnreducedBigInt3(0, 0, 0);
 
@@ -59,8 +104,17 @@ func test_verify_zero{range_check_ptr: felt}() {
     return ();
 }
 
+func test_verify_zero_alt{range_check_ptr: felt}() {
+    let val = UnreducedBigInt3(0, 0, 0);
+
+    verify_zero_alt(val);
+
+    return ();
+}
+
 func main{range_check_ptr: felt}() {
     test_verify_zero();
+    test_verify_zero_alt();
 
     return ();
 }
diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
index 58fc12429d..d97bbc37c9 100644
--- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
+++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
@@ -249,7 +249,7 @@ impl HintProcessor for BuiltinHintProcessor {
             hint_code::BLAKE2S_COMPUTE => {
                 compute_blake2s(vm, &hint_data.ids_data, &hint_data.ap_tracking)
             }
-            hint_code::VERIFY_ZERO_V1 | hint_code::VERIFY_ZERO_V2 => {
+            hint_code::VERIFY_ZERO_V1 | hint_code::VERIFY_ZERO_V2 | hint_code::VERIFY_ZERO_V3 => {
                 verify_zero(vm, &hint_data.ids_data, &hint_data.ap_tracking)
             }
             hint_code::NONDET_BIGINT3 => {
diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs
index 1b6e765eb2..43ecf97c4e 100644
--- a/src/hint_processor/builtin_hint_processor/hint_code.rs
+++ b/src/hint_processor/builtin_hint_processor/hint_code.rs
@@ -392,6 +392,12 @@ 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 VERIFY_ZERO_V3: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack
+
+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
 
 value = pack(ids.x, PRIME) % SECP_P"#;
diff --git a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
index 9ee1a3598b..57d4c1c654 100644
--- a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
@@ -154,38 +154,27 @@ mod tests {
     #[test]
     #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
     fn run_verify_zero_ok() {
-        let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME";
-        let mut vm = vm_with_range_check!();
-        //Initialize run_context
-        run_context!(vm, 0, 9, 9);
-        //Create hint data
-        let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)];
-        vm.segments = segments![((1, 4), 0), ((1, 5), 0), ((1, 6), 0)];
-        //Execute the hint
-        assert_matches!(
-            run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
-            Ok(())
-        );
-        //Check hint memory inserts
-        //ids.q
-        check_memory![vm.segments.memory, ((1, 9), 0)];
-    }
-
-    #[test]
-    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
-    fn run_verify_zero_without_pack_ok() {
-        let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME";
-        let mut vm = vm_with_range_check!();
-        //Initialize run_context
-        run_context!(vm, 0, 9, 9);
-        //Create hint data
-        let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)];
-        vm.segments = segments![((1, 4), 0), ((1, 5), 0), ((1, 6), 0)];
-        //Execute the hint
-        assert!(run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()).is_ok());
-        //Check hint memory inserts
-        //ids.q
-        check_memory![vm.segments.memory, ((1, 9), 0)];
+        let hint_codes = vec![
+            "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME",
+            "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME",
+            "from starkware.cairo.common.cairo_secp.secp_utils import pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME",
+        ];
+        for hint_code in hint_codes {
+            let mut vm = vm_with_range_check!();
+            //Initialize run_context
+            run_context!(vm, 0, 9, 9);
+            //Create hint data
+            let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)];
+            vm.segments = segments![((1, 4), 0), ((1, 5), 0), ((1, 6), 0)];
+            //Execute the hint
+            assert_matches!(
+                run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
+                Ok(())
+            );
+            //Check hint memory inserts
+            //ids.q
+            check_memory![vm.segments.memory, ((1, 9), 0)];
+        }
     }
 
     #[test]

From b384db90372c75f275161f59430e6f1b39e8b715 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Fri, 14 Apr 2023 17:36:05 -0300
Subject: [PATCH 02/13] Update changelog

---
 CHANGELOG.md | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b23d95862..f457ed627a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,16 @@
     * Added dynamic layout [#879](https://github.com/lambdaclass/cairo-rs/pull/879)
     * `get_segment_size` was exposed [#934](https://github.com/lambdaclass/cairo-rs/pull/934)
 
+* Add missing hint on cairo_secp lib [#992](https://github.com/lambdaclass/cairo-rs/pull/992):
+
+    `BuiltinHintProcessor` now supports the following hint:
+    ```python
+        from starkware.cairo.common.cairo_secp.secp_utils import pack
+
+        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
+    ```
 
 * Add missing hint on cairo_secp lib [#990](https://github.com/lambdaclass/cairo-rs/pull/990):
 

From 5ed4c05587c6de2bc2c363e2a22867f62d66dd79 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Mon, 17 Apr 2023 11:11:46 -0300
Subject: [PATCH 03/13] Change assert_matches for assert + is_ok

---
 .../builtin_hint_processor/secp/field_utils.rs               | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
index 57d4c1c654..9a80da4aaf 100644
--- a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
@@ -167,10 +167,7 @@ mod tests {
             let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)];
             vm.segments = segments![((1, 4), 0), ((1, 5), 0), ((1, 6), 0)];
             //Execute the hint
-            assert_matches!(
-                run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()),
-                Ok(())
-            );
+            assert!(run_hint!(vm, ids_data, hint_code, exec_scopes_ref!()).is_ok());
             //Check hint memory inserts
             //ids.q
             check_memory![vm.segments.memory, ((1, 9), 0)];

From 67477d98ed9f1a55104c7ca8154988092ed12e59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Mon, 17 Apr 2023 15:06:42 -0300
Subject: [PATCH 04/13] Get and insert SECP_P from scope where applicable

---
 cairo_programs/ed25519_field.cairo            |  2 +-
 .../builtin_hint_processor_definition.rs      | 26 +++++----
 .../builtin_hint_processor/hint_code.rs       |  2 +-
 .../builtin_hint_processor/secp/ec_utils.rs   |  8 ++-
 .../secp/field_utils.rs                       | 57 ++++++++++++++++++-
 .../builtin_hint_processor/secp/signature.rs  |  2 +
 6 files changed, 82 insertions(+), 15 deletions(-)

diff --git a/cairo_programs/ed25519_field.cairo b/cairo_programs/ed25519_field.cairo
index 95c6db2b65..cf5ddb06bd 100644
--- a/cairo_programs/ed25519_field.cairo
+++ b/cairo_programs/ed25519_field.cairo
@@ -54,7 +54,7 @@ func verify_zero{range_check_ptr}(val: UnreducedBigInt3) {
 // Source: https://github.com/myBraavos/efficient-secp256r1/blob/73cca4d53730cb8b2dcf34e36c7b8f34b96b3230/src/secp256r1/ec.cairo#L106
 func verify_zero_alt{range_check_ptr}(val: UnreducedBigInt3) {
     let x = val;
-    // Used just to import pack in scope
+    // Used just to import SECP_P in scope
     %{
         from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
 
diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
index d97bbc37c9..267c102085 100644
--- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
+++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
@@ -1,5 +1,3 @@
-use crate::stdlib::{any::Any, collections::HashMap, prelude::*, rc::Rc};
-
 use crate::{
     hint_processor::{
         builtin_hint_processor::{
@@ -14,6 +12,7 @@ use crate::{
                 default_dict_new, dict_new, dict_read, dict_squash_copy_dict,
                 dict_squash_update_ptr, dict_update, dict_write,
             },
+            ec_utils::{chained_ec_op_random_ec_point_hint, random_ec_point_hint, recover_y_hint},
             find_element_hint::{find_element, search_sorted_lower},
             hint_code,
             keccak_utils::{
@@ -36,7 +35,7 @@ use crate::{
                 },
                 field_utils::{
                     is_zero_assign_scope_variables, is_zero_nondet, is_zero_pack, reduce,
-                    verify_zero,
+                    verify_zero, verify_zero_with_external_const,
                 },
                 signature::{div_mod_n_packed_divmod, div_mod_n_safe_div, get_point_from_x},
             },
@@ -55,6 +54,10 @@ use crate::{
                 split_64, uint256_add, uint256_mul_div_mod, uint256_signed_nn, uint256_sqrt,
                 uint256_unsigned_div_rem,
             },
+            uint384::{
+                add_no_uint384_check, uint384_signed_nn, uint384_split_128, uint384_sqrt,
+                uint384_unsigned_div_rem, uint384_unsigned_div_rem_expanded,
+            },
             usort::{
                 usort_body, usort_enter_scope, verify_multiplicity_assert,
                 verify_multiplicity_body, verify_usort,
@@ -63,6 +66,7 @@ use crate::{
         hint_processor_definition::{HintProcessor, HintReference},
     },
     serde::deserialize_program::ApTracking,
+    stdlib::{any::Any, collections::HashMap, prelude::*, rc::Rc},
     types::exec_scope::ExecutionScopes,
     vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
 };
@@ -71,12 +75,6 @@ use felt::Felt252;
 #[cfg(feature = "skip_next_instruction_hint")]
 use crate::hint_processor::builtin_hint_processor::skip_next_instruction::skip_next_instruction;
 
-use super::ec_utils::{chained_ec_op_random_ec_point_hint, random_ec_point_hint, recover_y_hint};
-use super::uint384::{
-    add_no_uint384_check, uint384_signed_nn, uint384_split_128, uint384_sqrt,
-    uint384_unsigned_div_rem, uint384_unsigned_div_rem_expanded,
-};
-
 pub struct HintProcessorData {
     pub code: String,
     pub ap_tracking: ApTracking,
@@ -249,9 +247,15 @@ impl HintProcessor for BuiltinHintProcessor {
             hint_code::BLAKE2S_COMPUTE => {
                 compute_blake2s(vm, &hint_data.ids_data, &hint_data.ap_tracking)
             }
-            hint_code::VERIFY_ZERO_V1 | hint_code::VERIFY_ZERO_V2 | hint_code::VERIFY_ZERO_V3 => {
-                verify_zero(vm, &hint_data.ids_data, &hint_data.ap_tracking)
+            hint_code::VERIFY_ZERO_V1 | hint_code::VERIFY_ZERO_V2 => {
+                verify_zero(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
             }
+            hint_code::VERIFY_ZERO_EXTERNAL_SECP => verify_zero_with_external_const(
+                vm,
+                exec_scopes,
+                &hint_data.ids_data,
+                &hint_data.ap_tracking,
+            ),
             hint_code::NONDET_BIGINT3 => {
                 nondet_bigint3(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
             }
diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs
index 43ecf97c4e..ae32aef132 100644
--- a/src/hint_processor/builtin_hint_processor/hint_code.rs
+++ b/src/hint_processor/builtin_hint_processor/hint_code.rs
@@ -392,7 +392,7 @@ 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 VERIFY_ZERO_V3: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack
+pub const VERIFY_ZERO_EXTERNAL_SECP: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack
 
 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}."
diff --git a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs
index 049c721d54..dc5822d28f 100644
--- a/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs
@@ -1,5 +1,5 @@
-use crate::stdlib::{collections::HashMap, ops::BitAnd, prelude::*};
 use crate::{
+    any_box,
     hint_processor::{
         builtin_hint_processor::{
             hint_utils::{
@@ -11,6 +11,7 @@ use crate::{
     },
     math_utils::{ec_double_slope, line_slope},
     serde::deserialize_program::ApTracking,
+    stdlib::{collections::HashMap, ops::BitAnd, prelude::*},
     types::exec_scope::ExecutionScopes,
     vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
 };
@@ -58,6 +59,7 @@ pub fn ec_negate(
     ids_data: &HashMap<String, HintReference>,
     ap_tracking: &ApTracking,
 ) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone()));
     //ids.point
     let point_y = (get_relocatable_from_var_name("point", vm, ids_data, ap_tracking)? + 3i32)?;
     let y_bigint3 = BigInt3::from_base_addr(point_y, "point.y", vm)?;
@@ -86,6 +88,7 @@ pub fn compute_doubling_slope(
     ap_tracking: &ApTracking,
     point_alias: &str,
 ) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone()));
     //ids.point
     let point = EcPoint::from_var_name(point_alias, vm, ids_data, ap_tracking)?;
 
@@ -117,6 +120,7 @@ pub fn compute_slope(
     point0_alias: &str,
     point1_alias: &str,
 ) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone()));
     //ids.point0
     let point0 = EcPoint::from_var_name(point0_alias, vm, ids_data, ap_tracking)?;
     //ids.point1
@@ -150,6 +154,7 @@ pub fn ec_double_assign_new_x(
     ids_data: &HashMap<String, HintReference>,
     ap_tracking: &ApTracking,
 ) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone()));
     //ids.slope
     let slope = BigInt3::from_var_name("slope", vm, ids_data, ap_tracking)?;
     //ids.point
@@ -208,6 +213,7 @@ pub fn fast_ec_add_assign_new_x(
     ids_data: &HashMap<String, HintReference>,
     ap_tracking: &ApTracking,
 ) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone()));
     //ids.slope
     let slope = BigInt3::from_var_name("slope", vm, ids_data, ap_tracking)?;
     //ids.point0
diff --git a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
index 9a80da4aaf..c9beb022ff 100644
--- a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
@@ -1,3 +1,4 @@
+use crate::any_box;
 use crate::stdlib::{collections::HashMap, prelude::*};
 
 use crate::{
@@ -30,9 +31,11 @@ Implements hint:
 */
 pub fn verify_zero(
     vm: &mut VirtualMachine,
+    exec_scopes: &mut ExecutionScopes,
     ids_data: &HashMap<String, HintReference>,
     ap_tracking: &ApTracking,
 ) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone()));
     let val = pack(BigInt3::from_var_name("val", vm, ids_data, ap_tracking)?);
     let (q, r) = val.div_rem(&SECP_P);
     if !r.is_zero() {
@@ -42,6 +45,32 @@ pub fn verify_zero(
     insert_value_from_var_name("q", Felt252::new(q), vm, ids_data, ap_tracking)
 }
 
+/*
+Implements hint:
+%{
+    from starkware.cairo.common.cairo_secp.secp_utils import pack
+
+    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 fn verify_zero_with_external_const(
+    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 val = pack(BigInt3::from_var_name("val", vm, ids_data, ap_tracking)?);
+    let (q, r) = val.div_rem(&secp_p);
+    if !r.is_zero() {
+        return Err(HintError::SecpVerifyZero(val));
+    }
+
+    insert_value_from_var_name("q", Felt252::new(q), vm, ids_data, ap_tracking)
+}
+
 /*
 Implements hint:
 %{
@@ -56,6 +85,7 @@ pub fn reduce(
     ids_data: &HashMap<String, HintReference>,
     ap_tracking: &ApTracking,
 ) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone()));
     let value = pack(BigInt3::from_var_name("x", vm, ids_data, ap_tracking)?);
     exec_scopes.insert_value("value", value.mod_floor(&SECP_P));
     Ok(())
@@ -75,6 +105,8 @@ pub fn is_zero_pack(
     ids_data: &HashMap<String, HintReference>,
     ap_tracking: &ApTracking,
 ) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone()));
+
     let x_packed = pack(BigInt3::from_var_name("x", vm, ids_data, ap_tracking)?);
     let x = x_packed.mod_floor(&SECP_P);
     exec_scopes.insert_value("x", x);
@@ -114,6 +146,7 @@ Implements hint:
 %}
 */
 pub fn is_zero_assign_scope_variables(exec_scopes: &mut ExecutionScopes) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone()));
     //Get `x` variable from vm scope
     let x = exec_scopes.get::<BigInt>("x")?;
 
@@ -157,7 +190,6 @@ mod tests {
         let hint_codes = vec![
             "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME",
             "from starkware.cairo.common.cairo_secp.secp_utils import SECP_P\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME",
-            "from starkware.cairo.common.cairo_secp.secp_utils import pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME",
         ];
         for hint_code in hint_codes {
             let mut vm = vm_with_range_check!();
@@ -174,6 +206,29 @@ mod tests {
         }
     }
 
+    #[test]
+    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+    fn run_verify_zero_with_external_const_ok() {
+        let hint_code = "from starkware.cairo.common.cairo_secp.secp_utils import pack\n\nq, r = divmod(pack(ids.val, PRIME), SECP_P)\nassert r == 0, f\"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}.\"\nids.q = q % PRIME";
+        let mut vm = vm_with_range_check!();
+        //Initialize run_context
+        run_context!(vm, 0, 9, 9);
+        //Create hint data
+        let ids_data = non_continuous_ids_data![("val", -5), ("q", 0)];
+        vm.segments = segments![((1, 4), 55), ((1, 5), 0), ((1, 6), 0)];
+
+        let new_secp_p = 55;
+
+        let mut exec_scopes = ExecutionScopes::new();
+        exec_scopes.assign_or_update_variable("SECP_P", any_box!(bigint!(new_secp_p)));
+
+        //Execute the hint
+        assert!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes).is_ok());
+        //Check hint memory inserts
+        //ids.q
+        check_memory![vm.segments.memory, ((1, 9), 1)];
+    }
+
     #[test]
     #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
     fn run_verify_zero_error() {
diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs
index 1f65e56e85..224b9dd171 100644
--- a/src/hint_processor/builtin_hint_processor/secp/signature.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs
@@ -1,3 +1,4 @@
+use crate::any_box;
 use crate::stdlib::{collections::HashMap, ops::Shr, prelude::*};
 
 use crate::{
@@ -83,6 +84,7 @@ pub fn get_point_from_x(
     ap_tracking: &ApTracking,
     constants: &HashMap<String, Felt252>,
 ) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("SECP_P", any_box!(SECP_P.clone()));
     #[allow(deprecated)]
     let beta = constants
         .get(BETA)

From 3b7b8c0fd8173e8ffd01fc933e1b9d5d3d7c1f0e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Mon, 17 Apr 2023 15:28:14 -0300
Subject: [PATCH 05/13] Add NewHint#25

---
 cairo_programs/div_mod_n.cairo                | 117 ++++++++++++++++++
 .../builtin_hint_processor_definition.rs      |   5 +-
 .../builtin_hint_processor/hint_code.rs       |   3 +
 .../builtin_hint_processor/secp/signature.rs  |  21 ++--
 src/tests/cairo_run_test.rs                   |   7 ++
 5 files changed, 142 insertions(+), 11 deletions(-)
 create mode 100644 cairo_programs/div_mod_n.cairo

diff --git a/cairo_programs/div_mod_n.cairo b/cairo_programs/div_mod_n.cairo
new file mode 100644
index 0000000000..13a16d0e2e
--- /dev/null
+++ b/cairo_programs/div_mod_n.cairo
@@ -0,0 +1,117 @@
+%builtins range_check
+
+from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, BASE, bigint_mul
+from starkware.cairo.common.cairo_secp.constants import BETA, N0, N1, N2
+
+// Computes a * b^(-1) modulo the size of the elliptic curve (N).
+//
+// Prover assumptions:
+// * All the limbs of a are in the range (-2 ** 210.99, 2 ** 210.99).
+// * All the limbs of b are in the range (-2 ** 124.99, 2 ** 124.99).
+// * b is in the range [0, 2 ** 256).
+//
+// Soundness assumptions:
+// * The limbs of a are in the range (-2 ** 249, 2 ** 249).
+// * The limbs of b are in the range (-2 ** 159.83, 2 ** 159.83).
+func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) {
+    // just used to import N
+    %{
+        from starkware.cairo.common.cairo_secp.secp_utils import N, pack
+        from starkware.python.math_utils import div_mod, safe_div
+
+        a = pack(ids.a, PRIME)
+        b = pack(ids.b, PRIME)
+        value = res = div_mod(a, b, N)
+    %}
+    let (res) = nondet_bigint3();
+
+    %{ value = k_plus_one = safe_div(res * b - a, N) + 1 %}
+    let (k_plus_one) = nondet_bigint3();
+    let k = BigInt3(d0=k_plus_one.d0 - 1, d1=k_plus_one.d1, d2=k_plus_one.d2);
+
+    let (res_b) = bigint_mul(res, b);
+    let n = BigInt3(N0, N1, N2);
+    let (k_n) = bigint_mul(k, n);
+
+    // We should now have res_b = k_n + a. Since the numbers are in unreduced form,
+    // we should handle the carry.
+
+    tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE;
+    assert [range_check_ptr + 0] = carry1 + 2 ** 127;
+
+    tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE;
+    assert [range_check_ptr + 1] = carry2 + 2 ** 127;
+
+    tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE;
+    assert [range_check_ptr + 2] = carry3 + 2 ** 127;
+
+    tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE;
+    assert [range_check_ptr + 3] = carry4 + 2 ** 127;
+
+    assert res_b.d4 - k_n.d4 + carry4 = 0;
+
+    let range_check_ptr = range_check_ptr + 4;
+
+    return (res=res);
+}
+
+func div_mod_n_alt{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) {
+    %{
+        from starkware.cairo.common.cairo_secp.secp_utils import pack
+        from starkware.python.math_utils import div_mod, safe_div
+
+        a = pack(ids.a, PRIME)
+        b = pack(ids.b, PRIME)
+        value = res = div_mod(a, b, N)
+    %}
+    let (res) = nondet_bigint3();
+
+    %{ value = k_plus_one = safe_div(res * b - a, N) + 1 %}
+    let (k_plus_one) = nondet_bigint3();
+    let k = BigInt3(d0=k_plus_one.d0 - 1, d1=k_plus_one.d1, d2=k_plus_one.d2);
+
+    let (res_b) = bigint_mul(res, b);
+    let n = BigInt3(N0, N1, N2);
+    let (k_n) = bigint_mul(k, n);
+
+    tempvar carry1 = (res_b.d0 - k_n.d0 - a.d0) / BASE;
+    assert [range_check_ptr + 0] = carry1 + 2 ** 127;
+
+    tempvar carry2 = (res_b.d1 - k_n.d1 - a.d1 + carry1) / BASE;
+    assert [range_check_ptr + 1] = carry2 + 2 ** 127;
+
+    tempvar carry3 = (res_b.d2 - k_n.d2 - a.d2 + carry2) / BASE;
+    assert [range_check_ptr + 2] = carry3 + 2 ** 127;
+
+    tempvar carry4 = (res_b.d3 - k_n.d3 + carry3) / BASE;
+    assert [range_check_ptr + 3] = carry4 + 2 ** 127;
+
+    assert res_b.d4 - k_n.d4 + carry4 = 0;
+
+    let range_check_ptr = range_check_ptr + 4;
+
+    return (res=res);
+}
+
+func test_div_mod_n{range_check_ptr: felt}() {
+    let a: BigInt3 = BigInt3(100, 99, 98);
+    let b: BigInt3 = BigInt3(10, 9, 8);
+
+    let (res) = div_mod_n(a, b);
+
+    assert res = BigInt3(
+        3413472211745629263979533, 17305268010345238170172332, 11991751872105858217578135
+    );
+
+    // let (res_alt) = div_mod_n_alt(a, b);
+
+    // assert res_alt = res;
+
+    return ();
+}
+
+func main{range_check_ptr: felt}() {
+    test_div_mod_n();
+
+    return ();
+}
diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
index 7383370e99..3c1f9edbf8 100644
--- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
+++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
@@ -356,7 +356,8 @@ impl HintProcessor for BuiltinHintProcessor {
                 &hint_data.ids_data,
                 &hint_data.ap_tracking,
             ),
-            hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b"),
+            hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b", 0),
+            hint_code::DIV_MOD_N_SAFE_DIV_PLUS_ONE => div_mod_n_safe_div(exec_scopes, "a", "b", 1),
             hint_code::GET_POINT_FROM_X => get_point_from_x(
                 vm,
                 exec_scopes,
@@ -493,7 +494,7 @@ impl HintProcessor for BuiltinHintProcessor {
             hint_code::PACK_MODN_DIV_MODN => {
                 pack_modn_div_modn(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
             }
-            hint_code::XS_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "x", "s"),
+            hint_code::XS_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "x", "s", 0),
             hint_code::UINT384_UNSIGNED_DIV_REM => {
                 uint384_unsigned_div_rem(vm, &hint_data.ids_data, &hint_data.ap_tracking)
             }
diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs
index 6131ead533..c71dfc2ea9 100644
--- a/src/hint_processor/builtin_hint_processor/hint_code.rs
+++ b/src/hint_processor/builtin_hint_processor/hint_code.rs
@@ -449,6 +449,9 @@ value = res = div_mod(a, b, N)"#;
 
 pub const DIV_MOD_N_SAFE_DIV: &str = r#"value = k = safe_div(res * b - a, N)"#;
 
+pub const DIV_MOD_N_SAFE_DIV_PLUS_ONE: &str =
+    r#"value = k_plus_one = safe_div(res * b - a, N) + 1"#;
+
 pub const GET_POINT_FROM_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
 
 x_cube_int = pack(ids.x_cube, PRIME) % SECP_P
diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs
index 84dd9e5979..41ed5f436e 100644
--- a/src/hint_processor/builtin_hint_processor/secp/signature.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs
@@ -1,7 +1,5 @@
-use crate::any_box;
-use crate::stdlib::{collections::HashMap, ops::Shr, prelude::*};
-
 use crate::{
+    any_box,
     hint_processor::{
         builtin_hint_processor::{
             hint_utils::get_integer_from_var_name,
@@ -11,10 +9,11 @@ use crate::{
     },
     math_utils::{div_mod, safe_div_bigint},
     serde::deserialize_program::ApTracking,
+    stdlib::{collections::HashMap, ops::Shr, prelude::*},
     types::exec_scope::ExecutionScopes,
-    vm::errors::hint_errors::HintError,
-    vm::vm_core::VirtualMachine,
+    vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
 };
+use core::ops::Add;
 use felt::Felt252;
 use num_bigint::BigInt;
 use num_integer::Integer;
@@ -55,12 +54,13 @@ pub fn div_mod_n_safe_div(
     exec_scopes: &mut ExecutionScopes,
     a_alias: &str,
     b_alias: &str,
+    to_add: u64,
 ) -> Result<(), HintError> {
     let a = exec_scopes.get_ref::<BigInt>(a_alias)?;
     let b = exec_scopes.get_ref::<BigInt>(b_alias)?;
     let res = exec_scopes.get_ref::<BigInt>("res")?;
 
-    let value = safe_div_bigint(&(res * b - a), &N)?;
+    let value = safe_div_bigint(&(res * b - a), &N)?.add(to_add);
 
     exec_scopes.insert_value("value", value);
     Ok(())
@@ -178,7 +178,9 @@ mod tests {
         let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)];
         let mut exec_scopes = ExecutionScopes::new();
         assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
-        assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b"), Ok(()));
+
+        assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 0), Ok(()));
+        assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 1), Ok(()));
     }
 
     #[test]
@@ -193,7 +195,8 @@ mod tests {
             div_mod_n_safe_div(
                 &mut exec_scopes,
                 "a",
-                "b"
+                "b",
+                0,
             ),
             Err(
                 HintError::Math(MathError::SafeDivFailBigInt(
@@ -290,6 +293,6 @@ mod tests {
         let ids_data = non_continuous_ids_data![("x", -3), ("s", 0)];
         let mut exec_scopes = ExecutionScopes::new();
         assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
-        assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "x", "s"), Ok(()));
+        assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "x", "s", 0), Ok(()));
     }
 }
diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs
index 9429dd94ae..465d51e8f0 100644
--- a/src/tests/cairo_run_test.rs
+++ b/src/tests/cairo_run_test.rs
@@ -1322,3 +1322,10 @@ fn cairo_run_efficient_secp256r1_ec() {
     let program_data = include_bytes!("../../cairo_programs/efficient_secp256r1_ec.json");
     run_program_simple(program_data.as_slice());
 }
+
+#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+fn cairo_run_div_mod_n() {
+    let program_data = include_bytes!("../../cairo_programs/div_mod_n.json");
+    run_program_simple(program_data.as_slice());
+}

From f30f2c9c5499579c7249360f980b4d0810097cc7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Fri, 14 Apr 2023 19:02:12 -0300
Subject: [PATCH 06/13] Add NewHint#24

---
 cairo_programs/div_mod_n.cairo                |  7 +++-
 .../builtin_hint_processor_definition.rs      | 14 ++++---
 .../builtin_hint_processor/hint_code.rs       |  9 ++++-
 .../builtin_hint_processor/secp/signature.rs  | 37 +++++++++++--------
 4 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/cairo_programs/div_mod_n.cairo b/cairo_programs/div_mod_n.cairo
index 13a16d0e2e..ed1c4692c8 100644
--- a/cairo_programs/div_mod_n.cairo
+++ b/cairo_programs/div_mod_n.cairo
@@ -3,6 +3,8 @@
 from starkware.cairo.common.cairo_secp.bigint import BigInt3, nondet_bigint3, BASE, bigint_mul
 from starkware.cairo.common.cairo_secp.constants import BETA, N0, N1, N2
 
+// Source: https://github.com/myBraavos/efficient-secp256r1/blob/73cca4d53730cb8b2dcf34e36c7b8f34b96b3230/src/secp256r1/signature.cairo
+
 // Computes a * b^(-1) modulo the size of the elliptic curve (N).
 //
 // Prover assumptions:
@@ -103,9 +105,10 @@ func test_div_mod_n{range_check_ptr: felt}() {
         3413472211745629263979533, 17305268010345238170172332, 11991751872105858217578135
     );
 
-    // let (res_alt) = div_mod_n_alt(a, b);
+    // test alternative hint
+    let (res_alt) = div_mod_n_alt(a, b);
 
-    // assert res_alt = res;
+    assert res_alt = res;
 
     return ();
 }
diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
index 3c1f9edbf8..4f84a1c851 100644
--- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
+++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
@@ -350,12 +350,14 @@ impl HintProcessor for BuiltinHintProcessor {
             }
             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::DIV_MOD_N_PACKED_DIVMOD => div_mod_n_packed_divmod(
-                vm,
-                exec_scopes,
-                &hint_data.ids_data,
-                &hint_data.ap_tracking,
-            ),
+            hint_code::DIV_MOD_N_PACKED_DIVMOD_V1 | hint_code::DIV_MOD_N_PACKED_DIVMOD_V2 => {
+                div_mod_n_packed_divmod(
+                    vm,
+                    exec_scopes,
+                    &hint_data.ids_data,
+                    &hint_data.ap_tracking,
+                )
+            }
             hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b", 0),
             hint_code::DIV_MOD_N_SAFE_DIV_PLUS_ONE => div_mod_n_safe_div(exec_scopes, "a", "b", 1),
             hint_code::GET_POINT_FROM_X => get_point_from_x(
diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs
index c71dfc2ea9..c4731a4d48 100644
--- a/src/hint_processor/builtin_hint_processor/hint_code.rs
+++ b/src/hint_processor/builtin_hint_processor/hint_code.rs
@@ -440,7 +440,14 @@ from starkware.python.math_utils import div_mod
 
 value = x_inv = div_mod(1, x, SECP_P)"#;
 
-pub const DIV_MOD_N_PACKED_DIVMOD: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import N, pack
+pub const DIV_MOD_N_PACKED_DIVMOD_V1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import N, pack
+from starkware.python.math_utils import div_mod, safe_div
+
+a = pack(ids.a, PRIME)
+b = pack(ids.b, PRIME)
+value = res = div_mod(a, b, N)"#;
+
+pub const DIV_MOD_N_PACKED_DIVMOD_V2: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack
 from starkware.python.math_utils import div_mod, safe_div
 
 a = pack(ids.a, PRIME)
diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs
index 41ed5f436e..96929c7295 100644
--- a/src/hint_processor/builtin_hint_processor/secp/signature.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs
@@ -163,24 +163,29 @@ mod tests {
     #[test]
     #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
     fn safe_div_ok() {
-        let hint_code = hint_code::DIV_MOD_N_PACKED_DIVMOD;
-        let mut vm = vm!();
-
-        vm.segments = segments![
-            ((1, 0), 15),
-            ((1, 1), 3),
-            ((1, 2), 40),
-            ((1, 3), 0),
-            ((1, 4), 10),
-            ((1, 5), 1)
+        let hint_codes = vec![
+            hint_code::DIV_MOD_N_PACKED_DIVMOD_V1,
+            hint_code::DIV_MOD_N_PACKED_DIVMOD_V2,
         ];
-        vm.run_context.fp = 3;
-        let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)];
-        let mut exec_scopes = ExecutionScopes::new();
-        assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
+        for hint_code in hint_codes {
+            let mut vm = vm!();
+
+            vm.segments = segments![
+                ((1, 0), 15),
+                ((1, 1), 3),
+                ((1, 2), 40),
+                ((1, 3), 0),
+                ((1, 4), 10),
+                ((1, 5), 1)
+            ];
+            vm.run_context.fp = 3;
+            let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)];
+            let mut exec_scopes = ExecutionScopes::new();
+            assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
 
-        assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 0), Ok(()));
-        assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 1), Ok(()));
+            assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 0), Ok(()));
+            assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 1), Ok(()));
+        }
     }
 
     #[test]

From ccd5fdf0fdac195489694ca9f350e3928e7b1c6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Fri, 14 Apr 2023 19:06:20 -0300
Subject: [PATCH 07/13] Update changelog

---
 CHANGELOG.md | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index a09ff06ad4..e6e11d7e2d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -31,6 +31,22 @@
     * Added dynamic layout [#879](https://github.com/lambdaclass/cairo-rs/pull/879)
     * `get_segment_size` was exposed [#934](https://github.com/lambdaclass/cairo-rs/pull/934)
 
+* Add missing hints on cairo_secp lib [#994](https://github.com/lambdaclass/cairo-rs/pull/994)::
+
+    `BuiltinHintProcessor` now supports the following hints:
+    ```python
+        from starkware.cairo.common.cairo_secp.secp_utils import pack
+        from starkware.python.math_utils import div_mod, safe_div
+
+        a = pack(ids.a, PRIME)
+        b = pack(ids.b, PRIME)
+        value = res = div_mod(a, b, N)
+    ```
+
+    ```python
+        value = k_plus_one = safe_div(res * b - a, N) + 1
+    ```
+
 * Add missing hint on cairo_secp lib [#992](https://github.com/lambdaclass/cairo-rs/pull/992):
 
     `BuiltinHintProcessor` now supports the following hint:

From 72070025295bc408628088a67a5355c286824c84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Mon, 17 Apr 2023 15:33:29 -0300
Subject: [PATCH 08/13] Appease clippy

---
 src/hint_processor/builtin_hint_processor/secp/field_utils.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
index c9beb022ff..cf9afb1d68 100644
--- a/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/field_utils.rs
@@ -63,7 +63,7 @@ pub fn verify_zero_with_external_const(
 ) -> Result<(), HintError> {
     let secp_p = exec_scopes.get_ref("SECP_P")?;
     let val = pack(BigInt3::from_var_name("val", vm, ids_data, ap_tracking)?);
-    let (q, r) = val.div_rem(&secp_p);
+    let (q, r) = val.div_rem(secp_p);
     if !r.is_zero() {
         return Err(HintError::SecpVerifyZero(val));
     }

From 6f25f00151ef87a41d50d837c814a905cfaaeb9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Mon, 17 Apr 2023 15:36:47 -0300
Subject: [PATCH 09/13] Rename hint codes

---
 .../builtin_hint_processor_definition.rs          | 15 +++++++--------
 .../builtin_hint_processor/hint_code.rs           |  2 +-
 .../builtin_hint_processor/secp/signature.rs      |  2 +-
 3 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
index 4f84a1c851..b1b6a114b8 100644
--- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
+++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
@@ -350,14 +350,13 @@ impl HintProcessor for BuiltinHintProcessor {
             }
             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::DIV_MOD_N_PACKED_DIVMOD_V1 | hint_code::DIV_MOD_N_PACKED_DIVMOD_V2 => {
-                div_mod_n_packed_divmod(
-                    vm,
-                    exec_scopes,
-                    &hint_data.ids_data,
-                    &hint_data.ap_tracking,
-                )
-            }
+            hint_code::DIV_MOD_N_PACKED_DIVMOD_V1
+            | hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N => div_mod_n_packed_divmod(
+                vm,
+                exec_scopes,
+                &hint_data.ids_data,
+                &hint_data.ap_tracking,
+            ),
             hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes, "a", "b", 0),
             hint_code::DIV_MOD_N_SAFE_DIV_PLUS_ONE => div_mod_n_safe_div(exec_scopes, "a", "b", 1),
             hint_code::GET_POINT_FROM_X => get_point_from_x(
diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs
index c4731a4d48..872a6ec5cf 100644
--- a/src/hint_processor/builtin_hint_processor/hint_code.rs
+++ b/src/hint_processor/builtin_hint_processor/hint_code.rs
@@ -447,7 +447,7 @@ a = pack(ids.a, PRIME)
 b = pack(ids.b, PRIME)
 value = res = div_mod(a, b, N)"#;
 
-pub const DIV_MOD_N_PACKED_DIVMOD_V2: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack
+pub const DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import pack
 from starkware.python.math_utils import div_mod, safe_div
 
 a = pack(ids.a, PRIME)
diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs
index 96929c7295..403def8ba1 100644
--- a/src/hint_processor/builtin_hint_processor/secp/signature.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs
@@ -165,7 +165,7 @@ mod tests {
     fn safe_div_ok() {
         let hint_codes = vec![
             hint_code::DIV_MOD_N_PACKED_DIVMOD_V1,
-            hint_code::DIV_MOD_N_PACKED_DIVMOD_V2,
+            hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N,
         ];
         for hint_code in hint_codes {
             let mut vm = vm!();

From 6006cbc884179bbf43fb7a727c19d9a5010df193 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Mon, 17 Apr 2023 15:43:11 -0300
Subject: [PATCH 10/13] Get or insert N from scope

---
 .../builtin_hint_processor_definition.rs      | 11 ++++++--
 .../builtin_hint_processor/secp/signature.rs  | 25 +++++++++++++++++--
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
index b1b6a114b8..9a68a9cf96 100644
--- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
+++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs
@@ -78,6 +78,8 @@ use felt::Felt252;
 #[cfg(feature = "skip_next_instruction_hint")]
 use crate::hint_processor::builtin_hint_processor::skip_next_instruction::skip_next_instruction;
 
+use super::secp::signature::div_mod_n_packed_external_n;
+
 pub struct HintProcessorData {
     pub code: String,
     pub ap_tracking: ApTracking,
@@ -350,8 +352,13 @@ impl HintProcessor for BuiltinHintProcessor {
             }
             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::DIV_MOD_N_PACKED_DIVMOD_V1
-            | hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N => div_mod_n_packed_divmod(
+            hint_code::DIV_MOD_N_PACKED_DIVMOD_V1 => div_mod_n_packed_divmod(
+                vm,
+                exec_scopes,
+                &hint_data.ids_data,
+                &hint_data.ap_tracking,
+            ),
+            hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N => div_mod_n_packed_external_n(
                 vm,
                 exec_scopes,
                 &hint_data.ids_data,
diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs
index 403def8ba1..4b8af9a0dd 100644
--- a/src/hint_processor/builtin_hint_processor/secp/signature.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs
@@ -31,16 +31,17 @@ a = pack(ids.a, PRIME)
 b = pack(ids.b, PRIME)
 value = res = div_mod(a, b, N)
 */
-pub fn div_mod_n_packed_divmod(
+pub fn div_mod_n_packed(
     vm: &mut VirtualMachine,
     exec_scopes: &mut ExecutionScopes,
     ids_data: &HashMap<String, HintReference>,
     ap_tracking: &ApTracking,
+    n: &BigInt,
 ) -> Result<(), HintError> {
     let a = pack(BigInt3::from_var_name("a", vm, ids_data, ap_tracking)?);
     let b = pack(BigInt3::from_var_name("b", vm, ids_data, ap_tracking)?);
 
-    let value = div_mod(&a, &b, &N);
+    let value = div_mod(&a, &b, n);
     exec_scopes.insert_value("a", a);
     exec_scopes.insert_value("b", b);
     exec_scopes.insert_value("value", value.clone());
@@ -48,6 +49,26 @@ pub fn div_mod_n_packed_divmod(
     Ok(())
 }
 
+pub fn div_mod_n_packed_divmod(
+    vm: &mut VirtualMachine,
+    exec_scopes: &mut ExecutionScopes,
+    ids_data: &HashMap<String, HintReference>,
+    ap_tracking: &ApTracking,
+) -> Result<(), HintError> {
+    exec_scopes.assign_or_update_variable("N", any_box!(N.clone()));
+    div_mod_n_packed(vm, exec_scopes, ids_data, ap_tracking, &N)
+}
+
+pub fn div_mod_n_packed_external_n(
+    vm: &mut VirtualMachine,
+    exec_scopes: &mut ExecutionScopes,
+    ids_data: &HashMap<String, HintReference>,
+    ap_tracking: &ApTracking,
+) -> Result<(), HintError> {
+    let n = exec_scopes.get::<BigInt>("N")?;
+    div_mod_n_packed(vm, exec_scopes, ids_data, ap_tracking, &n)
+}
+
 // Implements hint:
 // value = k = safe_div(res * b - a, N)
 pub fn div_mod_n_safe_div(

From e8afdabe7b93c6f3746a7f43a155a1a81bddcf22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Mon, 17 Apr 2023 15:45:24 -0300
Subject: [PATCH 11/13] Change test contract

---
 cairo_programs/div_mod_n.cairo | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/cairo_programs/div_mod_n.cairo b/cairo_programs/div_mod_n.cairo
index ed1c4692c8..4dbe3c8290 100644
--- a/cairo_programs/div_mod_n.cairo
+++ b/cairo_programs/div_mod_n.cairo
@@ -16,7 +16,6 @@ from starkware.cairo.common.cairo_secp.constants import BETA, N0, N1, N2
 // * The limbs of a are in the range (-2 ** 249, 2 ** 249).
 // * The limbs of b are in the range (-2 ** 159.83, 2 ** 159.83).
 func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) {
-    // just used to import N
     %{
         from starkware.cairo.common.cairo_secp.secp_utils import N, pack
         from starkware.python.math_utils import div_mod, safe_div
@@ -58,6 +57,16 @@ func div_mod_n{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) {
 }
 
 func div_mod_n_alt{range_check_ptr}(a: BigInt3, b: BigInt3) -> (res: BigInt3) {
+    // just used to import N
+    %{
+        from starkware.cairo.common.cairo_secp.secp_utils import N, pack
+        from starkware.python.math_utils import div_mod, safe_div
+
+        a = pack(ids.a, PRIME)
+        b = pack(ids.b, PRIME)
+        value = res = div_mod(a, b, N)
+    %}
+
     %{
         from starkware.cairo.common.cairo_secp.secp_utils import pack
         from starkware.python.math_utils import div_mod, safe_div

From e82a5bd294588ba42dd5ae7e3db5494fbf032abc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Mon, 17 Apr 2023 16:07:32 -0300
Subject: [PATCH 12/13] Fix test

---
 src/hint_processor/builtin_hint_processor/secp/signature.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs
index 4b8af9a0dd..24789e256c 100644
--- a/src/hint_processor/builtin_hint_processor/secp/signature.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs
@@ -184,6 +184,10 @@ mod tests {
     #[test]
     #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
     fn safe_div_ok() {
+        // "import N"
+        let mut exec_scopes = ExecutionScopes::new();
+        exec_scopes.assign_or_update_variable("N", any_box!(N.clone()));
+
         let hint_codes = vec![
             hint_code::DIV_MOD_N_PACKED_DIVMOD_V1,
             hint_code::DIV_MOD_N_PACKED_DIVMOD_EXTERNAL_N,

From 79169989164de0d8e9e6c5d42253a61a2373932c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1s?= <tomas.gruner@lambdaclass.com>
Date: Mon, 17 Apr 2023 16:09:08 -0300
Subject: [PATCH 13/13] Fix test (for real this time)

---
 src/hint_processor/builtin_hint_processor/secp/signature.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/hint_processor/builtin_hint_processor/secp/signature.rs b/src/hint_processor/builtin_hint_processor/secp/signature.rs
index 24789e256c..54b13b0bf4 100644
--- a/src/hint_processor/builtin_hint_processor/secp/signature.rs
+++ b/src/hint_processor/builtin_hint_processor/secp/signature.rs
@@ -205,7 +205,7 @@ mod tests {
             ];
             vm.run_context.fp = 3;
             let ids_data = non_continuous_ids_data![("a", -3), ("b", 0)];
-            let mut exec_scopes = ExecutionScopes::new();
+
             assert_matches!(run_hint!(vm, ids_data, hint_code, &mut exec_scopes), Ok(()));
 
             assert_matches!(div_mod_n_safe_div(&mut exec_scopes, "a", "b", 0), Ok(()));