mpc_engine/
broadcast.rs

1//! This module implements a trusted broadcast relay.
2//!
3//! It must be stressed that this acts as a trusted third party in the protocol
4//! and does not implement secure point-to-point broadcast among the parties.
5
6use std::sync::mpsc::{Receiver, Sender};
7
8use crate::messages::{Message, MessagePayload};
9
10/// A broadcast relay functionality.
11///
12/// Accepts openings to broadcasted committed values and faithfully relays them to all
13/// parties.
14pub struct BroadcastRelay {
15    num_parties: usize,
16    pub(crate) listen: Receiver<Message>,
17    pub(crate) parties: Vec<Sender<Message>>,
18}
19
20impl BroadcastRelay {
21    /// Create a new broadcast relay.
22    pub fn new(listen: Receiver<Message>, parties: Vec<Sender<Message>>) -> Self {
23        Self {
24            num_parties: parties.len(),
25            listen,
26            parties,
27        }
28    }
29
30    /// Continuously await broadcast communication rounds.
31    ///
32    /// A broadcast round starts with all parties sending commitment opening
33    /// information to the broadcast relay. Once openings have been received by
34    /// all parties, the relay starts distributing openings to all parties,
35    /// sending every opening to every party, except the party where the opening
36    /// came from.
37    ///
38    /// If the receiving channel errors this must mean that all parties have
39    /// shut down and dropped their copies of the sender. In this case the
40    /// broadcast relay also shuts down.
41    pub fn run(&self) {
42        loop {
43            let mut openings = Vec::new();
44            for _i in 0..self.num_parties {
45                let opening_msg = self.listen.recv();
46                if let Ok(Message {
47                    from,
48                    to,
49                    payload: MessagePayload::BroadcastOpening(_),
50                }) = opening_msg
51                {
52                    debug_assert_eq!(from, to, "malformed broadcast opening");
53                    openings.push(opening_msg.expect("already confirmed it's ok"))
54                } else {
55                    // One of the parties was dropped, time to shut down.
56                    return;
57                }
58            }
59
60            for opening in openings {
61                for i in 0..self.num_parties {
62                    if i == opening.from {
63                        continue;
64                    }
65
66                    if let MessagePayload::BroadcastOpening(ref inner_opening) = opening.payload {
67                        let franked_opening = Message {
68                            from: opening.from,
69                            to: i,
70                            payload: MessagePayload::BroadcastOpening(inner_opening.clone()),
71                        };
72                        self.parties[i].send(franked_opening).expect(
73                            "all parties should still be online, waiting to receive the opening",
74                        );
75                    }
76                }
77            }
78        }
79    }
80}