fawkes-crypto 4.4.0

zk-SNARK circuit building framework
Documentation
use crate::{
    circuit::{
        cs::{CS, RCS},
        num::CNum,
    },
    core::signal::Signal,
    ff_uint::{Num},
};
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not};

#[derive(Clone, Debug)]
pub struct CBool<C: CS>(CNum<C>);

impl<C: CS> CBool<C> {
    pub fn new_unchecked(n: &CNum<C>) -> Self {
        CBool(n.clone())
    }

    pub fn new(n: &CNum<C>) -> Self {
        n.assert_bit();
        Self::new_unchecked(n)
    }

    pub fn to_num(&self) -> CNum<C> {
        self.0.clone()
    }

    pub fn as_num(&self) -> &CNum<C> {
        &self.0
    }

    pub fn capacity(&self) -> usize {
        0
    }
}

impl<C: CS> Signal<C> for CBool<C> {
    type Value = bool;

    fn as_const(&self) -> Option<Self::Value> {
        self.0.as_const().map(|v| v == Num::ONE)
    }

    fn inputize(&self) {
        self.0.inputize()
    }

    fn get_value(&self) -> Option<Self::Value> {
        self.0.value.map(|v| {
            if v == Num::ZERO {
                false
            } else if v == Num::ONE {
                true
            } else {
                panic!("Wrong boolean value")
            }
        })
    }

    fn from_const(cs: &RCS<C>, value: &Self::Value) -> Self {
        Self::new_unchecked(&CNum::from_const(cs, &(*value).into()))
    }

    fn get_cs(&self) -> &RCS<C> {
        &self.0.cs
    }

    fn alloc(cs: &RCS<C>, value: Option<&Self::Value>) -> Self {
        let value = value.map(|&b| Into::<Num<C::Fr>>::into(b));
        Self::new(&CNum::alloc(cs, value.as_ref()))
    }

    fn assert_const(&self, value: &Self::Value) {
        CS::enforce(
            &self.to_num(),
            &self.derive_const(&Num::ONE),
            &self.derive_const(&(*value).into()),
        )
    }

    fn switch(&self, bit: &CBool<C>, if_else: &Self) -> Self {
        self.to_num()
            .switch(bit, &if_else.to_num())
            .to_bool_unchecked()
    }

    fn assert_eq(&self, other: &Self) {
        self.to_num().assert_eq(&other.to_num())
    }

    fn is_eq(&self, other: &Self) -> CBool<C> {
        let value = self
            .get_value()
            .map(|a| other.get_value().map(|b| a == b))
            .flatten();
        let signal: CBool<C> = self.derive_alloc(value.as_ref());
        CS::enforce(
            &(self.to_num() * Num::from(2) - Num::ONE),
            &(other.to_num() * Num::from(2) - Num::ONE),
            &(signal.to_num() * Num::from(2) - Num::ONE),
        );
        signal
    }
}

impl<C: CS> Not for CBool<C> {
    type Output = Self;

    fn not(self) -> Self::Output {
        (Num::ONE - self.to_num()).to_bool_unchecked()
    }
}

forward_unop_ex!(impl<C: CS> Not for CBool<C>, not);

#[allow(clippy::suspicious_op_assign_impl)]
impl<'l, C: CS> BitAndAssign<&'l CBool<C>> for CBool<C> {
    #[inline]
    fn bitand_assign(&mut self, other: &'l CBool<C>) {
        *self = (self.to_num() * other.to_num()).to_bool_unchecked()
    }
}

impl<'l, C: CS> BitAndAssign<&'l bool> for CBool<C> {
    #[inline]
    fn bitand_assign(&mut self, other: &'l bool) {
        *self &= self.derive_const::<Self>(other)
    }
}

impl<'l, C: CS> BitOrAssign<&'l CBool<C>> for CBool<C> {
    #[inline]
    fn bitor_assign(&mut self, other: &'l CBool<C>) {
        *self = !(!self.clone() & !other)
    }
}

impl<'l, C: CS> BitOrAssign<&'l bool> for CBool<C> {
    #[inline]
    fn bitor_assign(&mut self, other: &'l bool) {
        *self |= self.derive_const::<Self>(other)
    }
}

impl<'l, C: CS> BitXorAssign<&'l CBool<C>> for CBool<C> {
    #[inline]
    fn bitxor_assign(&mut self, other: &'l CBool<C>) {
        *self = !self.is_eq(other)
    }
}

impl<'l, C: CS> BitXorAssign<&'l bool> for CBool<C> {
    #[inline]
    fn bitxor_assign(&mut self, other: &'l bool) {
        *self ^= self.derive_const::<Self>(other)
    }
}

forward_val_assign_ex!(impl<C: CS> BitAndAssign<CBool<C>> for CBool<C>, bitand_assign);
forward_val_assign_ex!(impl<C: CS> BitAndAssign<bool> for CBool<C>, bitand_assign);

forward_val_assign_ex!(impl<C: CS> BitOrAssign<CBool<C>> for CBool<C>, bitor_assign);
forward_val_assign_ex!(impl<C: CS> BitOrAssign<bool> for CBool<C>, bitor_assign);

forward_val_assign_ex!(impl<C: CS> BitXorAssign<CBool<C>> for CBool<C>, bitxor_assign);
forward_val_assign_ex!(impl<C: CS> BitXorAssign<bool> for CBool<C>, bitxor_assign);

impl<'l, C: CS> BitAnd<&'l CBool<C>> for CBool<C> {
    type Output = CBool<C>;

    #[inline]
    fn bitand(mut self, other: &'l CBool<C>) -> Self::Output {
        self &= other;
        self
    }
}

impl<'l, C: CS> BitAnd<&'l bool> for CBool<C> {
    type Output = CBool<C>;

    #[inline]
    fn bitand(mut self, other: &'l bool) -> Self::Output {
        self &= other;
        self
    }
}

forward_all_binop_to_val_ref_commutative_ex!(impl<C: CS> BitAnd for CBool<C>, bitand);
forward_all_binop_to_val_ref_ex!(impl<C: CS> BitAnd<bool> for CBool<C>, bitand -> CBool<C>);
swap_commutative!(impl<C: CS> BitAnd<bool> for CBool<C>, bitand);

impl<'l, C: CS> BitOr<&'l CBool<C>> for CBool<C> {
    type Output = CBool<C>;

    #[inline]
    fn bitor(mut self, other: &'l CBool<C>) -> Self::Output {
        self |= other;
        self
    }
}

impl<'l, C: CS> BitOr<&'l bool> for CBool<C> {
    type Output = CBool<C>;

    #[inline]
    fn bitor(mut self, other: &'l bool) -> Self::Output {
        self |= other;
        self
    }
}

forward_all_binop_to_val_ref_commutative_ex!(impl<C: CS> BitOr for CBool<C>, bitor);
forward_all_binop_to_val_ref_ex!(impl<C: CS> BitOr<bool> for CBool<C>, bitor -> CBool<C>);
swap_commutative!(impl<C: CS> BitOr<bool> for CBool<C>, bitor);

impl<'l, C: CS> BitXor<&'l CBool<C>> for CBool<C> {
    type Output = CBool<C>;

    #[inline]
    fn bitxor(mut self, other: &'l CBool<C>) -> Self::Output {
        self ^= other;
        self
    }
}

impl<'l, C: CS> BitXor<&'l bool> for CBool<C> {
    type Output = CBool<C>;

    #[inline]
    fn bitxor(mut self, other: &'l bool) -> Self::Output {
        self ^= other;
        self
    }
}

forward_all_binop_to_val_ref_commutative_ex!(impl<C: CS> BitXor for CBool<C>, bitxor);
forward_all_binop_to_val_ref_ex!(impl<C: CS> BitXor<bool> for CBool<C>, bitxor -> CBool<C>);
swap_commutative!(impl<C: CS> BitXor<bool> for CBool<C>, bitxor);