Repository: lambdaclass/cairo-vm (language: rust)

Issue:
Reduce duplicate versions of math hints
Some functions have multiple versions, each one only using a different `UintNNN` wrapper to interact with the VM memory. An example are the `u384_get_square_root` and `u256_get_square_root` functions.

This could be solved by extracting the common interface into a trait, and using generics to write these hints only one time.

An alternative would be to make a generic `UintNNN` struct, but that way we wouldn't be able to add custom "member X doesn't exist" for each variant.

Another alternative would be to add all of these variants into an enum.



Discussion / hints:
> An alternative would be to make a generic UintNNN struct, but that way we wouldn't be able to add custom "member X doesn't exist" for each variant.

I think this is actually possible with a little bit of magic.

Fix patch:
diff --git a/vm/src/hint_processor/builtin_hint_processor/bigint.rs b/vm/src/hint_processor/builtin_hint_processor/bigint.rs
index 25fa23a242..ef0e8abb04 100644
--- a/vm/src/hint_processor/builtin_hint_processor/bigint.rs
+++ b/vm/src/hint_processor/builtin_hint_processor/bigint.rs
@@ -42,13 +42,15 @@ pub fn bigint_pack_div_mod_hint(
         let x_bigint5 = BigInt5::from_var_name("x", vm, ids_data, ap_tracking)?;
         // pack only takes the first three limbs
         let x_lower = BigInt3 {
-            d0: x_bigint5.d0,
-            d1: x_bigint5.d1,
-            d2: x_bigint5.d2,
+            limbs: [
+                x_bigint5.limbs[0].clone(),
+                x_bigint5.limbs[1].clone(),
+                x_bigint5.limbs[2].clone(),
+            ],
         };
         let x_lower = x_lower.pack86();
-        let d3 = x_bigint5.d3.as_ref().to_signed_felt();
-        let d4 = x_bigint5.d4.as_ref().to_signed_felt();
+        let d3 = x_bigint5.limbs[3].as_ref().to_signed_felt();
+        let d4 = x_bigint5.limbs[4].as_ref().to_signed_felt();
         x_lower + d3 * BigInt::from(BASE.pow(3)) + d4 * BigInt::from(BASE.pow(4))
     };
     let y: BigInt = BigInt3::from_var_name("y", vm, ids_data, ap_tracking)?.pack86();
diff --git a/vm/src/hint_processor/builtin_hint_processor/mod.rs b/vm/src/hint_processor/builtin_hint_processor/mod.rs
index 1c1c640e1a..0a3f067b5b 100644
--- a/vm/src/hint_processor/builtin_hint_processor/mod.rs
+++ b/vm/src/hint_processor/builtin_hint_processor/mod.rs
@@ -30,7 +30,6 @@ pub mod squash_dict_utils;
 pub mod uint256_utils;
 pub mod uint384;
 pub mod uint384_extension;
-pub mod uint512_utils;
 pub mod uint_utils;
 pub mod usort;
 pub mod vrf;
diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs b/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs
index 7515eea017..2be1ac58a2 100644
--- a/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs
+++ b/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs
@@ -21,32 +21,33 @@ use felt::Felt252;
 use num_bigint::{BigInt, BigUint};
 use num_traits::Bounded;
 
-// Uint384 and BigInt3 are used interchangeably with BigInt3
-pub(crate) type Uint384<'a> = BigInt3<'a>;
+pub(crate) type BigInt3<'a> = BigIntN<'a, 3>;
+pub(crate) type Uint384<'a> = BigIntN<'a, 3>;
+pub(crate) type Uint512<'a> = BigIntN<'a, 4>;
+pub(crate) type BigInt5<'a> = BigIntN<'a, 5>;
+pub(crate) type Uint768<'a> = BigIntN<'a, 6>;
 
 #[derive(Debug, PartialEq)]
-pub(crate) struct BigInt3<'a> {
-    pub d0: Cow<'a, Felt252>,
-    pub d1: Cow<'a, Felt252>,
-    pub d2: Cow<'a, Felt252>,
+pub(crate) struct BigIntN<'a, const NUM_LIMBS: usize> {
+    pub(crate) limbs: [Cow<'a, Felt252>; NUM_LIMBS],
 }
 
-impl BigInt3<'_> {
+impl<const NUM_LIMBS: usize> BigIntN<'_, NUM_LIMBS> {
     pub(crate) fn from_base_addr<'a>(
         addr: Relocatable,
         name: &str,
         vm: &'a VirtualMachine,
-    ) -> Result<BigInt3<'a>, HintError> {
-        Ok(BigInt3 {
-            d0: vm.get_integer(addr).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d0".to_string())))
-            })?,
-            d1: vm.get_integer((addr + 1)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d1".to_string())))
-            })?,
-            d2: vm.get_integer((addr + 2)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d2".to_string())))
-            })?,
+    ) -> Result<BigIntN<'a, NUM_LIMBS>, HintError> {
+        let mut limbs = vec![];
+        for i in 0..NUM_LIMBS {
+            limbs.push(vm.get_integer((addr + i)?).map_err(|_| {
+                HintError::IdentifierHasNoMember(Box::new((name.to_string(), format!("d{}", i))))
+            })?)
+        }
+        Ok(BigIntN {
+            limbs: limbs
+                .try_into()
+                .map_err(|_| HintError::FixedSizeArrayFail(NUM_LIMBS))?,
         })
     }
 
@@ -55,17 +56,15 @@ impl BigInt3<'_> {
         vm: &'a VirtualMachine,
         ids_data: &HashMap<String, HintReference>,
         ap_tracking: &ApTracking,
-    ) -> Result<BigInt3<'a>, HintError> {
+    ) -> Result<BigIntN<'a, NUM_LIMBS>, HintError> {
         let base_addr = get_relocatable_from_var_name(name, vm, ids_data, ap_tracking)?;
-        BigInt3::from_base_addr(base_addr, name, vm)
+        BigIntN::from_base_addr(base_addr, name, vm)
     }
 
-    pub(crate) fn from_values(limbs: [Felt252; 3]) -> Self {
-        let [d0, d1, d2] = limbs;
-        let d0 = Cow::Owned(d0);
-        let d1 = Cow::Owned(d1);
-        let d2 = Cow::Owned(d2);
-        Self { d0, d1, d2 }
+    pub(crate) fn from_values(limbs: [Felt252; NUM_LIMBS]) -> Self {
+        Self {
+            limbs: limbs.map(Cow::Owned),
+        }
     }
 
     pub(crate) fn insert_from_var_name(
@@ -76,22 +75,20 @@ impl BigInt3<'_> {
         ap_tracking: &ApTracking,
     ) -> Result<(), HintError> {
         let addr = get_relocatable_from_var_name(var_name, vm, ids_data, ap_tracking)?;
-
-        vm.insert_value(addr, self.d0.into_owned())?;
-        vm.insert_value((addr + 1)?, self.d1.into_owned())?;
-        vm.insert_value((addr + 2)?, self.d2.into_owned())?;
-
+        for i in 0..NUM_LIMBS {
+            vm.insert_value((addr + i)?, self.limbs[i].as_ref().clone())?;
+        }
         Ok(())
     }
 
     pub(crate) fn pack(self) -> BigUint {
-        pack([self.d0, self.d1, self.d2], 128)
+        pack(self.limbs, 128)
     }
 
     pub(crate) fn pack86(self) -> BigInt {
-        let limbs = [self.d0, self.d1, self.d2];
-        limbs
+        self.limbs
             .into_iter()
+            .take(3)
             .enumerate()
             .map(|(idx, value)| value.to_signed_felt().shl(idx * 86))
             .sum()
@@ -103,50 +100,12 @@ impl BigInt3<'_> {
     }
 }
 
-#[derive(Debug, PartialEq)]
-pub(crate) struct BigInt5<'a> {
-    pub d0: Cow<'a, Felt252>,
-    pub d1: Cow<'a, Felt252>,
-    pub d2: Cow<'a, Felt252>,
-    pub d3: Cow<'a, Felt252>,
-    pub d4: Cow<'a, Felt252>,
-}
-
-impl BigInt5<'_> {
-    pub(crate) fn from_base_addr<'a>(
-        addr: Relocatable,
-        name: &str,
-        vm: &'a VirtualMachine,
-    ) -> Result<BigInt5<'a>, HintError> {
-        Ok(BigInt5 {
-            d0: vm.get_integer(addr).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d0".to_string())))
-            })?,
-            d1: vm.get_integer((addr + 1)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d1".to_string())))
-            })?,
-            d2: vm.get_integer((addr + 2)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d2".to_string())))
-            })?,
-            d3: vm.get_integer((addr + 3)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d3".to_string())))
-            })?,
-            d4: vm.get_integer((addr + 4)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d4".to_string())))
-            })?,
-        })
-    }
-
-    pub(crate) fn from_var_name<'a>(
-        name: &str,
-        vm: &'a VirtualMachine,
-        ids_data: &HashMap<String, HintReference>,
-        ap_tracking: &ApTracking,
-    ) -> Result<BigInt5<'a>, HintError> {
-        let base_addr = get_relocatable_from_var_name(name, vm, ids_data, ap_tracking)?;
-        BigInt5::from_base_addr(base_addr, name, vm)
+impl<'a, const NUM_LIMBS: usize> From<&'a BigUint> for BigIntN<'a, NUM_LIMBS> {
+    fn from(value: &'a BigUint) -> Self {
+        Self::split(value)
     }
 }
+
 /*
 Implements hint:
 %{
@@ -204,8 +163,8 @@ pub fn hi_max_bitlen(
     let scalar_u = BigInt3::from_var_name("scalar_u", vm, ids_data, ap_tracking)?;
     let scalar_v = BigInt3::from_var_name("scalar_v", vm, ids_data, ap_tracking)?;
 
-    let len_hi_u = scalar_u.d2.bits();
-    let len_hi_v = scalar_v.d2.bits();
+    let len_hi_u = scalar_u.limbs[2].bits();
+    let len_hi_v = scalar_v.limbs[2].bits();
 
     let len_hi = len_hi_u.max(len_hi_v);
 
@@ -318,9 +277,9 @@ mod tests {
         let mut vm = vm!();
         vm.segments = segments![((0, 0), 1), ((0, 1), 2), ((0, 2), 3)];
         let x = BigInt3::from_base_addr((0, 0).into(), "x", &vm).unwrap();
-        assert_eq!(x.d0.as_ref(), &Felt252::one());
-        assert_eq!(x.d1.as_ref(), &Felt252::from(2));
-        assert_eq!(x.d2.as_ref(), &Felt252::from(3));
+        assert_eq!(x.limbs[0].as_ref(), &Felt252::one());
+        assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2));
+        assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3));
     }
 
     #[test]
@@ -335,11 +294,11 @@ mod tests {
             ((0, 4), 5)
         ];
         let x = BigInt5::from_base_addr((0, 0).into(), "x", &vm).unwrap();
-        assert_eq!(x.d0.as_ref(), &Felt252::one());
-        assert_eq!(x.d1.as_ref(), &Felt252::from(2));
-        assert_eq!(x.d2.as_ref(), &Felt252::from(3));
-        assert_eq!(x.d3.as_ref(), &Felt252::from(4));
-        assert_eq!(x.d4.as_ref(), &Felt252::from(5));
+        assert_eq!(x.limbs[0].as_ref(), &Felt252::one());
+        assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2));
+        assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3));
+        assert_eq!(x.limbs[3].as_ref(), &Felt252::from(4));
+        assert_eq!(x.limbs[4].as_ref(), &Felt252::from(5));
     }
 
     #[test]
@@ -373,9 +332,9 @@ mod tests {
         vm.segments = segments![((1, 0), 1), ((1, 1), 2), ((1, 2), 3)];
         let ids_data = ids_data!["x"];
         let x = BigInt3::from_var_name("x", &vm, &ids_data, &ApTracking::default()).unwrap();
-        assert_eq!(x.d0.as_ref(), &Felt252::one());
-        assert_eq!(x.d1.as_ref(), &Felt252::from(2));
-        assert_eq!(x.d2.as_ref(), &Felt252::from(3));
+        assert_eq!(x.limbs[0].as_ref(), &Felt252::one());
+        assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2));
+        assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3));
     }
 
     #[test]
@@ -392,11 +351,11 @@ mod tests {
         ];
         let ids_data = ids_data!["x"];
         let x = BigInt5::from_var_name("x", &vm, &ids_data, &ApTracking::default()).unwrap();
-        assert_eq!(x.d0.as_ref(), &Felt252::one());
-        assert_eq!(x.d1.as_ref(), &Felt252::from(2));
-        assert_eq!(x.d2.as_ref(), &Felt252::from(3));
-        assert_eq!(x.d3.as_ref(), &Felt252::from(4));
-        assert_eq!(x.d4.as_ref(), &Felt252::from(5));
+        assert_eq!(x.limbs[0].as_ref(), &Felt252::one());
+        assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2));
+        assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3));
+        assert_eq!(x.limbs[3].as_ref(), &Felt252::from(4));
+        assert_eq!(x.limbs[4].as_ref(), &Felt252::from(5));
     }
 
     #[test]
@@ -481,9 +440,11 @@ mod tests {
     #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
     fn u384_pack86() {
         let pack_1 = Uint384 {
-            d0: Cow::Borrowed(&Felt252::new(10_i32)),
-            d1: Cow::Borrowed(&Felt252::new(10_i32)),
-            d2: Cow::Borrowed(&Felt252::new(10_i32)),
+            limbs: [
+                Cow::Borrowed(&Felt252::new(10_i32)),
+                Cow::Borrowed(&Felt252::new(10_i32)),
+                Cow::Borrowed(&Felt252::new(10_i32)),
+            ],
         }
         .pack86();
         assert_eq!(
@@ -492,9 +453,11 @@ mod tests {
         );
 
         let pack_2 = Uint384 {
-            d0: Cow::Borrowed(&felt_str!("773712524553362")),
-            d1: Cow::Borrowed(&felt_str!("57408430697461422066401280")),
-            d2: Cow::Borrowed(&felt_str!("1292469707114105")),
+            limbs: [
+                Cow::Borrowed(&felt_str!("773712524553362")),
+                Cow::Borrowed(&felt_str!("57408430697461422066401280")),
+                Cow::Borrowed(&felt_str!("1292469707114105")),
+            ],
         }
         .pack86();
         assert_eq!(
diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs b/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs
index 224f23eadf..ffeb87472f 100644
--- a/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs
+++ b/vm/src/hint_processor/builtin_hint_processor/secp/ec_utils.rs
@@ -1272,12 +1272,12 @@ mod tests {
         let ids_data = ids_data!["e"];
         let ap_tracking = ApTracking::default();
         let e = EcPoint::from_var_name("e", &vm, &ids_data, &ap_tracking).unwrap();
-        assert_eq!(e.x.d0.as_ref(), &Felt252::one());
-        assert_eq!(e.x.d1.as_ref(), &Felt252::from(2));
-        assert_eq!(e.x.d2.as_ref(), &Felt252::from(3));
-        assert_eq!(e.y.d0.as_ref(), &Felt252::from(4));
-        assert_eq!(e.y.d1.as_ref(), &Felt252::from(5));
-        assert_eq!(e.y.d2.as_ref(), &Felt252::from(6));
+        assert_eq!(e.x.limbs[0].as_ref(), &Felt252::one());
+        assert_eq!(e.x.limbs[1].as_ref(), &Felt252::from(2));
+        assert_eq!(e.x.limbs[2].as_ref(), &Felt252::from(3));
+        assert_eq!(e.y.limbs[0].as_ref(), &Felt252::from(4));
+        assert_eq!(e.y.limbs[1].as_ref(), &Felt252::from(5));
+        assert_eq!(e.y.limbs[2].as_ref(), &Felt252::from(6));
     }
 
     #[test]
diff --git a/vm/src/hint_processor/builtin_hint_processor/uint384.rs b/vm/src/hint_processor/builtin_hint_processor/uint384.rs
index 1a643b1a14..9eb25240bd 100644
--- a/vm/src/hint_processor/builtin_hint_processor/uint384.rs
+++ b/vm/src/hint_processor/builtin_hint_processor/uint384.rs
@@ -111,11 +111,11 @@ pub fn add_no_uint384_check(
     // This hint is not from the cairo commonlib, and its lib can be found under different paths, so we cant rely on a full path name
     let shift = get_constant_from_var_name("SHIFT", constants)?.to_biguint();
 
-    let sum_d0 = a.d0.to_biguint() + b.d0.to_biguint();
+    let sum_d0 = a.limbs[0].to_biguint() + b.limbs[0].to_biguint();
     let carry_d0 = Felt252::from((sum_d0 >= shift) as usize);
-    let sum_d1 = a.d1.to_biguint() + b.d1.to_biguint() + carry_d0.to_biguint();
+    let sum_d1 = a.limbs[1].to_biguint() + b.limbs[1].to_biguint() + carry_d0.to_biguint();
     let carry_d1 = Felt252::from((sum_d1 >= shift) as usize);
-    let sum_d2 = a.d2.to_biguint() + b.d2.to_biguint() + carry_d1.to_biguint();
+    let sum_d2 = a.limbs[2].to_biguint() + b.limbs[2].to_biguint() + carry_d1.to_biguint();
     let carry_d2 = Felt252::from((sum_d2 >= shift) as usize);
 
     insert_value_from_var_name("carry_d0", carry_d0, vm, ids_data, ap_tracking)?;
diff --git a/vm/src/hint_processor/builtin_hint_processor/uint384_extension.rs b/vm/src/hint_processor/builtin_hint_processor/uint384_extension.rs
index dd981380bb..27bada5acf 100644
--- a/vm/src/hint_processor/builtin_hint_processor/uint384_extension.rs
+++ b/vm/src/hint_processor/builtin_hint_processor/uint384_extension.rs
@@ -1,111 +1,14 @@
-use super::secp::bigint_utils::Uint384;
-use super::uint_utils::{pack, split};
-use crate::stdlib::{borrow::Cow, boxed::Box, collections::HashMap, prelude::*};
+use super::secp::bigint_utils::{Uint384, Uint768};
+use crate::stdlib::{collections::HashMap, prelude::*};
 use crate::types::errors::math_errors::MathError;
 use crate::{
-    hint_processor::{
-        builtin_hint_processor::hint_utils::get_relocatable_from_var_name,
-        hint_processor_definition::HintReference,
-    },
+    hint_processor::hint_processor_definition::HintReference,
     serde::deserialize_program::ApTracking,
-    types::relocatable::Relocatable,
     vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
 };
-use felt::Felt252;
-use num_bigint::BigUint;
 use num_integer::Integer;
 use num_traits::Zero;
 
-#[derive(Debug, PartialEq)]
-pub(crate) struct Uint768<'a> {
-    pub d0: Cow<'a, Felt252>,
-    pub d1: Cow<'a, Felt252>,
-    pub d2: Cow<'a, Felt252>,
-    pub d3: Cow<'a, Felt252>,
-    pub d4: Cow<'a, Felt252>,
-    pub d5: Cow<'a, Felt252>,
-}
-
-impl Uint768<'_> {
-    pub(crate) fn from_base_addr<'a>(
-        addr: Relocatable,
-        name: &str,
-        vm: &'a VirtualMachine,
-    ) -> Result<Uint768<'a>, HintError> {
-        Ok(Uint768 {
-            d0: vm.get_integer(addr).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d0".to_string())))
-            })?,
-            d1: vm.get_integer((addr + 1)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d1".to_string())))
-            })?,
-            d2: vm.get_integer((addr + 2)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d2".to_string())))
-            })?,
-            d3: vm.get_integer((addr + 3)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d3".to_string())))
-            })?,
-            d4: vm.get_integer((addr + 4)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d4".to_string())))
-            })?,
-            d5: vm.get_integer((addr + 5)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d5".to_string())))
-            })?,
-        })
-    }
-
-    pub(crate) fn from_var_name<'a>(
-        name: &str,
-        vm: &'a VirtualMachine,
-        ids_data: &HashMap<String, HintReference>,
-        ap_tracking: &ApTracking,
-    ) -> Result<Uint768<'a>, HintError> {
-        let base_addr = get_relocatable_from_var_name(name, vm, ids_data, ap_tracking)?;
-        Uint768::from_base_addr(base_addr, name, vm)
-    }
-
-    pub(crate) fn from_values(limbs: [Felt252; 6]) -> Self {
-        let [d0, d1, d2, d3, d4, d5] = limbs;
-        Self {
-            d0: Cow::Owned(d0),
-            d1: Cow::Owned(d1),
-            d2: Cow::Owned(d2),
-            d3: Cow::Owned(d3),
-            d4: Cow::Owned(d4),
-            d5: Cow::Owned(d5),
-        }
-    }
-
-    pub(crate) fn insert_from_var_name(
-        self,
-        var_name: &str,
-        vm: &mut VirtualMachine,
-        ids_data: &HashMap<String, HintReference>,
-        ap_tracking: &ApTracking,
-    ) -> Result<(), HintError> {
-        let addr = get_relocatable_from_var_name(var_name, vm, ids_data, ap_tracking)?;
-
-        vm.insert_value(addr, self.d0.into_owned())?;
-        vm.insert_value((addr + 1)?, self.d1.into_owned())?;
-        vm.insert_value((addr + 2)?, self.d2.into_owned())?;
-        vm.insert_value((addr + 3)?, self.d3.into_owned())?;
-        vm.insert_value((addr + 4)?, self.d4.into_owned())?;
-        vm.insert_value((addr + 5)?, self.d5.into_owned())?;
-
-        Ok(())
-    }
-
-    pub(crate) fn pack(self) -> BigUint {
-        let limbs = [self.d0, self.d1, self.d2, self.d3, self.d4, self.d5];
-        pack(limbs, 128)
-    }
-
-    pub(crate) fn split(num: &BigUint) -> Self {
-        let limbs = split(num, 128);
-        Self::from_values(limbs)
-    }
-}
-
 /* Implements Hint:
        %{
            def split(num: int, num_bits_shift: int, length: int):
@@ -168,6 +71,7 @@ mod tests {
     use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor;
     use crate::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData;
     use crate::hint_processor::builtin_hint_processor::hint_code;
+    use crate::hint_processor::builtin_hint_processor::secp::bigint_utils::Uint768;
     use crate::hint_processor::hint_processor_definition::HintProcessorLogic;
     use crate::types::exec_scope::ExecutionScopes;
     use crate::utils::test_utils::*;
@@ -175,6 +79,7 @@ mod tests {
     use assert_matches::assert_matches;
 
     use felt::felt_str;
+    use felt::Felt252;
     use num_traits::One;
     use rstest::rstest;
     #[cfg(target_arch = "wasm32")]
@@ -193,9 +98,9 @@ mod tests {
             ((1, 5), 6)
         ];
         let x = Uint768::from_base_addr((1, 0).into(), "x", &vm).unwrap();
-        assert_eq!(x.d0.as_ref(), &Felt252::one());
-        assert_eq!(x.d1.as_ref(), &Felt252::from(2));
-        assert_eq!(x.d2.as_ref(), &Felt252::from(3));
+        assert_eq!(x.limbs[0].as_ref(), &Felt252::one());
+        assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2));
+        assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3));
     }
 
     fn assert_is_err_identifier_has_no_member(
@@ -281,9 +186,9 @@ mod tests {
         ];
         let ids_data = ids_data!["x"];
         let x = Uint768::from_var_name("x", &vm, &ids_data, &ApTracking::default()).unwrap();
-        assert_eq!(x.d0.as_ref(), &Felt252::one());
-        assert_eq!(x.d1.as_ref(), &Felt252::from(2));
-        assert_eq!(x.d2.as_ref(), &Felt252::from(3));
+        assert_eq!(x.limbs[0].as_ref(), &Felt252::one());
+        assert_eq!(x.limbs[1].as_ref(), &Felt252::from(2));
+        assert_eq!(x.limbs[2].as_ref(), &Felt252::from(3));
     }
 
     #[test]
diff --git a/vm/src/hint_processor/builtin_hint_processor/uint512_utils.rs b/vm/src/hint_processor/builtin_hint_processor/uint512_utils.rs
deleted file mode 100644
index bec6eb2ef5..0000000000
--- a/vm/src/hint_processor/builtin_hint_processor/uint512_utils.rs
+++ /dev/null
@@ -1,95 +0,0 @@
-use crate::{
-    hint_processor::hint_processor_definition::HintReference,
-    serde::deserialize_program::ApTracking,
-    stdlib::{borrow::Cow, boxed::Box, collections::HashMap, prelude::*},
-    types::relocatable::Relocatable,
-    vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
-};
-use felt::Felt252;
-use num_bigint::BigUint;
-
-use super::{
-    hint_utils::get_relocatable_from_var_name,
-    uint_utils::{pack, split},
-};
-
-pub(crate) struct Uint512<'a> {
-    pub d0: Cow<'a, Felt252>,
-    pub d1: Cow<'a, Felt252>,
-    pub d2: Cow<'a, Felt252>,
-    pub d3: Cow<'a, Felt252>,
-}
-
-impl<'a> Uint512<'a> {
-    pub(crate) fn from_base_addr(
-        addr: Relocatable,
-        name: &str,
-        vm: &'a VirtualMachine,
-    ) -> Result<Self, HintError> {
-        Ok(Self {
-            d0: vm.get_integer(addr).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d0".to_string())))
-            })?,
-            d1: vm.get_integer((addr + 1)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d1".to_string())))
-            })?,
-            d2: vm.get_integer((addr + 2)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d2".to_string())))
-            })?,
-            d3: vm.get_integer((addr + 3)?).map_err(|_| {
-                HintError::IdentifierHasNoMember(Box::new((name.to_string(), "d3".to_string())))
-            })?,
-        })
-    }
-
-    pub(crate) fn from_var_name(
-        name: &str,
-        vm: &'a VirtualMachine,
-        ids_data: &HashMap<String, HintReference>,
-        ap_tracking: &ApTracking,
-    ) -> Result<Self, HintError> {
-        let base_addr = get_relocatable_from_var_name(name, vm, ids_data, ap_tracking)?;
-        Self::from_base_addr(base_addr, name, vm)
-    }
-
-    pub(crate) fn from_values(limbs: [Felt252; 4]) -> Self {
-        let [d0, d1, d2, d3] = limbs;
-        let d0 = Cow::Owned(d0);
-        let d1 = Cow::Owned(d1);
-        let d2 = Cow::Owned(d2);
-        let d3 = Cow::Owned(d3);
-        Self { d0, d1, d2, d3 }
-    }
-
-    pub(crate) fn insert_from_var_name(
-        self,
-        var_name: &str,
-        vm: &mut VirtualMachine,
-        ids_data: &HashMap<String, HintReference>,
-        ap_tracking: &ApTracking,
-    ) -> Result<(), HintError> {
-        let addr = get_relocatable_from_var_name(var_name, vm, ids_data, ap_tracking)?;
-
-        [self.d0, self.d1, self.d2, self.d3]
-            .into_iter()
-            .enumerate()
-            .try_for_each(|(i, limb)| vm.insert_value((addr + i)?, limb.into_owned()))?;
-
-        Ok(())
-    }
-
-    pub(crate) fn pack(self) -> BigUint {
-        pack([self.d0, self.d1, self.d2, self.d3], 128)
-    }
-
-    pub(crate) fn split(num: &'a BigUint) -> Uint512 {
-        let limbs = split(num, 128);
-        Self::from_values(limbs)
-    }
-}
-
-impl<'a> From<&'a BigUint> for Uint512<'a> {
-    fn from(value: &'a BigUint) -> Self {
-        Self::split(value)
-    }
-}
diff --git a/vm/src/hint_processor/builtin_hint_processor/vrf/fq.rs b/vm/src/hint_processor/builtin_hint_processor/vrf/fq.rs
index 3515336ff8..3efac0df3f 100644
--- a/vm/src/hint_processor/builtin_hint_processor/vrf/fq.rs
+++ b/vm/src/hint_processor/builtin_hint_processor/vrf/fq.rs
@@ -1,8 +1,11 @@
 //! Fq stands for "a finite field of q elements"
 
 use crate::{
-    hint_processor::builtin_hint_processor::{uint256_utils::Uint256, uint512_utils::Uint512},
-    hint_processor::hint_processor_definition::HintReference,
+    hint_processor::builtin_hint_processor::uint256_utils::Uint256,
+    hint_processor::{
+        builtin_hint_processor::secp::bigint_utils::Uint512,
+        hint_processor_definition::HintReference,
+    },
     math_utils::div_mod,
     serde::deserialize_program::ApTracking,
     stdlib::{collections::HashMap, prelude::*},
diff --git a/vm/src/hint_processor/builtin_hint_processor/vrf/inv_mod_p_uint512.rs b/vm/src/hint_processor/builtin_hint_processor/vrf/inv_mod_p_uint512.rs
index 3a1280609e..accd67c193 100644
--- a/vm/src/hint_processor/builtin_hint_processor/vrf/inv_mod_p_uint512.rs
+++ b/vm/src/hint_processor/builtin_hint_processor/vrf/inv_mod_p_uint512.rs
@@ -1,5 +1,5 @@
+use crate::hint_processor::builtin_hint_processor::secp::bigint_utils::Uint512;
 use crate::hint_processor::builtin_hint_processor::uint256_utils::Uint256;
-use crate::hint_processor::builtin_hint_processor::uint512_utils::Uint512;
 use crate::stdlib::prelude::String;
 use crate::{
     hint_processor::hint_processor_definition::HintReference, math_utils::div_mod,


Test patch: