Skip to main content

fancy_garbling/circuits/binary/
pairwise_and.rs

1use crate::{FancyBinary, circuit::Circuit};
2use core::marker::PhantomData;
3use swanky_channel::Channel;
4use swanky_error::Result;
5
6/// Pairwise AND of two bitvectors.
7#[derive(Default)]
8pub struct PairwiseAnd<'a>(PhantomData<&'a ()>);
9
10impl<'a> PairwiseAnd<'a> {
11    /// Create a new [`PairwiseAnd`] circuit.
12    pub fn new() -> Self {
13        Default::default()
14    }
15}
16
17impl<'a, F: FancyBinary> Circuit<F> for PairwiseAnd<'a>
18where
19    F::Item: 'a,
20{
21    type Input = (&'a Vec<F::Item>, &'a Vec<F::Item>);
22    type Output = Vec<F::Item>;
23
24    fn execute(
25        &self,
26        backend: &mut F,
27        inputs: Self::Input,
28        channel: &mut Channel,
29    ) -> Result<Self::Output> {
30        let (x, y) = inputs;
31        x.iter()
32            .zip(y.iter())
33            .map(|(x, y)| backend.and(x, y, channel))
34            .collect()
35    }
36}
37
38#[cfg(test)]
39pub mod test {
40    use super::PairwiseAnd;
41
42    #[test]
43    fn pairwise_and() {
44        use crate::dummy::{Dummy, DummyVal};
45        use rand::Rng;
46
47        let mut rng = rand::thread_rng();
48        for _ in 0..100 {
49            let n = 1 + (rng.r#gen::<usize>() % 200);
50
51            let x = (0..n)
52                .map(|_| DummyVal::rand_bool(&mut rng))
53                .collect::<Vec<_>>();
54            let y = (0..n)
55                .map(|_| DummyVal::rand_bool(&mut rng))
56                .collect::<Vec<_>>();
57            let expected = x
58                .iter()
59                .zip(y.iter())
60                .map(|(x, y)| DummyVal::new(x.val() & y.val(), 2))
61                .collect::<Vec<_>>();
62            let output = Dummy::eval(&PairwiseAnd::new(), (&x, &y)).unwrap();
63            assert_eq!(output, expected);
64        }
65    }
66}