Skip to main content

fancy_garbling/circuits/binary/
xor_many.rs

1use crate::{FancyBinary, circuit::Circuit};
2use core::marker::PhantomData;
3use swanky_channel::Channel;
4use swanky_error::Result;
5
6/// Returns the XOR of a vector of items.
7///
8/// # Panics
9/// Panics if no inputs are provided.
10#[derive(Default)]
11pub struct XorMany<'a>(PhantomData<&'a ()>);
12
13impl<'a> XorMany<'a> {
14    /// Create a new [`XorMany`] circuit.
15    pub fn new() -> Self {
16        Default::default()
17    }
18}
19
20impl<'a, F: FancyBinary> Circuit<F> for XorMany<'a>
21where
22    F::Item: 'a,
23{
24    type Input = &'a [F::Item];
25    type Output = F::Item;
26
27    fn execute(
28        &self,
29        backend: &mut F,
30        inputs: Self::Input,
31        _: &mut Channel,
32    ) -> Result<Self::Output> {
33        assert!(!inputs.is_empty(), "`args` cannot be empty");
34        Ok(inputs
35            .iter()
36            .skip(1)
37            .fold(inputs[0].clone(), |acc, x| backend.xor(&acc, x)))
38    }
39}
40
41#[cfg(test)]
42pub mod test {
43    use super::XorMany;
44
45    #[test]
46    fn xor_many() {
47        use crate::dummy::{Dummy, DummyVal};
48        use rand::Rng;
49
50        let mut rng = rand::thread_rng();
51        for _ in 0..16 {
52            let n = 2 + (rng.r#gen::<usize>() % 200);
53            let inputs = (0..n)
54                .map(|_| DummyVal::rand_bool(&mut rng))
55                .collect::<Vec<_>>();
56            let expected = inputs.iter().fold(0, |acc, &x| x.val() ^ acc);
57            let circuit = XorMany::new();
58            let output = Dummy::eval(&circuit, inputs.as_slice()).unwrap();
59            assert_eq!(output.val(), expected);
60        }
61    }
62}