Skip to main content

primitives/correlated_randomness/dabits/
sharing.rs

1use itertools::izip;
2use num_traits::identities::{One, Zero};
3
4use crate::{
5    algebra::field::{binary::Gf2_128, Bit, FieldExtension, SubfieldElement},
6    correlated_randomness::dabits::{DaBit, DaBits, OpenDaBit, OpenDaBits},
7    errors::PrimitiveError,
8    sharing::{Reconstructible, VerifiableWith},
9    types::{HeapArray, PeerIndex, Positive},
10};
11// ---------------
12// |   Opening   |
13// ---------------
14
15impl<F: FieldExtension> Reconstructible for DaBit<F> {
16    type Value = (Bit, SubfieldElement<F>);
17    type Opening = OpenDaBit<F>;
18
19    /// Open the daBit towards another peer.
20    fn open_to(&self, peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
21        let opened_bit = self.bit.open_to(peer_index)?;
22
23        Ok(OpenDaBit {
24            opened_bit,
25            opened_field: self.field.open_to(peer_index)?,
26        })
27    }
28
29    /// Open the daBit towards all other peers.
30    fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
31        (0..self.field.get_macs().len())
32            .map(|peer_index| self.open_to(peer_index).expect("Opening should not fail"))
33    }
34
35    /// Reconstruct a secret from openings coming from all other parties.
36    fn reconstruct(&self, openings: Vec<Self::Opening>) -> Result<Self::Value, PrimitiveError> {
37        let (bit_openings, field_openings): (Vec<_>, Vec<_>) = openings
38            .iter()
39            .map(|dabit_opening| (dabit_opening.bit(), dabit_opening.field()))
40            .unzip();
41
42        if field_openings.len() != self.field.get_macs().len() {
43            return Err(PrimitiveError::InvalidSize(
44                self.field.get_macs().len(),
45                field_openings.len(),
46            ));
47        }
48
49        let field = self.field.reconstruct(field_openings)?;
50        let bit = self.bit.reconstruct(bit_openings)?;
51
52        Ok((bit, field))
53    }
54}
55
56impl<F: FieldExtension> VerifiableWith for DaBit<F> {
57    type VerificationData = ();
58
59    /// Verify openings from all peers.
60    fn verify_with(&self, openings: Vec<Self::Opening>, _data: ()) -> Result<(), PrimitiveError> {
61        let (bit, field) = self.reconstruct(openings)?;
62
63        // Check that the bit has the same value as the field element
64        if field == SubfieldElement::<F>::one() {
65            if bit != SubfieldElement::<Gf2_128>::one() {
66                return Err(PrimitiveError::WrongCorrelation(
67                    "daBit bit does not match the field element.".to_string(),
68                ));
69            }
70        } else if field == SubfieldElement::<F>::zero() {
71            if bit != SubfieldElement::<Gf2_128>::zero() {
72                return Err(PrimitiveError::WrongCorrelation(
73                    "daBit bit does not match the field element.".to_string(),
74                ));
75            }
76        } else {
77            return Err(PrimitiveError::WrongCorrelation(
78                "daBit field element is not 0 or 1.".to_string(),
79            ));
80        }
81        Ok(())
82    }
83}
84
85impl<F: FieldExtension, N: Positive> Reconstructible for DaBits<F, N> {
86    type Opening = OpenDaBits<F, N>;
87    type Value = HeapArray<(Bit, SubfieldElement<F>), N>;
88
89    /// Open the share towards another peer.
90    fn open_to(&self, peer_index: PeerIndex) -> Result<Self::Opening, PrimitiveError> {
91        Ok(OpenDaBits {
92            opened_bits: self.bits.open_to(peer_index)?,
93            opened_field_shares: self.field_shares.open_to(peer_index)?,
94        })
95    }
96
97    /// Open the share towards all other peers. Returns an iterator with either one opening for
98    /// each peer or a single opening for all peers.
99    fn open_to_all_others(&self) -> impl ExactSizeIterator<Item = Self::Opening> {
100        izip!(
101            self.bits.open_to_all_others(),
102            self.field_shares.open_to_all_others()
103        )
104        .map(|(opened_bits, opened_field_shares)| OpenDaBits {
105            opened_bits,
106            opened_field_shares,
107        })
108    }
109
110    /// Reconstruct a secret from openings coming from all other parties.
111    fn reconstruct(&self, openings: Vec<Self::Opening>) -> Result<Self::Value, PrimitiveError> {
112        let (bit_openings, field_openings): (Vec<_>, Vec<_>) = openings
113            .into_iter()
114            .map(|dabit_opening| (dabit_opening.opened_bits, dabit_opening.opened_field_shares))
115            .unzip();
116        let bits = self.bits.reconstruct(bit_openings)?;
117        let field_shares = self.field_shares.reconstruct(field_openings)?;
118
119        Ok(HeapArray::from_iter(izip!(
120            bits.into_iter(),
121            field_shares.into_iter()
122        )))
123    }
124}
125
126impl<F: FieldExtension, N: Positive> VerifiableWith for DaBits<F, N> {
127    type VerificationData = ();
128
129    /// Verify openings from all peers.
130    fn verify_with(&self, openings: Vec<Self::Opening>, _data: ()) -> Result<(), PrimitiveError> {
131        let openings = self.reconstruct(openings)?;
132
133        for (bit, field) in openings {
134            // Check that the bit has the same value as the field element
135            if field == SubfieldElement::<F>::one() {
136                if bit != SubfieldElement::<Gf2_128>::one() {
137                    return Err(PrimitiveError::WrongCorrelation(
138                        "daBit bit does not match the field element.".to_string(),
139                    ));
140                }
141            } else if field == SubfieldElement::<F>::zero() {
142                if bit != SubfieldElement::<Gf2_128>::zero() {
143                    return Err(PrimitiveError::WrongCorrelation(
144                        "daBit bit does not match the field element.".to_string(),
145                    ));
146                }
147            } else {
148                return Err(PrimitiveError::WrongCorrelation(
149                    "daBit field element is not 0 or 1.".to_string(),
150                ));
151            }
152        }
153
154        Ok(())
155    }
156}