Skip to main content

fancy_garbling/
fancy.rs

1//! Traits for representing specific kinds of garbled circuit computations.
2//!
3//! The core trait of this module is [`Fancy`], which represents the basic set
4//! of operations possible by a garbled circuit. There are also extension
5//! traits, in particular [`FancyBinary`] and [`FancyArithmetic`] that further
6//! extend the core [`Fancy`] trait to provide binary and arithmetic operations,
7//! respectively.
8
9use swanky_channel::Channel;
10use swanky_error::Result;
11
12mod binary;
13mod bundle;
14mod crt;
15pub use binary::{BinaryBundle, BinaryGadgets};
16pub use bundle::Bundle;
17pub use crt::{CrtBundle, CrtGadgets};
18
19/// An object that has a modulus.
20pub trait HasModulus {
21    /// The modulus of the wire.
22    fn modulus(&self) -> u16;
23}
24
25/// The `Fancy` trait is the core trait for writing circuits.
26///
27/// The trait contains an associated type, [`Fancy::Item`], which defines the
28/// underlying wire representation, alongside a [`Fancy::constant`] method for
29/// creating constant (public) wires.
30///
31/// This trait can be further extended to support binary, arithmetic, and/or
32/// projections by using the [`FancyBinary`], [`FancyArithmetic`], or
33/// [`FancyProj`] extension traits, respectively. The [`FancyEncode`] trait
34/// allows for encoding values into wires, and the [`FancyOutput`] trait allows
35/// for converting wires into their underlying plaintext representation.
36pub trait Fancy {
37    /// The underlying wire representation of this [`Fancy`] object.
38    type Item: Clone + core::fmt::Debug + HasModulus;
39
40    /// Encode a constant `x` with modulus `q`.
41    fn constant(&mut self, x: u16, q: u16, channel: &mut Channel) -> Result<Self::Item>;
42}
43
44/// Extension trait for [`Fancy`] that provides encoding and receiving operations.
45pub trait FancyEncode: Fancy {
46    /// Encode many wires for known values.
47    fn encode_many(
48        &mut self,
49        values: &[u16],
50        moduli: &[u16],
51        channel: &mut Channel,
52    ) -> Result<Vec<Self::Item>>;
53
54    /// Receive many wires for unknown values.
55    fn receive_many(&mut self, moduli: &[u16], channel: &mut Channel) -> Result<Vec<Self::Item>>;
56
57    /// Encode a wire for a known value.
58    fn encode(&mut self, value: u16, modulus: u16, channel: &mut Channel) -> Result<Self::Item> {
59        let xs = self.encode_many(&[value], &[modulus], channel)?;
60        Ok(xs[0].clone())
61    }
62
63    /// Receive a wire for an unknown value.
64    fn receive(&mut self, modulus: u16, channel: &mut Channel) -> Result<Self::Item> {
65        let xs = self.receive_many(&[modulus], channel)?;
66        Ok(xs[0].clone())
67    }
68}
69
70/// Extension trait for [`Fancy`] that provides output operations.
71pub trait FancyOutput: Fancy {
72    /// Output the value associated with wire `x`.
73    ///
74    /// Some [`Fancy`] implementers don't actually *return* output, but they
75    /// need to be involved in the process, so they can return `None`.
76    fn output(&mut self, x: &Self::Item, channel: &mut Channel) -> Result<Option<u16>>;
77
78    /// Output the values associated with a slice of wires.
79    ///
80    /// Some [`Fancy`] implementers don't actually *return* output, but they
81    /// need to be involved in the process, so they can return `None`.
82    fn outputs(&mut self, xs: &[Self::Item], channel: &mut Channel) -> Result<Option<Vec<u16>>> {
83        let mut zs = Vec::with_capacity(xs.len());
84        for x in xs.iter() {
85            zs.push(self.output(x, channel)?);
86        }
87        Ok(zs.into_iter().collect())
88    }
89}
90
91/// Extension trait for [`Fancy`] that provides binary operations.
92pub trait FancyBinary: Fancy {
93    /// Binary XOR.
94    fn xor(&mut self, x: &Self::Item, y: &Self::Item) -> Self::Item;
95
96    /// Binary AND.
97    fn and(&mut self, x: &Self::Item, y: &Self::Item, channel: &mut Channel) -> Result<Self::Item>;
98
99    /// Binary negation.
100    fn negate(&mut self, x: &Self::Item) -> Self::Item;
101
102    /// Binary OR.
103    fn or(&mut self, x: &Self::Item, y: &Self::Item, channel: &mut Channel) -> Result<Self::Item> {
104        let notx = self.negate(x);
105        let noty = self.negate(y);
106        let z = self.and(&notx, &noty, channel)?;
107        Ok(self.negate(&z))
108    }
109}
110
111/// Extension trait for [`Fancy`] that provides arithmetic operations.
112pub trait FancyArithmetic: Fancy {
113    /// Add `x` and `y`.
114    ///
115    /// # Panics
116    /// This panics if `x` and `y` do not have equal moduli.
117    fn add(&mut self, x: &Self::Item, y: &Self::Item) -> Self::Item;
118
119    /// Subtract `x` and `y`.
120    ///
121    /// # Panics
122    /// This panics if `x` and `y` do not have equal moduli.
123    fn sub(&mut self, x: &Self::Item, y: &Self::Item) -> Self::Item;
124
125    /// Multiply `x` with the constant `c`.
126    fn cmul(&mut self, x: &Self::Item, c: u16) -> Self::Item;
127
128    /// Multiply `x` and `y`.
129    fn mul(&mut self, x: &Self::Item, y: &Self::Item, channel: &mut Channel) -> Result<Self::Item>;
130}
131
132/// Extension trait for [`Fancy`] that provides a projection gate, alongside
133/// methods that utilize projection gates.
134///
135/// # Security Warning
136/// In its current form, using projection gates in arithmetic garbling is
137/// **insecure**.
138pub trait FancyProj: Fancy {
139    /// Project `x` according to the truth table `tt`. Resulting wire has
140    /// modulus `q`.
141    ///
142    /// Optional `tt` is useful for hiding the gate from the evaluator.
143    ///
144    /// # Panics
145    /// This may panic in certain implementations if `tt` is `None` when it
146    /// should be `Some`. In addition, it may panic if `tt` is improperly
147    /// formed: either the length of `tt` is smaller than `x`s modulus, or the
148    /// values in `tt` are larger than `q`.
149    fn proj(
150        &mut self,
151        x: &Self::Item,
152        q: u16,
153        tt: Option<Vec<u16>>,
154        channel: &mut Channel,
155    ) -> Result<Self::Item>;
156}
157
158macro_rules! check_binary {
159    ($x:ident) => {
160        assert_eq!($x.modulus(), 2);
161    };
162}
163
164pub(crate) use check_binary;