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}