Skip to main content

fancy_garbling/fancy/
bundle.rs

1use crate::{FancyOutput, HasModulus};
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4use swanky_channel::Channel;
5
6/// A collection of wires, useful for the garbled gadgets defined by `BundleGadgets`.
7#[derive(Clone)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub struct Bundle<W>(Vec<W>);
10
11impl<W: Clone + HasModulus> Bundle<W> {
12    /// Create a new bundle from some wires.
13    pub fn new(ws: Vec<W>) -> Bundle<W> {
14        Bundle(ws)
15    }
16
17    /// Return the moduli of all the wires in the bundle.
18    pub(crate) fn moduli(&self) -> Vec<u16> {
19        self.0.iter().map(HasModulus::modulus).collect()
20    }
21
22    /// Extract the wires from this bundle.
23    pub fn wires(&self) -> &Vec<W> {
24        &self.0
25    }
26
27    /// Get the number of wires in this bundle.
28    pub fn size(&self) -> usize {
29        self.0.len()
30    }
31
32    /// Returns a new bundle only containing wires with matching moduli.
33    pub(crate) fn with_moduli(&self, moduli: &[u16]) -> Bundle<W> {
34        let old_ws = self.wires();
35        let mut new_ws = Vec::with_capacity(moduli.len());
36        for &p in moduli {
37            if let Some(w) = old_ws.iter().find(|&x| x.modulus() == p) {
38                new_ws.push(w.clone());
39            } else {
40                panic!("Bundle::with_moduli: no {} modulus in bundle", p);
41            }
42        }
43        Bundle(new_ws)
44    }
45
46    /// Pad the Bundle with val, n times.
47    pub(crate) fn pad(&mut self, val: &W, n: usize) {
48        for _ in 0..n {
49            self.0.push(val.clone());
50        }
51    }
52
53    /// Insert a wire from the Bundle
54    pub(crate) fn insert(&mut self, wire_index: usize, val: W) {
55        self.0.insert(wire_index, val)
56    }
57
58    /// push a wire onto the Bundle.
59    pub(crate) fn push(&mut self, val: W) {
60        self.0.push(val);
61    }
62
63    /// Pop a wire from the Bundle.
64    pub(crate) fn pop(&mut self) -> Option<W> {
65        self.0.pop()
66    }
67
68    /// Access the underlying iterator
69    pub fn iter(&self) -> std::slice::Iter<'_, W> {
70        self.0.iter()
71    }
72
73    /// Reverse the wires
74    pub(crate) fn reverse(&mut self) {
75        self.0.reverse();
76    }
77}
78
79impl<F: FancyOutput> BundleGadgets for F {}
80
81/// Extension trait for Fancy which provides Bundle constructions which are not
82/// necessarily CRT nor binary-based.
83pub trait BundleGadgets: FancyOutput {
84    /// Output the wires that make up a bundle.
85    fn output_bundle(
86        &mut self,
87        x: &Bundle<Self::Item>,
88        channel: &mut Channel,
89    ) -> swanky_error::Result<Option<Vec<u16>>> {
90        let ws = x.wires();
91        let mut outputs = Vec::with_capacity(ws.len());
92        for w in ws.iter() {
93            outputs.push(self.output(w, channel)?);
94        }
95        Ok(outputs.into_iter().collect())
96    }
97
98    /// Output a slice of bundles.
99    fn output_bundles(
100        &mut self,
101        xs: &[Bundle<Self::Item>],
102        channel: &mut Channel,
103    ) -> swanky_error::Result<Option<Vec<Vec<u16>>>> {
104        let mut zs = Vec::with_capacity(xs.len());
105        for x in xs.iter() {
106            let z = self.output_bundle(x, channel)?;
107            zs.push(z);
108        }
109        Ok(zs.into_iter().collect())
110    }
111}