Skip to content

Commit ddc19e7

Browse files
return an error instead of panicking when trying to divide by zero
1 parent 21ec03e commit ddc19e7

File tree

1 file changed

+18
-16
lines changed
  • crates/starknet-types-core/src/felt

1 file changed

+18
-16
lines changed

crates/starknet-types-core/src/felt/qm31.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const MASK_8: u64 = (1 << 8) - 1;
1010
#[derive(Debug)]
1111
pub enum QM31Error {
1212
FeltTooBig(Felt),
13+
InvalidInversion,
1314
}
1415

1516
#[cfg(feature = "std")]
@@ -23,6 +24,7 @@ impl fmt::Display for QM31Error {
2324
"Number used as QM31 since it's more than 144 bits long: {}",
2425
felt
2526
),
27+
QM31Error::InvalidInversion => writeln!(f, "Attempt to invert a qm31 equal to zero"),
2628
}
2729
}
2830
}
@@ -35,7 +37,6 @@ impl QM31Felt {
3537
/// [QM31Felt] constant that's equal to 0.
3638
pub const ZERO: Self = Self([0, 0, 0, 0]);
3739

38-
3940
pub fn as_raw(&self) -> [u64; 4] {
4041
self.0
4142
}
@@ -55,10 +56,10 @@ impl QM31Felt {
5556
result_bytes[0..9].copy_from_slice(&bytes_part1[0..9]);
5657
result_bytes[9..18].copy_from_slice(&bytes_part2[0..9]);
5758

58-
let limbs = {
59+
let limbs = {
5960
let felt = Felt::from_bytes_le_slice(&result_bytes);
6061
felt.to_le_digits()
61-
};
62+
};
6263

6364
Self([
6465
(limbs[0] & MASK_36),
@@ -163,8 +164,10 @@ impl QM31Felt {
163164
/// Computes the inverse of a QM31 element in reduced form.
164165
/// # Safety
165166
/// If the value is zero will panic.
166-
pub fn inverse(&self) -> QM31Felt {
167-
assert_ne!(*self, Self::ZERO, "Zero is not an invertible number");
167+
pub fn inverse(&self) -> Result<QM31Felt, QM31Error> {
168+
if *self == Self::ZERO {
169+
return Err(QM31Error::InvalidInversion);
170+
}
168171

169172
let coordinates = self.as_raw();
170173

@@ -188,7 +191,7 @@ impl QM31Felt {
188191
let denom_inverse_r = (denom_r * denom_norm_inverse_squared) % STWO_PRIME;
189192
let denom_inverse_i = ((STWO_PRIME - denom_i) * denom_norm_inverse_squared) % STWO_PRIME;
190193

191-
Self::from_raw([
194+
Ok(Self::from_raw([
192195
coordinates[0] * denom_inverse_r + STWO_PRIME * STWO_PRIME
193196
- coordinates[1] * denom_inverse_i,
194197
coordinates[0] * denom_inverse_i + coordinates[1] * denom_inverse_r,
@@ -197,14 +200,13 @@ impl QM31Felt {
197200
2 * STWO_PRIME * STWO_PRIME
198201
- coordinates[2] * denom_inverse_i
199202
- coordinates[3] * denom_inverse_r,
200-
])
203+
]))
201204
}
202205

203-
/// Computes the division of two QM31 elements in reduced form.
204-
/// # Safety
205-
/// Will panic if the rhs value is equal to zero.
206+
/// Computes the division of two QM31 elements in reduced form. Returns an error
207+
/// if the rhs value is equal to zero.
206208
pub fn div(&self, rhs: &QM31Felt) -> Result<QM31Felt, QM31Error> {
207-
let rhs_inv = rhs.inverse();
209+
let rhs_inv = rhs.inverse()?;
208210
Ok(self.mul(&rhs_inv))
209211
}
210212

@@ -357,19 +359,19 @@ mod test {
357359
fn test_qm31_packed_reduced_inv() {
358360
let x_coordinates = [1259921049, 1442249570, 1847759065, 2094551481];
359361
let x = QM31Felt::from_raw(x_coordinates);
360-
let res = x.inverse();
362+
let res = x.inverse().unwrap();
361363
let expected = Felt::from(1).try_into().unwrap();
362364
assert_eq!(x.mul(&res), expected);
363365

364366
let x_coordinates = [1, 2, 3, 4];
365367
let x = QM31Felt::from_raw(x_coordinates);
366-
let res = x.inverse();
368+
let res = x.inverse().unwrap();
367369
let expected = Felt::from(1).try_into().unwrap();
368370
assert_eq!(x.mul(&res), expected);
369371

370372
let x_coordinates = [1749652895, 834624081, 1930174752, 2063872165];
371373
let x = QM31Felt::from_raw(x_coordinates);
372-
let res = x.inverse();
374+
let res = x.inverse().unwrap();
373375
let expected = Felt::from(1).try_into().unwrap();
374376
assert_eq!(x.mul(&res), expected);
375377
}
@@ -386,7 +388,7 @@ mod test {
386388
|arr| !arr.iter().all(|x| *x == 0))
387389
) {
388390
let x = QM31Felt::from_raw(x_coordinates);
389-
let res = x.inverse();
391+
let res = x.inverse().unwrap();
390392
// Expect 1_felt252
391393
let expected = QM31Felt::from_raw([1,0,0,0]);
392394
assert_eq!(x.mul(&res), expected);
@@ -400,7 +402,7 @@ mod test {
400402
.no_shrink()
401403
) {
402404
let x = QM31Felt::from_raw(x_coordinates);
403-
let res = x.inverse();
405+
let res = x.inverse().unwrap();
404406
// Expect 1_felt252
405407
let expected = QM31Felt::from_raw([1,0,0,0]);
406408
assert_eq!(x.mul(&res), expected);

0 commit comments

Comments
 (0)