Skip to content

Commit

Permalink
Add property testing for Felt bit shifts (#701)
Browse files Browse the repository at this point in the history
* add property testing for left bit shift

* decrease the size of the right-hand operator

* add property based testing for right bit shift

* reduced the size of the shift amount

* added comments describing each test

* improved one of the comments

* added a space

* fix delimiters {}

* fixed conflict

Co-authored-by: Martina <martina@martina>
Co-authored-by: Juan Rigada <62958725+Jrigada@users.noreply.github.com>
  • Loading branch information
3 people authored Jan 12, 2023
1 parent e7c8c8e commit 874e6e0
Showing 1 changed file with 31 additions and 7 deletions.
38 changes: 31 additions & 7 deletions felt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,16 @@ mod test {

proptest! {
#[test]
// Property-based test that ensures, for 100 felt values that are randomly generated each time tests are run, that a new felt doesn't fall outside the range [0, p].
// In this and some of the following tests, The value of {x} can be either [0] or a very large number, in order to try to overflow the value of {p} and thus ensure the modular arithmetic is working correctly.
fn new_in_range(ref x in "(0|[1-9][0-9]*)") {
let x = &Felt::parse_bytes(x.as_bytes(), 10).unwrap();
let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
prop_assert!(&x.to_biguint() < p);
}

#[test]
// Property-based test that ensures, for 100 {x} and {y} values that are randomly generated each time tests are run, that a multiplication between two felts {x} and {y} and doesn't fall outside the range [0, p]. The values of {x} and {y} can be either [0] or a very large number.
fn mul_in_range(ref x in "(0|[1-9][0-9]*)", ref y in "(0|[1-9][0-9]*)") {
let x = &Felt::parse_bytes(x.as_bytes(), 10).unwrap();
let y = &Felt::parse_bytes(y.as_bytes(), 10).unwrap();
Expand All @@ -177,6 +180,7 @@ mod test {
}

#[test]
// Property-based test that ensures, for 100 {x} and {y} values that are randomly generated each time tests are run, that the result of the division of {x} by {y} is the inverse multiplicative of {x} --that is, multiplying the result by {y} returns the original number {x}. The values of {x} and {y} can be either [0] or a very large number.
fn div_is_mul_inv(ref x in "(0|[1-9][0-9]*)", ref y in "[1-9][0-9]*") {
prop_assume!("0" != y);

Expand All @@ -191,15 +195,23 @@ mod test {
}

#[test]
// Property-based test that ensures, for 100 values {x} that are randomly generated each time tests are run, that raising {x} to the {y}th power returns a result that is inside of the range [0, p].
fn pow_in_range(ref x in "(0|[1-9][0-9]*)", ref y in "[0-9]{1,2}"){
let base = &Felt::parse_bytes(x.as_bytes(), 10).unwrap();
let exponent:u32 = y.parse()?;
// Property-based test that ensures, for 100 {value}s that are randomly generated each time tests are run, that performing a bit shift to the left by {shift_amount} of bits (between 0 and 999) returns a result that is inside of the range [0, p].
fn shift_left_in_range(ref value in "(0|[1-9][0-9]*)", ref shift_amount in "[0-9]{1,3}"){
let value = Felt::parse_bytes(value.as_bytes(), 10).unwrap();
let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
let shift_amount:u32 = shift_amount.parse::<u32>().unwrap();
let result = (value << shift_amount).to_biguint();
prop_assert!(&result < p);
}

let result = Pow::pow(base, exponent);
let as_uint = &result.to_biguint();
prop_assert!(as_uint < p, "{}", as_uint);
#[test]
// Property-based test that ensures, for 100 {value}s that are randomly generated each time tests are run, that performing a bit shift to the right by {shift_amount} of bits (between 0 and 999) returns a result that is inside of the range [0, p].
fn shift_right_in_range(ref value in "(0|[1-9][0-9]*)", ref shift_amount in "[0-9]{1,3}"){
let value = Felt::parse_bytes(value.as_bytes(), 10).unwrap();
let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();
let shift_amount:u32 = shift_amount.parse::<u32>().unwrap();
let result = (value >> shift_amount).to_biguint();
prop_assert!(&result < p);
}

#[test]
Expand All @@ -213,5 +225,17 @@ mod test {
value.to_biguint();
prop_assert!(value < p);
}

#[test]
// Property-based test that ensures, for 100 values {x} that are randomly generated each time tests are run, that raising {x} to the {y}th power returns a result that is inside of the range [0, p].
fn pow_in_range(ref x in "(0|[1-9][0-9]*)", ref y in "[0-9]{1,2}"){
let base = &Felt::parse_bytes(x.as_bytes(), 10).unwrap();
let exponent:u32 = y.parse()?;
let p = &BigUint::parse_bytes(PRIME_STR[2..].as_bytes(), 16).unwrap();

let result = Pow::pow(base, exponent);
let as_uint = &result.to_biguint();
prop_assert!(as_uint < p, "{}", as_uint);
}
}
}

0 comments on commit 874e6e0

Please sign in to comment.