Skip to content

Commit f7e69ad

Browse files
JulianGCalderongabrielbosio
authored andcommitted
Fix into_u96_guarantee not handling other types (#1171)
* Add track_caller * Fix into u96 guarantee Now it handles both: - BoundedInts with non zero lower range - Smaller integers * Add tests * Document and refactor implementation
1 parent 6275e40 commit f7e69ad

File tree

3 files changed

+114
-7
lines changed

3 files changed

+114
-7
lines changed

src/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ pub mod panic {
155155
impl std::error::Error for NativeAssertError {}
156156

157157
impl NativeAssertError {
158+
#[track_caller]
158159
pub fn new(msg: String) -> Self {
159160
let backtrace = Backtrace::capture();
160161
let info = if BacktraceStatus::Captured == backtrace.status() {

src/libfuncs/circuit.rs

Lines changed: 95 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::{
77
error::{Result, SierraAssertError},
88
libfuncs::r#struct::build_struct_value,
99
metadata::MetadataStorage,
10+
native_panic,
1011
types::{circuit::build_u384_struct_type, TypeBuilder},
1112
utils::{get_integer_layout, layout_repeat, BlockExt, ProgramRegistryExt},
1213
};
@@ -33,6 +34,7 @@ use melior::{
3334
},
3435
Context,
3536
};
37+
use num_traits::Signed;
3638

3739
/// Select and call the correct libfunc builder function from the selector.
3840
pub fn build<'ctx, 'this>(
@@ -66,11 +68,10 @@ pub fn build<'ctx, 'this>(
6668
CircuitConcreteLibfunc::FailureGuaranteeVerify(info) => build_failure_guarantee_verify(
6769
context, registry, entry, location, helper, metadata, info,
6870
),
69-
CircuitConcreteLibfunc::IntoU96Guarantee(SignatureAndTypeConcreteLibfunc {
70-
signature,
71-
..
72-
})
73-
| CircuitConcreteLibfunc::U96SingleLimbLessThanGuaranteeVerify(
71+
CircuitConcreteLibfunc::IntoU96Guarantee(info) => {
72+
build_into_u96_guarantee(context, registry, entry, location, helper, metadata, info)
73+
}
74+
CircuitConcreteLibfunc::U96SingleLimbLessThanGuaranteeVerify(
7475
SignatureOnlyConcreteLibfunc { signature, .. },
7576
)
7677
| CircuitConcreteLibfunc::U96GuaranteeVerify(SignatureOnlyConcreteLibfunc { signature }) => {
@@ -1083,6 +1084,52 @@ fn build_array_slice<'ctx>(
10831084
)
10841085
}
10851086

1087+
/// Converts input to an U96Guarantee.
1088+
/// Input type must fit inside of an u96.
1089+
///
1090+
/// # Signature
1091+
/// ```cairo
1092+
/// extern fn into_u96_guarantee<T>(val: T) -> U96Guarantee nopanic;
1093+
/// ```
1094+
fn build_into_u96_guarantee<'ctx, 'this>(
1095+
context: &'ctx Context,
1096+
registry: &ProgramRegistry<CoreType, CoreLibfunc>,
1097+
entry: &'this Block<'ctx>,
1098+
location: Location<'ctx>,
1099+
helper: &LibfuncHelper<'ctx, 'this>,
1100+
_metadata: &mut MetadataStorage,
1101+
info: &SignatureAndTypeConcreteLibfunc,
1102+
) -> Result<()> {
1103+
let src = entry.argument(0)?.into();
1104+
1105+
let src_ty = registry.get_type(&info.param_signatures()[0].ty)?;
1106+
1107+
let src_range = src_ty.integer_range(registry)?;
1108+
1109+
// We expect the input value to be unsigned, but we check it just in case.
1110+
if src_range.lower.is_negative() {
1111+
native_panic!("into_u96_guarantee expects an unsigned integer")
1112+
}
1113+
1114+
// Extend the input value to an u96
1115+
let mut dst = entry.extui(src, IntegerType::new(context, 96).into(), location)?;
1116+
1117+
// If the lower bound is positive, we offset the value by the lower bound
1118+
// to obtain the actual value.
1119+
if src_range.lower.is_positive() {
1120+
let klower = entry.const_int_from_type(
1121+
context,
1122+
location,
1123+
src_range.lower,
1124+
IntegerType::new(context, 96).into(),
1125+
)?;
1126+
dst = entry.addi(dst, klower, location)?
1127+
}
1128+
1129+
entry.append_operation(helper.br(0, &[dst], location));
1130+
Ok(())
1131+
}
1132+
10861133
#[cfg(test)]
10871134
mod test {
10881135

@@ -1094,8 +1141,8 @@ mod test {
10941141
values::Value,
10951142
};
10961143
use cairo_lang_sierra::extensions::utils::Range;
1097-
use num_bigint::BigUint;
1098-
use num_traits::Num;
1144+
use num_bigint::{BigInt, BigUint};
1145+
use num_traits::{Num, One};
10991146
use starknet_types_core::felt::Felt;
11001147

11011148
fn u384(limbs: [&str; 4]) -> Value {
@@ -1404,4 +1451,45 @@ mod test {
14041451
),
14051452
);
14061453
}
1454+
1455+
#[test]
1456+
fn run_into_u96_guarantee() {
1457+
let program = load_cairo!(
1458+
use core::circuit::{into_u96_guarantee, U96Guarantee};
1459+
use core::internal::bounded_int::BoundedInt;
1460+
1461+
fn main() -> (U96Guarantee, U96Guarantee, U96Guarantee) {
1462+
(
1463+
into_u96_guarantee::<BoundedInt<0, 79228162514264337593543950335>>(123),
1464+
into_u96_guarantee::<BoundedInt<100, 1000>>(123),
1465+
into_u96_guarantee::<u8>(123),
1466+
)
1467+
}
1468+
);
1469+
1470+
let range = Range {
1471+
lower: BigInt::ZERO,
1472+
upper: BigInt::one() << 96,
1473+
};
1474+
1475+
run_program_assert_output(
1476+
&program,
1477+
"main",
1478+
&[],
1479+
jit_struct!(
1480+
Value::BoundedInt {
1481+
value: 123.into(),
1482+
range: range.clone()
1483+
},
1484+
Value::BoundedInt {
1485+
value: 123.into(),
1486+
range: range.clone()
1487+
},
1488+
Value::BoundedInt {
1489+
value: 123.into(),
1490+
range: range.clone()
1491+
}
1492+
),
1493+
);
1494+
}
14071495
}

src/values.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::{
1515
use bumpalo::Bump;
1616
use cairo_lang_sierra::{
1717
extensions::{
18+
circuit::CircuitTypeConcrete,
1819
core::{CoreLibfunc, CoreType, CoreTypeConcrete},
1920
starknet::{secp256::Secp256PointTypeConcrete, StarknetTypeConcrete},
2021
utils::Range,
@@ -966,6 +967,23 @@ impl Value {
966967
range: info.range.clone(),
967968
}
968969
}
970+
CoreTypeConcrete::Circuit(CircuitTypeConcrete::U96Guarantee(_)) => {
971+
let data = BigInt::from_biguint(
972+
Sign::Plus,
973+
BigUint::from_bytes_le(slice::from_raw_parts(
974+
ptr.cast::<u8>().as_ptr(),
975+
12,
976+
)),
977+
);
978+
979+
Self::BoundedInt {
980+
value: data.into(),
981+
range: Range {
982+
lower: BigInt::ZERO,
983+
upper: BigInt::one() << 96,
984+
},
985+
}
986+
}
969987
CoreTypeConcrete::Coupon(_)
970988
| CoreTypeConcrete::Circuit(_)
971989
| CoreTypeConcrete::RangeCheck96(_) => native_panic!("implement from_ptr"),

0 commit comments

Comments
 (0)