mpc_stark/
beaver.rs

1//! Defines the Beaver value generation interface
2//! as well as a dummy beaver interface for testing
3
4use itertools::Itertools;
5
6use crate::algebra::scalar::Scalar;
7
8/// SharedValueSource implements both the functionality for:
9///     1. Single additively shared values [x] where party 1 holds
10///        x_1 and party 2 holds x_2 such that x_1 + x_2 = x
11///     2. Beaver triplets; additively shared values [a], [b], [c] such
12///        that a * b = c
13pub trait SharedValueSource: Send + Sync {
14    /// Fetch the next shared single bit
15    fn next_shared_bit(&mut self) -> Scalar;
16    /// Fetch the next shared batch of bits
17    fn next_shared_bit_batch(&mut self, num_values: usize) -> Vec<Scalar> {
18        (0..num_values)
19            .map(|_| self.next_shared_bit())
20            .collect_vec()
21    }
22    /// Fetch the next shared single value
23    fn next_shared_value(&mut self) -> Scalar;
24    /// Fetch a batch of shared single values
25    fn next_shared_value_batch(&mut self, num_values: usize) -> Vec<Scalar> {
26        (0..num_values)
27            .map(|_| self.next_shared_value())
28            .collect_vec()
29    }
30    /// Fetch the next pair of values that are multiplicative inverses of one another
31    fn next_shared_inverse_pair(&mut self) -> (Scalar, Scalar);
32    /// Fetch the next batch of multiplicative inverse pairs
33    fn next_shared_inverse_pair_batch(&mut self, num_pairs: usize) -> (Vec<Scalar>, Vec<Scalar>) {
34        (0..num_pairs)
35            .map(|_| self.next_shared_inverse_pair())
36            .unzip()
37    }
38    /// Fetch the next beaver triplet
39    fn next_triplet(&mut self) -> (Scalar, Scalar, Scalar);
40    /// Fetch a batch of beaver triplets
41    fn next_triplet_batch(
42        &mut self,
43        num_triplets: usize,
44    ) -> (Vec<Scalar>, Vec<Scalar>, Vec<Scalar>) {
45        let mut a_vals = Vec::with_capacity(num_triplets);
46        let mut b_vals = Vec::with_capacity(num_triplets);
47        let mut c_vals = Vec::with_capacity(num_triplets);
48
49        for _ in 0..num_triplets {
50            let (a, b, c) = self.next_triplet();
51            a_vals.push(a);
52            b_vals.push(b);
53            c_vals.push(c);
54        }
55
56        (a_vals, b_vals, c_vals)
57    }
58}
59/// An implementation of a beaver value source that returns
60/// beaver triples (0, 0, 0) for party 0 and (1, 1, 1) for party 1
61#[cfg(any(feature = "test_helpers", test))]
62#[derive(Clone, Debug, Default)]
63pub struct PartyIDBeaverSource {
64    /// The ID of the local party
65    party_id: u64,
66}
67
68#[cfg(any(feature = "test_helpers", test))]
69impl PartyIDBeaverSource {
70    /// Create a new beaver source given the local party_id
71    pub fn new(party_id: u64) -> Self {
72        Self { party_id }
73    }
74}
75
76/// The PartyIDBeaverSource returns beaver triplets split statically between the
77/// parties. We assume a = 2, b = 3 ==> c = 6. [a] = (1, 1); [b] = (3, 0) [c] = (2, 4)
78#[cfg(any(feature = "test_helpers", test))]
79impl SharedValueSource for PartyIDBeaverSource {
80    fn next_shared_bit(&mut self) -> Scalar {
81        // Simply output partyID, assume partyID \in {0, 1}
82        assert!(self.party_id == 0 || self.party_id == 1);
83        Scalar::from(self.party_id)
84    }
85
86    fn next_triplet(&mut self) -> (Scalar, Scalar, Scalar) {
87        if self.party_id == 0 {
88            (Scalar::from(1u64), Scalar::from(3u64), Scalar::from(2u64))
89        } else {
90            (Scalar::from(1u64), Scalar::from(0u64), Scalar::from(4u64))
91        }
92    }
93
94    fn next_shared_inverse_pair(&mut self) -> (Scalar, Scalar) {
95        (Scalar::from(self.party_id), Scalar::from(self.party_id))
96    }
97
98    fn next_shared_value(&mut self) -> Scalar {
99        Scalar::from(self.party_id)
100    }
101}