Skip to main content

fedimint_hbbft/
sync_key_gen.rs

1//! A _synchronous_ algorithm for dealerless distributed key generation.
2//!
3//! This protocol is meant to run in a _completely synchronous_ setting where each node handles all
4//! messages in the same order. It can e.g. exchange messages as transactions on top of
5//! `HoneyBadger`, or it can run "on-chain", i.e. committing its messages to a blockchain.
6//!
7//! Its messages are encrypted where necessary, so they can be publicly broadcast.
8//!
9//! When the protocol completes, every node receives a secret key share suitable for threshold
10//! signatures and encryption. The secret master key is not known by anyone. The protocol succeeds
11//! if up to _t_ nodes are faulty, where _t_ is the `threshold` parameter. The number of nodes must
12//! be at least _2 t + 1_.
13//!
14//! ## Usage
15//!
16//! Before beginning the threshold key generation process, each validator needs to generate a
17//! regular (non-threshold) key pair and multicast its public key. `SyncKeyGen::new` returns the
18//! instance itself and a `Part` message, containing a contribution to the new threshold keys.
19//! It needs to be sent to all nodes. `SyncKeyGen::handle_part` in turn produces an `Ack`
20//! message, which is also multicast.
21//!
22//! All nodes must handle the exact same set of `Part` and `Ack` messages. In this sense the
23//! algorithm is synchronous: If Alice's `Ack` was handled by Bob but not by Carol, Bob and
24//! Carol could receive different public key sets, and secret key shares that don't match. One way
25//! to ensure this is to commit the messages to a public ledger before handling them, e.g. by
26//! feeding them to a preexisting instance of Honey Badger. The messages will then appear in the
27//! same order for everyone.
28//!
29//! To complete the process, call `SyncKeyGen::generate`. It produces your secret key share and the
30//! public key set.
31//!
32//! While not asynchronous, the algorithm is fault tolerant: It is not necessary to handle a
33//! `Part` and all `Ack` messages from every validator. A `Part` is _complete_ if it
34//! received at least _2 t + 1_ valid `Ack`s. Only complete `Part`s are used for key
35//! generation in the end, and as long as at least one complete `Part` is from a correct node,
36//! the new key set is secure. You can use `SyncKeyGen::is_ready` to check whether at least
37//! _t + 1_ `Part`s are complete. So all nodes can call `generate` as soon as `is_ready` returns
38//! `true`.
39//!
40//! Alternatively, you can use any stronger criterion, too, as long as all validators call
41//! `generate` at the same point, i.e. after handling the same set of messages.
42//! `SyncKeyGen::count_complete` returns the number of complete `Part` messages. And
43//! `SyncKeyGen::is_node_ready` can be used to check whether a particluar node's `Part` is
44//! complete.
45//!
46//! The `Part` and `Ack` messages alone contain all the information needed for anyone to compute
47//! the public key set, and for anyone owning one of the participating secret keys to compute
48//! their own secret key share. In particular:
49//! * Observer nodes can also use `SyncKeyGen`. For observers, no `Part` and `Ack`
50//! messages will be created and they do not need to send anything. On completion, they will only
51//! receive the public key set, but no secret key share.
52//! * If a participant crashed and lost its `SyncKeyGen` instance, but still has its original
53//! key pair, and if the key generation messages were committed to some public ledger, it can
54//! create a new `SyncKeyGen`, handle all the messages in order, and compute its secret key share.
55//!
56//! ## Example
57//!
58//! ```
59//! use std::collections::BTreeMap;
60//! use std::sync::Arc;
61//!
62//! use threshold_crypto::{SecretKey, SignatureShare};
63//! use hbbft::sync_key_gen::{to_pub_keys, AckOutcome, PartOutcome, PubKeyMap, SyncKeyGen};
64//!
65//! // Use the OS random number generator for any randomness:
66//! let mut rng = rand::rngs::OsRng;
67//!
68//! // Two out of four shares will suffice to sign or encrypt something.
69//! let (threshold, node_num) = (1, 4);
70//!
71//! // Generate individual key pairs for encryption. These are not suitable for threshold schemes.
72//! let sec_keys: Vec<SecretKey> = (0..node_num).map(|_| rand::random()).collect();
73//! let pub_keys = to_pub_keys(sec_keys.iter().enumerate());
74//!
75//! // Create the `SyncKeyGen` instances. The constructor also outputs the part that needs to
76//! // be sent to all other participants, so we save the parts together with their sender ID.
77//! let mut nodes = BTreeMap::new();
78//! let mut parts = Vec::new();
79//! for (id, sk) in sec_keys.into_iter().enumerate() {
80//!     let (sync_key_gen, opt_part) = SyncKeyGen::new(
81//!         id,
82//!         sk,
83//!         pub_keys.clone(),
84//!         threshold,
85//!         &mut rng,
86//!     ).unwrap_or_else(|_| panic!("Failed to create `SyncKeyGen` instance for node #{}", id));
87//!     nodes.insert(id, sync_key_gen);
88//!     parts.push((id, opt_part.unwrap())); // Would be `None` for observer nodes.
89//! }
90//!
91//! // All nodes now handle the parts and send the resulting `Ack` messages.
92//! let mut acks = Vec::new();
93//! for (sender_id, part) in parts {
94//!     for (&id, node) in &mut nodes {
95//!         match node
96//!             .handle_part(&sender_id, part.clone(), &mut rng)
97//!             .expect("Failed to handle Part")
98//!         {
99//!             PartOutcome::Valid(Some(ack)) => acks.push((id, ack)),
100//!             PartOutcome::Invalid(fault) => panic!("Invalid Part: {:?}", fault),
101//!             PartOutcome::Valid(None) => {
102//!                 panic!("We are not an observer, so we should send Ack.")
103//!             }
104//!         }
105//!     }
106//! }
107//!
108//! // Finally, we handle all the `Ack`s.
109//! for (sender_id, ack) in acks {
110//!     for node in nodes.values_mut() {
111//!         match node.handle_ack(&sender_id, ack.clone()).expect("Failed to handle Ack") {
112//!             AckOutcome::Valid => (),
113//!             AckOutcome::Invalid(fault) => panic!("Invalid Ack: {:?}", fault),
114//!         }
115//!     }
116//! }
117//!
118//! // We have all the information and can generate the key sets.
119//! // Generate the public key set; which is identical for all nodes.
120//! let pub_key_set = nodes[&0].generate().expect("Failed to create `PublicKeySet` from node #0").0;
121//! let mut secret_key_shares = BTreeMap::new();
122//! for (&id, node) in &mut nodes {
123//!     assert!(node.is_ready());
124//!     let (pks, opt_sks) = node.generate().unwrap_or_else(|_|
125//!         panic!("Failed to create `PublicKeySet` and `SecretKeyShare` for node #{}", id)
126//!     );
127//!     assert_eq!(pks, pub_key_set); // All nodes now know the public keys and public key shares.
128//!     let sks = opt_sks.expect("Not an observer node: We receive a secret key share.");
129//!     secret_key_shares.insert(id, sks);
130//! }
131//!
132//! // Two out of four nodes can now sign a message. Each share can be verified individually.
133//! let msg = "Nodes 0 and 1 does not agree with this.";
134//! let mut sig_shares: BTreeMap<usize, SignatureShare> = BTreeMap::new();
135//! for (&id, sks) in &secret_key_shares {
136//!     if id != 0 && id != 1 {
137//!         let sig_share = sks.sign(msg);
138//!         let pks = pub_key_set.public_key_share(id);
139//!         assert!(pks.verify(&sig_share, msg));
140//!         sig_shares.insert(id, sig_share);
141//!     }
142//! }
143//!
144//! // Two signatures are over the threshold. They are enough to produce a signature that matches
145//! // the public master key.
146//! let sig = pub_key_set
147//!     .combine_signatures(&sig_shares)
148//!     .expect("The shares can be combined.");
149//! assert!(pub_key_set.public_key().verify(&sig, msg));
150//! ```
151//!
152//! ## How it works
153//!
154//! The algorithm is based on ideas from
155//! [Distributed Key Generation in the Wild](https://eprint.iacr.org/2012/377.pdf) and
156//! [A robust threshold elliptic curve digital signature providing a new verifiable secret sharing scheme](https://www.researchgate.net/profile/Ihab_Ali/publication/4205262_A_robust_threshold_elliptic_curve_digital_signature_providing_a_new_verifiable_secret_sharing_scheme/links/02e7e538f15726323a000000/A-robust-threshold-elliptic-curve-digital-signature-providing-a-new-verifiable-secret-sharing-scheme.pdf?origin=publication_detail).
157//!
158//! In a trusted dealer scenario, the following steps occur:
159//!
160//! 1. Dealer generates a `BivarPoly` of degree _t_ and publishes the `BivarCommitment` which is
161//!    used to publicly verify the polynomial's values.
162//! 2. Dealer sends _row_ _m > 0_ to node number _m_.
163//! 3. Node _m_, in turn, sends _value_ number _s_ to node number _s_.
164//! 4. This process continues until _2 t + 1_ nodes confirm they have received a valid row. If
165//!    there are at most _t_ faulty nodes, we know that at least _t + 1_ correct nodes sent on an
166//!    entry of every other node's column to that node.
167//! 5. This means every node can reconstruct its column, and the value at _0_ of its column.
168//! 6. These values all lie on a univariate polynomial of degree _t_ and can be used as secret keys.
169//!
170//! In our _dealerless_ environment, at least _t + 1_ nodes each generate a polynomial using the
171//! method above. The sum of the secret keys we received from each node is then used as our secret
172//! key. No single node knows the secret master key.
173
174use std::borrow::Borrow;
175use std::collections::{BTreeMap, BTreeSet};
176use std::fmt::{self, Debug, Formatter};
177use std::string::ToString;
178use std::sync::Arc;
179
180use bincode;
181use rand::{self, Rng};
182use serde::{Deserialize, Serialize};
183use thiserror::Error;
184
185use crate::crypto::{
186    self,
187    error::Error as CryptoError,
188    poly::{BivarCommitment, BivarPoly, Poly},
189    serde_impl::FieldWrap,
190    G1Affine, PublicKeySet, Scalar, SecretKeyShare,
191};
192use crate::NodeIdT;
193use std::ops::AddAssign;
194use std::ops::Mul;
195
196/// A cryptographic key that allows decrypting messages that were encrypted to the key's owner.
197pub trait SecretKey {
198    /// The decryption error type.
199    type Error: ToString;
200
201    /// Decrypts a ciphertext.
202    fn decrypt(&self, ct: &[u8]) -> Result<Vec<u8>, Self::Error>;
203}
204
205/// A cryptographic public key that allows encrypting messages to the key's owner.
206pub trait PublicKey {
207    /// The encryption error type.
208    type Error: ToString;
209    /// The corresponding secret key type. The secret key is known only to the key's owner.
210    type SecretKey: SecretKey;
211
212    /// Encrypts a message to this key's owner and returns the ciphertext.
213    fn encrypt<M: AsRef<[u8]>, R: Rng>(&self, msg: M, rng: &mut R) -> Result<Vec<u8>, Self::Error>;
214}
215
216impl SecretKey for crypto::SecretKey {
217    type Error = bincode::Error;
218
219    fn decrypt(&self, ct: &[u8]) -> Result<Vec<u8>, bincode::Error> {
220        self.decrypt(&bincode::deserialize(ct)?)
221            .ok_or_else(|| bincode::ErrorKind::Custom("Invalid ciphertext.".to_string()).into())
222    }
223}
224
225impl PublicKey for crypto::PublicKey {
226    type Error = bincode::Error;
227    type SecretKey = crypto::SecretKey;
228
229    fn encrypt<M: AsRef<[u8]>, R: Rng>(
230        &self,
231        msg: M,
232        rng: &mut R,
233    ) -> Result<Vec<u8>, bincode::Error> {
234        bincode::serialize(&self.encrypt_with_rng(rng, msg))
235    }
236}
237
238/// A map assigning to each node ID a public key, wrapped in an `Arc`.
239pub type PubKeyMap<N, PK = crypto::PublicKey> = Arc<BTreeMap<N, PK>>;
240
241/// Returns a `PubKeyMap` corresponding to the given secret keys.
242///
243/// This is mostly useful for setting up test networks.
244pub fn to_pub_keys<'a, I, B, N: NodeIdT + 'a>(sec_keys: I) -> PubKeyMap<N>
245where
246    B: Borrow<N>,
247    I: IntoIterator<Item = (B, &'a crypto::SecretKey)>,
248{
249    let to_pub = |(id, sk): I::Item| (id.borrow().clone(), sk.public_key());
250    Arc::new(sec_keys.into_iter().map(to_pub).collect())
251}
252
253/// A local error while handling an `Ack` or `Part` message, that was not caused by that message
254/// being invalid.
255#[derive(Clone, Eq, PartialEq, Debug, Error)]
256pub enum Error {
257    /// Error creating `SyncKeyGen`.
258    #[error("Error creating SyncKeyGen: {0}")]
259    Creation(CryptoError),
260    /// Error generating keys.
261    #[error("Error generating keys: {0}")]
262    Generation(CryptoError),
263    /// Unknown sender.
264    #[error("Unknown sender")]
265    UnknownSender,
266    /// Failed to serialize message.
267    #[error("Serialization error: {0}")]
268    Serialize(String),
269    /// Failed to encrypt message parts for a peer.
270    #[error("Encryption error: {0}")]
271    Encrypt(String),
272}
273
274impl From<bincode::Error> for Error {
275    fn from(err: bincode::Error) -> Error {
276        Error::Serialize(format!("{:?}", err))
277    }
278}
279
280impl Error {
281    fn encrypt<E: ToString>(err: E) -> Error {
282        Error::Encrypt(err.to_string())
283    }
284}
285
286/// A submission by a validator for the key generation. It must to be sent to all participating
287/// nodes and handled by all of them, including the one that produced it.
288///
289/// The message contains a commitment to a bivariate polynomial, and for each node, an encrypted
290/// row of values. If this message receives enough `Ack`s, it will be used as summand to produce
291/// the the key set in the end.
292#[derive(Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
293pub struct Part(BivarCommitment, Vec<Vec<u8>>);
294
295impl Debug for Part {
296    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
297        f.debug_tuple("Part")
298            .field(&format!("<degree {}>", self.0.degree()))
299            .field(&format!("<{} rows>", self.1.len()))
300            .finish()
301    }
302}
303
304/// A confirmation that we have received and verified a validator's part. It must be sent to
305/// all participating nodes and handled by all of them, including ourselves.
306///
307/// The message is only produced after we verified our row against the commitment in the `Part`.
308/// For each node, it contains one encrypted value of that row.
309#[derive(Deserialize, Serialize, Clone, Hash, Eq, PartialEq)]
310pub struct Ack(u64, Vec<Vec<u8>>);
311
312impl Debug for Ack {
313    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
314        f.debug_tuple("Ack")
315            .field(&self.0)
316            .field(&format!("<{} values>", self.1.len()))
317            .finish()
318    }
319}
320
321/// The information needed to track a single proposer's secret sharing process.
322#[derive(Debug, PartialEq, Eq)]
323struct ProposalState {
324    /// The proposer's commitment.
325    commit: BivarCommitment,
326    /// The verified values we received from `Ack` messages.
327    values: BTreeMap<u64, Scalar>,
328    /// The nodes which have acked this part, valid or not.
329    acks: BTreeSet<u64>,
330}
331
332impl ProposalState {
333    /// Creates a new part state with a commitment.
334    fn new(commit: BivarCommitment) -> ProposalState {
335        ProposalState {
336            commit,
337            values: BTreeMap::new(),
338            acks: BTreeSet::new(),
339        }
340    }
341
342    /// Returns `true` if at least `2 * threshold + 1` nodes have acked.
343    fn is_complete(&self, threshold: usize) -> bool {
344        self.acks.len() > 2 * threshold
345    }
346}
347
348/// The outcome of handling and verifying a `Part` message.
349pub enum PartOutcome {
350    /// The message was valid: the part of it that was encrypted to us matched the public
351    /// commitment, so we can multicast an `Ack` message for it. If we are an observer or we have
352    /// already handled the same `Part` before, this contains `None` instead.
353    Valid(Option<Ack>),
354    /// The message was invalid: We now know that the proposer is faulty, and dont' send an `Ack`.
355    Invalid(PartFault),
356}
357
358/// The outcome of handling and verifying an `Ack` message.
359pub enum AckOutcome {
360    /// The message was valid.
361    Valid,
362    /// The message was invalid: The sender is faulty.
363    Invalid(AckFault),
364}
365
366/// A synchronous algorithm for dealerless distributed key generation.
367///
368/// It requires that all nodes handle all messages in the exact same order.
369#[derive(Debug)]
370pub struct SyncKeyGen<N, PK: PublicKey = crypto::PublicKey> {
371    /// Our node ID.
372    our_id: N,
373    /// Our node index.
374    our_idx: Option<u64>,
375    /// Our secret key.
376    sec_key: PK::SecretKey,
377    /// The public keys of all nodes, by node ID.
378    pub_keys: PubKeyMap<N, PK>,
379    /// Proposed bivariate polynomials.
380    parts: BTreeMap<u64, ProposalState>,
381    /// The degree of the generated polynomial.
382    threshold: usize,
383}
384
385impl<N: NodeIdT, PK: PublicKey> SyncKeyGen<N, PK> {
386    /// Creates a new `SyncKeyGen` instance, together with the `Part` message that should be
387    /// multicast to all nodes.
388    ///
389    /// If we are not a validator but only an observer, no `Part` message is produced and no
390    /// messages need to be sent.
391    pub fn new<R: rand::Rng>(
392        our_id: N,
393        sec_key: PK::SecretKey,
394        pub_keys: PubKeyMap<N, PK>,
395        threshold: usize,
396        rng: &mut R,
397    ) -> Result<(Self, Option<Part>), Error> {
398        let our_idx = pub_keys
399            .keys()
400            .position(|id| *id == our_id)
401            .map(|idx| idx as u64);
402        let key_gen = SyncKeyGen {
403            our_id,
404            our_idx,
405            sec_key,
406            pub_keys,
407            parts: BTreeMap::new(),
408            threshold,
409        };
410        if our_idx.is_none() {
411            return Ok((key_gen, None)); // No part: we are an observer.
412        }
413
414        let our_part = BivarPoly::random(threshold, rng);
415        let commit = our_part.commitment();
416        let encrypt = |(i, pk): (usize, &PK)| {
417            let row = bincode::serialize(&our_part.row(i + 1))?;
418            pk.encrypt(&row, rng).map_err(Error::encrypt)
419        };
420        let rows = key_gen
421            .pub_keys
422            .values()
423            .enumerate()
424            .map(encrypt)
425            .collect::<Result<Vec<Vec<u8>>, Error>>()?;
426        Ok((key_gen, Some(Part(commit, rows))))
427    }
428
429    /// Returns the id of this node.
430    pub fn our_id(&self) -> &N {
431        &self.our_id
432    }
433
434    /// Returns the map of participating nodes and their public keys.
435    pub fn public_keys(&self) -> &PubKeyMap<N, PK> {
436        &self.pub_keys
437    }
438
439    /// Handles a `Part` message. If it is valid, returns an `Ack` message to be broadcast.
440    ///
441    /// If we are only an observer, `None` is returned instead and no messages need to be sent.
442    ///
443    /// All participating nodes must handle the exact same sequence of messages.
444    /// Note that `handle_part` also needs to explicitly be called with this instance's own `Part`.
445    pub fn handle_part<R: rand::Rng>(
446        &mut self,
447        sender_id: &N,
448        part: Part,
449        rng: &mut R,
450    ) -> Result<PartOutcome, Error> {
451        let sender_idx = self.node_index(sender_id).ok_or(Error::UnknownSender)?;
452        let row = match self.handle_part_or_fault(sender_idx, part) {
453            Ok(Some(row)) => row,
454            Ok(None) => return Ok(PartOutcome::Valid(None)),
455            Err(fault) => return Ok(PartOutcome::Invalid(fault)),
456        };
457        // The row is valid. Encrypt one value for each node and broadcast an `Ack`.
458        let mut values = Vec::new();
459        for (idx, pk) in self.pub_keys.values().enumerate() {
460            let val = row.evaluate(idx + 1);
461            let ser_val = bincode::serialize(&FieldWrap(val))?;
462            values.push(pk.encrypt(ser_val, rng).map_err(Error::encrypt)?);
463        }
464        Ok(PartOutcome::Valid(Some(Ack(sender_idx, values))))
465    }
466
467    /// Handles an `Ack` message.
468    ///
469    /// All participating nodes must handle the exact same sequence of messages.
470    /// Note that `handle_ack` also needs to explicitly be called with this instance's own `Ack`s.
471    pub fn handle_ack(&mut self, sender_id: &N, ack: Ack) -> Result<AckOutcome, Error> {
472        let sender_idx = self.node_index(sender_id).ok_or(Error::UnknownSender)?;
473        Ok(match self.handle_ack_or_fault(sender_idx, ack) {
474            Ok(()) => AckOutcome::Valid,
475            Err(fault) => AckOutcome::Invalid(fault),
476        })
477    }
478
479    /// Returns the index of the node, or `None` if it is unknown.
480    fn node_index(&self, node_id: &N) -> Option<u64> {
481        self.pub_keys
482            .keys()
483            .position(|id| id == node_id)
484            .map(|idx| idx as u64)
485    }
486
487    /// Returns the number of complete parts. If this is at least `threshold + 1`, the keys can
488    /// be generated, but it is possible to wait for more to increase security.
489    pub fn count_complete(&self) -> usize {
490        self.parts
491            .values()
492            .filter(|part| part.is_complete(self.threshold))
493            .count()
494    }
495
496    /// Returns `true` if the part of the given node is complete.
497    pub fn is_node_ready(&self, proposer_id: &N) -> bool {
498        self.node_index(proposer_id)
499            .and_then(|proposer_idx| self.parts.get(&proposer_idx))
500            .map_or(false, |part| part.is_complete(self.threshold))
501    }
502
503    /// Returns `true` if enough parts are complete to safely generate the new key.
504    pub fn is_ready(&self) -> bool {
505        self.count_complete() > self.threshold
506    }
507
508    /// Returns the new secret key share and the public key set.
509    ///
510    /// These are only secure if `is_ready` returned `true`. Otherwise it is not guaranteed that
511    /// none of the nodes knows the secret master key.
512    ///
513    /// If we are only an observer node, no secret key share is returned.
514    ///
515    /// All participating nodes must have handled the exact same sequence of `Part` and `Ack`
516    /// messages before calling this method. Otherwise their key shares will not match.
517    pub fn generate(&self) -> Result<(PublicKeySet, Option<SecretKeyShare>), Error> {
518        let mut pk_commit = Poly::zero().commitment();
519        let mut opt_sk_val = self.our_idx.map(|_| Scalar::zero());
520        let is_complete = |part: &&ProposalState| part.is_complete(self.threshold);
521        for part in self.parts.values().filter(is_complete) {
522            pk_commit += part.commit.row(0);
523            if let Some(sk_val) = opt_sk_val.as_mut() {
524                let row = Poly::interpolate(part.values.iter().take(self.threshold + 1));
525                sk_val.add_assign(&row.evaluate(0));
526            }
527        }
528        let opt_sk = if let Some(mut fr) = opt_sk_val {
529            let sk = SecretKeyShare::from_mut(&mut fr);
530            Some(sk)
531        } else {
532            None
533        };
534        Ok((pk_commit.into(), opt_sk))
535    }
536
537    /// Returns the number of nodes participating in the key generation.
538    pub fn num_nodes(&self) -> usize {
539        self.pub_keys.len()
540    }
541
542    /// Handles a `Part` message, or returns a `PartFault` if it is invalid.
543    fn handle_part_or_fault(
544        &mut self,
545        sender_idx: u64,
546        Part(commit, rows): Part,
547    ) -> Result<Option<Poly>, PartFault> {
548        if rows.len() != self.pub_keys.len() {
549            return Err(PartFault::RowCount);
550        }
551        if let Some(state) = self.parts.get(&sender_idx) {
552            if state.commit != commit {
553                return Err(PartFault::MultipleParts);
554            }
555            return Ok(None); // We already handled this `Part` before.
556        }
557        // Retrieve our own row's commitment, and store the full commitment.
558        let opt_idx_commit_row = self.our_idx.map(|idx| (idx, commit.row(idx + 1)));
559        self.parts.insert(sender_idx, ProposalState::new(commit));
560        let (our_idx, commit_row) = match opt_idx_commit_row {
561            Some((idx, row)) => (idx, row),
562            None => return Ok(None), // We are only an observer. Nothing to send or decrypt.
563        };
564        // We are a validator: Decrypt and deserialize our row and compare it to the commitment.
565        let ser_row = self
566            .sec_key
567            .decrypt(&rows[our_idx as usize])
568            .map_err(|_| PartFault::DecryptRow)?;
569        let row: Poly = bincode::deserialize(&ser_row).map_err(|_| PartFault::DeserializeRow)?;
570        if row.commitment() != commit_row {
571            return Err(PartFault::RowCommitment);
572        }
573        Ok(Some(row))
574    }
575
576    /// Handles an `Ack` message, or returns an `AckFault` if it is invalid.
577    fn handle_ack_or_fault(
578        &mut self,
579        sender_idx: u64,
580        Ack(proposer_idx, values): Ack,
581    ) -> Result<(), AckFault> {
582        if values.len() != self.pub_keys.len() {
583            return Err(AckFault::ValueCount);
584        }
585        let part = self
586            .parts
587            .get_mut(&proposer_idx)
588            .ok_or(AckFault::MissingPart)?;
589        if !part.acks.insert(sender_idx) {
590            return Ok(()); // We already handled this `Ack` before.
591        }
592        let our_idx = match self.our_idx {
593            Some(our_idx) => our_idx,
594            None => return Ok(()), // We are only an observer. Nothing to decrypt for us.
595        };
596        // We are a validator: Decrypt and deserialize our value and compare it to the commitment.
597        let ser_val = self
598            .sec_key
599            .decrypt(&values[our_idx as usize])
600            .map_err(|_| AckFault::DecryptValue)?;
601        let val = bincode::deserialize::<FieldWrap<Scalar>>(&ser_val)
602            .map_err(|_| AckFault::DeserializeValue)?
603            .into_inner();
604        if part.commit.evaluate(our_idx + 1, sender_idx + 1) != G1Affine::generator().mul(val) {
605            return Err(AckFault::ValueCommitment);
606        }
607        part.values.insert(sender_idx + 1, val);
608        Ok(())
609    }
610}
611
612/// An error in an `Ack` message sent by a faulty node.
613#[derive(Clone, Copy, Eq, PartialEq, Debug, Error)]
614pub enum AckFault {
615    /// The number of values differs from the number of nodes.
616    #[error("The number of values differs from the number of nodes")]
617    ValueCount,
618    /// No corresponding Part received.
619    #[error("No corresponding Part received")]
620    MissingPart,
621    /// Value decryption failed.
622    #[error("Value decryption failed")]
623    DecryptValue,
624    /// Value deserialization failed.
625    #[error("Value deserialization failed")]
626    DeserializeValue,
627    /// Value doesn't match the commitment.
628    #[error("Value doesn't match the commitment")]
629    ValueCommitment,
630}
631
632/// An error in a `Part` message sent by a faulty node.
633#[derive(Clone, Copy, Eq, PartialEq, Debug, Error)]
634pub enum PartFault {
635    /// The number of rows differs from the number of nodes.
636    #[error("The number of rows differs from the number of nodes")]
637    RowCount,
638    /// Received multiple different Part messages from the same sender.
639    #[error("Received multiple different Part messages from the same sender")]
640    MultipleParts,
641    /// Could not decrypt our row in the Part message.
642    #[error("Could not decrypt our row in the Part message")]
643    DecryptRow,
644    /// Could not deserialize our row in the Part message.
645    #[error("Could not deserialize our row in the Part message")]
646    DeserializeRow,
647    /// Row does not match the commitment.
648    #[error("Row does not match the commitment")]
649    RowCommitment,
650}