ark-r1cs-std 0.6.0

A standard library for constraint system gadgets
Documentation
use ark_relations::gr1cs::{ConstraintSystem, SynthesisError};
use std::ops::RangeInclusive;

use crate::test_utils::{self, modes};

use super::*;

pub(crate) fn test_unary_op<T: PrimUInt, const N: usize, F: PrimeField>(
    a: T,
    mode: AllocationMode,
    test: impl FnOnce(UInt<N, T, F>) -> Result<(), SynthesisError>,
) -> Result<(), SynthesisError> {
    let cs = ConstraintSystem::<F>::new_ref();
    let a = UInt::<N, T, F>::new_variable(cs.clone(), || Ok(a), mode)?;
    test(a)
}

pub(crate) fn test_binary_op<T: PrimUInt, const N: usize, F: PrimeField>(
    a: T,
    b: T,
    mode_a: AllocationMode,
    mode_b: AllocationMode,
    test: impl FnOnce(UInt<N, T, F>, UInt<N, T, F>) -> Result<(), SynthesisError>,
) -> Result<(), SynthesisError> {
    let cs = ConstraintSystem::<F>::new_ref();
    let a = UInt::<N, T, F>::new_variable(cs.clone(), || Ok(a), mode_a)?;
    let b = UInt::<N, T, F>::new_variable(cs.clone(), || Ok(b), mode_b)?;
    test(a, b)
}

pub(crate) fn test_binary_op_with_native<T: PrimUInt, const N: usize, F: PrimeField>(
    a: T,
    b: T,
    mode_a: AllocationMode,
    test: impl FnOnce(UInt<N, T, F>, T) -> Result<(), SynthesisError>,
) -> Result<(), SynthesisError> {
    let cs = ConstraintSystem::<F>::new_ref();
    let a = UInt::<N, T, F>::new_variable(cs.clone(), || Ok(a), mode_a)?;
    test(a, b)
}

pub(crate) fn run_binary_random_both<const ITERATIONS: usize, const N: usize, T, F>(
    test: impl Fn(UInt<N, T, F>, UInt<N, T, F>) -> Result<(), SynthesisError> + Copy,
    test_native: impl Fn(UInt<N, T, F>, T) -> Result<(), SynthesisError> + Copy,
) -> Result<(), SynthesisError>
where
    T: PrimUInt,
    F: PrimeField,
{
    let mut rng = ark_std::test_rng();

    for _ in 0..ITERATIONS {
        for mode_a in modes() {
            let a = T::rand(&mut rng);
            for mode_b in modes() {
                let b = T::rand(&mut rng);
                test_binary_op(a, b, mode_a, mode_b, test)?;
                test_binary_op_with_native(a, b, mode_a, test_native)?;
            }
        }
    }
    Ok(())
}

pub(crate) fn run_binary_random<const ITERATIONS: usize, const N: usize, T, F>(
    test: impl Fn(UInt<N, T, F>, UInt<N, T, F>) -> Result<(), SynthesisError> + Copy,
) -> Result<(), SynthesisError>
where
    T: PrimUInt,
    F: PrimeField,
{
    let mut rng = ark_std::test_rng();

    for _ in 0..ITERATIONS {
        for mode_a in modes() {
            let a = T::rand(&mut rng);
            for mode_b in modes() {
                let b = T::rand(&mut rng);
                test_binary_op(a, b, mode_a, mode_b, test)?;
            }
        }
    }
    Ok(())
}

pub(crate) fn run_binary_exhaustive<const N: usize, T, F>(
    test: impl Fn(UInt<N, T, F>, UInt<N, T, F>) -> Result<(), SynthesisError> + Copy,
) -> Result<(), SynthesisError>
where
    T: PrimUInt,
    F: PrimeField,
    RangeInclusive<T>: Iterator<Item = T>,
{
    for (mode_a, a) in test_utils::combination(T::min_value()..=T::max_value()) {
        for (mode_b, b) in test_utils::combination(T::min_value()..=T::max_value()) {
            test_binary_op(a, b, mode_a, mode_b, test)?;
        }
    }
    Ok(())
}

pub(crate) fn run_binary_exhaustive_both<const N: usize, T, F>(
    test: impl Fn(UInt<N, T, F>, UInt<N, T, F>) -> Result<(), SynthesisError> + Copy,
    test_native: impl Fn(UInt<N, T, F>, T) -> Result<(), SynthesisError> + Copy,
) -> Result<(), SynthesisError>
where
    T: PrimUInt,
    F: PrimeField,
    RangeInclusive<T>: Iterator<Item = T>,
{
    for (mode_a, a) in test_utils::combination(T::min_value()..=T::max_value()) {
        for (mode_b, b) in test_utils::combination(T::min_value()..=T::max_value()) {
            test_binary_op(a, b, mode_a, mode_b, test)?;
        }
        for b in T::min_value()..=T::max_value() {
            test_binary_op_with_native(a, b, mode_a, test_native)?;
        }
    }
    Ok(())
}

pub(crate) fn run_binary_random_native_only<const ITERATIONS: usize, const N: usize, T, F>(
    test: impl Fn(UInt<N, T, F>, T) -> Result<(), SynthesisError> + Copy,
) -> Result<(), SynthesisError>
where
    T: PrimUInt,
    F: PrimeField,
{
    let mut rng = ark_std::test_rng();

    for _ in 0..ITERATIONS {
        for mode_a in modes() {
            let a = T::rand(&mut rng);
            let b = T::rand(&mut rng);
            test_binary_op_with_native(a, b, mode_a, test)?;
        }
    }
    Ok(())
}

pub(crate) fn run_binary_exhaustive_native_only<const N: usize, T, F>(
    test: impl Fn(UInt<N, T, F>, T) -> Result<(), SynthesisError> + Copy,
) -> Result<(), SynthesisError>
where
    T: PrimUInt,
    F: PrimeField,
    RangeInclusive<T>: Iterator<Item = T>,
{
    for (mode_a, a) in test_utils::combination(T::min_value()..=T::max_value()) {
        for b in T::min_value()..=T::max_value() {
            test_binary_op_with_native(a, b, mode_a, test)?;
        }
    }
    Ok(())
}

pub(crate) fn run_unary_random<const ITERATIONS: usize, const N: usize, T, F>(
    test: impl Fn(UInt<N, T, F>) -> Result<(), SynthesisError> + Copy,
) -> Result<(), SynthesisError>
where
    T: PrimUInt,
    F: PrimeField,
{
    let mut rng = ark_std::test_rng();

    for _ in 0..ITERATIONS {
        for mode_a in modes() {
            let a = T::rand(&mut rng);
            test_unary_op(a, mode_a, test)?;
        }
    }
    Ok(())
}

pub(crate) fn run_unary_exhaustive<const N: usize, T, F>(
    test: impl Fn(UInt<N, T, F>) -> Result<(), SynthesisError> + Copy,
) -> Result<(), SynthesisError>
where
    T: PrimUInt,
    F: PrimeField,
    RangeInclusive<T>: Iterator<Item = T>,
{
    for (mode, a) in test_utils::combination(T::min_value()..=T::max_value()) {
        test_unary_op(a, mode, test)?;
    }
    Ok(())
}