Skip to content

Commit

Permalink
crypto-bigint: add init proptests for equivalence with num-bigint
Browse files Browse the repository at this point in the history
Adds an initial set of property-based tests to check equivalence between
`crypto_bigint::U256` and `num_bigint::BigUint`.
  • Loading branch information
tarcieri committed Jul 29, 2021
1 parent 615762c commit cd19cd3
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 1 deletion.
14 changes: 14 additions & 0 deletions .github/workflows/crypto-bigint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,20 @@ jobs:
- run: cargo test --target ${{ matrix.target }} --release --features zeroize
- run: cargo test --target ${{ matrix.target }} --release --all-features

proptests:
runs-on: ubuntu-latest
defaults:
run:
working-directory: crypto-bigint/proptests
steps:
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- run: cargo test

# Cross-compiled tests
cross:
strategy:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
target
**/Cargo.lock
**/*.proptest-regressions
16 changes: 16 additions & 0 deletions crypto-bigint/proptests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "proptests"
version = "0.0.0"
edition = "2018"
publish = false

[lib]
path = "./lib.rs"

[workspace]
members = ["."]

[dependencies]
crypto-bigint = { path = ".." }
num-bigint = "0.4"
proptest = "1"
Empty file added crypto-bigint/proptests/lib.rs
Empty file.
70 changes: 70 additions & 0 deletions crypto-bigint/proptests/tests/equivalence.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//! Equivalence tests between `num-bigint` and `crypto-bigint`

use crypto_bigint::{Encoding, U256};
use num_bigint::BigUint;
use proptest::prelude::*;
use std::mem;

fn to_biguint(uint: &U256) -> BigUint {
BigUint::from_bytes_be(uint.to_be_bytes().as_ref())
}

fn to_uint(big_uint: BigUint) -> U256 {
let mut input = [0u8; U256::BYTE_SIZE];
let encoded = big_uint.to_bytes_be();

match U256::BYTE_SIZE.checked_sub(encoded.len()) {
Some(off) => input[off..].copy_from_slice(&encoded),
None => {
let off = encoded.len() - U256::BYTE_SIZE;
input.copy_from_slice(&encoded[off..]);
}
}

U256::from_be_slice(&input)
}

prop_compose! {
fn uint()(bytes in any::<[u8; 32]>()) -> U256 {
U256::from_be_slice(&bytes)
}
}

proptest! {
#[test]
fn wrapping_add(a in uint(), b in uint()) {
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);

let expected = to_uint(a_bi + b_bi);
let actual = a.wrapping_add(&b);

assert_eq!(expected, actual);
}

#[test]
fn wrapping_sub(mut a in uint(), mut b in uint()) {
if b > a {
mem::swap(&mut a, &mut b);
}

let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);

let expected = to_uint(a_bi - b_bi);
let actual = a.wrapping_sub(&b);

assert_eq!(expected, actual);
}

#[test]
fn wrapping_mul(a in uint(), b in uint()) {
let a_bi = to_biguint(&a);
let b_bi = to_biguint(&b);

let expected = to_uint(a_bi * b_bi);
let actual = a.wrapping_mul(&b);

assert_eq!(expected, actual);
}
}
2 changes: 1 addition & 1 deletion crypto-bigint/src/uint/mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl<const LIMBS: usize> UInt<LIMBS> {

/// Perform wrapping multiplication, discarding overflow.
pub const fn wrapping_mul(&self, rhs: &Self) -> Self {
self.mul_wide(rhs).0
self.mul_wide(rhs).1
}

/// Perform checked multiplication, returning a [`CtOption`] which `is_some`
Expand Down

0 comments on commit cd19cd3

Please sign in to comment.