Skip to content

Fix WRITE_DIVMOD_SEGMENT hint #2078

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

Merged
merged 5 commits into from
May 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#### Upcoming Changes

* fix: Use Cairo prime instead of SECP_P in WRITE_DIVMOD_SEGMENT hint [#2078](https://github.com/lambdaclass/cairo-vm/pull/2078)

* feat: add support for alias identifiers destination in program serde [#2071](https://github.com/lambdaclass/cairo-vm/pull/2071)

Expand Down
63 changes: 31 additions & 32 deletions vm/src/hint_processor/builtin_hint_processor/kzg_da/mod.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
use core::str::FromStr;

use super::{
hint_utils::get_relocatable_from_var_name,
secp::{bigint_utils::BigInt3, secp_utils::SECP_P},
};
use super::{hint_utils::get_relocatable_from_var_name, secp::bigint_utils::BigInt3};
use crate::{
hint_processor::hint_processor_definition::HintReference,
serde::deserialize_program::ApTracking,
types::relocatable::MaybeRelocatable,
utils::CAIRO_PRIME,
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
Felt252,
};
use crate::{
stdlib::{collections::HashMap, ops::Deref, prelude::*},
stdlib::{collections::HashMap, prelude::*},
types::exec_scope::ExecutionScopes,
};
use lazy_static::lazy_static;
use num_bigint::BigInt;
use num_bigint::{BigInt, BigUint};
use num_integer::Integer;
use num_traits::FromPrimitive;
use num_traits::Zero;
use num_traits::Signed;

lazy_static! {
static ref BLS_BASE: BigInt = BigInt::from_u64(2).unwrap().pow(86);
Expand Down Expand Up @@ -50,21 +48,21 @@ pub fn write_div_mod_segment(
) -> Result<(), HintError> {
let a = bls_pack(
&BigInt3::from_var_name("a", vm, ids_data, ap_tracking)?,
&SECP_P,
&CAIRO_PRIME,
);
let b = bls_pack(
&BigInt3::from_var_name("b", vm, ids_data, ap_tracking)?,
&SECP_P,
&CAIRO_PRIME,
);
let (q, r) = (a * b).div_mod_floor(&BLS_PRIME);
let q_reloc = get_relocatable_from_var_name("q", vm, ids_data, ap_tracking)?;
let res_reloc = get_relocatable_from_var_name("res", vm, ids_data, ap_tracking)?;

let q_arg: Vec<MaybeRelocatable> = bls_split(q)
let q_arg: Vec<MaybeRelocatable> = bls_split(q)?
.into_iter()
.map(|ref n| Felt252::from(n).into())
.collect::<Vec<MaybeRelocatable>>();
let res_arg: Vec<MaybeRelocatable> = bls_split(r)
let res_arg: Vec<MaybeRelocatable> = bls_split(r)?
.into_iter()
.map(|ref n| Felt252::from(n).into())
.collect::<Vec<MaybeRelocatable>>();
Expand All @@ -74,35 +72,36 @@ pub fn write_div_mod_segment(
Ok(())
}

fn bls_split(mut num: BigInt) -> Vec<BigInt> {
use num_traits::Signed;
let mut a = Vec::new();
fn bls_split(mut num: BigInt) -> Result<Vec<BigInt>, HintError> {
let mut canonical = Vec::new();
for _ in 0..2 {
let residue = &num % BLS_BASE.deref();
num /= BLS_BASE.deref();
a.push(residue);
let (new_num, residue) = num.div_rem(&BLS_BASE);
num = new_num;
canonical.push(residue);
}

if num.abs() >= BigInt::from(1u128 << 127) {
return Err(HintError::BlsSplitError(Box::new(num)));
}
assert!(num.abs() < BigInt::from_u128(1 << 127).unwrap());
a.push(num);
a

canonical.push(num);
Ok(canonical)
}

fn as_int(value: BigInt, prime: &BigInt) -> BigInt {
let half_prime = prime / 2u32;
if value > half_prime {
value - prime
} else {
fn as_int(value: BigInt, prime: &BigUint) -> BigInt {
let half_prime: BigInt = (prime / 2u32).into();
let prime: BigInt = prime.clone().into();
if value < half_prime {
value
} else {
value - prime
}
}

fn bls_pack(z: &BigInt3, prime: &BigInt) -> BigInt {
let limbs = &z.limbs;
limbs
fn bls_pack(z: &BigInt3, prime: &BigUint) -> BigInt {
z.limbs
.iter()
.enumerate()
.fold(BigInt::zero(), |acc, (i, limb)| {
let limb_as_int = as_int(limb.to_bigint(), prime);
acc + limb_as_int * &BLS_BASE.pow(i as u32)
})
.map(|(i, limb)| as_int(limb.to_bigint(), prime) * &BLS_BASE.pow(i as u32))
.sum()
}
2 changes: 2 additions & 0 deletions vm/src/vm/errors/hint_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ pub enum HintError {
EmptyNibbles,
#[error("circuit evalution: {0}")]
CircuitEvaluationFailed(Box<str>),
#[error("high limb magnitude should be smaller than 2 ** 127: {0}")]
BlsSplitError(Box<BigInt>),
}

#[cfg(test)]
Expand Down
Loading