Skip to content

Commit af6c76e

Browse files
committed
Temporary
1 parent 246dae7 commit af6c76e

File tree

5 files changed

+101
-107
lines changed

5 files changed

+101
-107
lines changed

examples/src/simple.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ impl<Id: PartyId> Round<Id> for Round1<Id> {
200200
}
201201

202202
fn communication_info(&self) -> CommunicationInfo<Id> {
203-
CommunicationInfo::regular(&self.context.other_ids)
203+
CommunicationInfo::all_to_all(&self.context.other_ids)
204204
}
205205

206206
fn make_normal_broadcast(

manul/src/protocol.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ pub use errors::{
2626
};
2727
pub use message::{DirectMessage, EchoBroadcast, NormalBroadcast, ProtocolMessage, ProtocolMessagePart};
2828
pub use round::{
29-
Artifact, CommunicationInfo, EchoRoundParticipation, EntryPoint, FinalizeOutcome, IdSet, NoProtocolErrors, PartyId,
30-
Payload, Protocol, ProtocolError, RequiredMessageParts, RequiredMessages, Round,
29+
Artifact, CommunicationInfo, EntryPoint, FinalizeOutcome, IdSet, NoProtocolErrors,
30+
PartyId, Payload, Protocol, ProtocolError, RequiredMessageParts, RequiredMessages, Round, RoundCommunicationInfo,
3131
};
3232
pub use round_id::{RoundId, TransitionInfo};
3333

manul/src/protocol/round.rs

+47-35
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,41 @@ impl<Id: Ord> IdSet<Id> {
5757
}
5858
}
5959

60-
/// Describes what other parties this rounds sends messages to, and what other parties it expects messages from.
60+
/// Encapsulates the communication info for the main round and the possible echo round.
6161
#[derive(Debug, Clone)]
6262
pub struct CommunicationInfo<Id> {
63+
/// Communication info for the main part of the round (that is, not considering the echo round).
64+
pub main_round: RoundCommunicationInfo<Id>,
65+
66+
/// The specific way the node participates in the echo round following this round.
67+
///
68+
/// If `None`, and there is an echo round, will be set to `main_round`.
69+
pub echo_round: Option<RoundCommunicationInfo<Id>>,
70+
71+
/// The parties whose echoed messages this node expects to receive in the echo round (if any).
72+
///
73+
/// If `None`, and there is an echo round, will be set to `echo_round.expecting_messages_from`.
74+
pub expected_echos: Option<IdSet<Id>>,
75+
}
76+
77+
impl<Id: PartyId> CommunicationInfo<Id> {
78+
/// A regular round that sends messages to all `other_parties`, and expects messages back from them.
79+
pub fn all_to_all(id_set: &IdSet<Id>) -> Self {
80+
Self {
81+
main_round: RoundCommunicationInfo::all_to_all(id_set),
82+
echo_round: None,
83+
expected_echos: None,
84+
}
85+
}
86+
87+
pub fn set_to_set(senders: &IdSet<Id>, receivers: &IdSet<Id>, my_id: &Id) -> Self {
88+
todo!()
89+
}
90+
}
91+
92+
/// Describes what other parties this rounds sends messages to, and what other parties it expects messages from.
93+
#[derive(Debug, Clone)]
94+
pub struct RoundCommunicationInfo<Id> {
6395
/// The destinations of the messages to be sent out by this round.
6496
///
6597
/// The way it is interpreted by the execution layer is
@@ -69,27 +101,26 @@ pub struct CommunicationInfo<Id> {
69101
/// for each element of the returned set.
70102
pub message_destinations: BTreeSet<Id>,
71103

72-
/// Returns the set of node IDs from which this round expects messages.
104+
/// The set of node IDs from which this round expects messages.
73105
///
74-
/// The execution layer will not call [`finalize`](`Round::finalize`) until all these nodes have responded
75-
/// (and the corresponding [`receive_message`](`Round::receive_message`) finished successfully).
106+
/// The execution layer will not call [`finalize`](`Round::finalize`) until enough nodes to constitute the quorum
107+
/// have responded (and the corresponding [`receive_message`](`Round::receive_message`) finished successfully).
76108
pub expecting_messages_from: IdSet<Id>,
77-
78-
/// Returns the specific way the node participates in the echo round following this round.
79-
///
80-
/// Returns [`EchoRoundParticipation::Default`] by default; this works fine when every node
81-
/// sends messages to every other one, or do not send or receive any echo broadcasts.
82-
/// Otherwise, review the options in [`EchoRoundParticipation`] and pick the appropriate one.
83-
pub echo_round_participation: EchoRoundParticipation<Id>,
84109
}
85110

86-
impl<Id: PartyId> CommunicationInfo<Id> {
111+
impl<Id: PartyId> RoundCommunicationInfo<Id> {
87112
/// A regular round that sends messages to all `other_parties`, and expects messages back from them.
88-
pub fn regular(other_parties: &BTreeSet<Id>) -> Self {
113+
pub fn all_to_all(id_set: &IdSet<Id>) -> Self {
114+
Self {
115+
message_destinations: id_set.all().clone(),
116+
expecting_messages_from: id_set.clone(),
117+
}
118+
}
119+
120+
pub fn none() -> Self {
89121
Self {
90-
message_destinations: other_parties.clone(),
91-
expecting_messages_from: IdSet::new_non_threshold(other_parties.clone()),
92-
echo_round_participation: EchoRoundParticipation::Default,
122+
message_destinations: BTreeSet::new(),
123+
expecting_messages_from: IdSet::empty(),
93124
}
94125
}
95126
}
@@ -376,25 +407,6 @@ pub trait PartyId: 'static + Debug + Clone + Ord + Send + Sync + Serialize + for
376407

377408
impl<T> PartyId for T where T: 'static + Debug + Clone + Ord + Send + Sync + Serialize + for<'de> Deserialize<'de> {}
378409

379-
/// The specific way the node participates in the echo round (if any).
380-
#[derive(Debug, Clone)]
381-
pub enum EchoRoundParticipation<Id> {
382-
/// The default behavior: sends broadcasts and receives echoed messages, or does neither.
383-
///
384-
/// That is, this node will be a part of the echo round if [`Round::make_echo_broadcast`] generates a message.
385-
Default,
386-
387-
/// This node sends broadcasts that will be echoed, but does not receive any.
388-
Send,
389-
390-
/// This node receives broadcasts that it needs to echo, but does not send any itself.
391-
Receive {
392-
/// The other participants of the echo round
393-
/// (that is, the nodes to which echoed messages will be sent).
394-
echo_targets: BTreeSet<Id>,
395-
},
396-
}
397-
398410
mod sealed {
399411
/// A dyn safe trait to get the type's ID.
400412
pub trait DynTypeId: 'static {

manul/src/session/echo.rs

+25-22
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ use tracing::debug;
1313

1414
use super::{
1515
message::{MessageVerificationError, SignedMessageHash, SignedMessagePart},
16-
session::{EchoRoundInfo, SessionParameters},
16+
session::{SessionParameters},
1717
LocalError,
1818
};
1919
use crate::{
20-
protocol::{
21-
Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast, EchoRoundParticipation,
20+
protocol::{RoundCommunicationInfo, IdSet,
21+
Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast,
2222
FinalizeOutcome, MessageValidationError, NormalBroadcast, Payload, Protocol, ProtocolMessage,
2323
ProtocolMessagePart, ReceiveError, Round, TransitionInfo,
2424
},
@@ -75,8 +75,9 @@ pub(crate) struct EchoRoundMessage<SP: SessionParameters> {
7575
pub struct EchoRound<P: Protocol<SP::Verifier>, SP: SessionParameters> {
7676
verifier: SP::Verifier,
7777
echo_broadcasts: BTreeMap<SP::Verifier, SignedMessagePart<EchoBroadcast>>,
78-
echo_round_info: EchoRoundInfo<SP::Verifier>,
7978
communication_info: CommunicationInfo<SP::Verifier>,
79+
expected_echos: IdSet<SP::Verifier>,
80+
banned_ids: BTreeSet<SP::Verifier>,
8081
main_round: BoxedRound<SP::Verifier, P>,
8182
payloads: BTreeMap<SP::Verifier, Payload>,
8283
artifacts: BTreeMap<SP::Verifier, Artifact>,
@@ -90,24 +91,25 @@ where
9091
pub fn new(
9192
verifier: SP::Verifier,
9293
echo_broadcasts: BTreeMap<SP::Verifier, SignedMessagePart<EchoBroadcast>>,
93-
echo_round_info: EchoRoundInfo<SP::Verifier>,
94+
communication_info: RoundCommunicationInfo<SP::Verifier>,
95+
expected_echos: IdSet<SP::Verifier>,
96+
banned_ids: BTreeSet<SP::Verifier>,
9497
main_round: BoxedRound<SP::Verifier, P>,
9598
payloads: BTreeMap<SP::Verifier, Payload>,
9699
artifacts: BTreeMap<SP::Verifier, Artifact>,
97100
) -> Self {
98-
debug!("{:?}: initialized echo round with {:?}", verifier, echo_round_info);
99-
101+
debug!("{:?}: initialized echo round with {:?} {:?}", verifier, communication_info, expected_echos);
100102
let communication_info = CommunicationInfo {
101-
message_destinations: echo_round_info.message_destinations.clone(),
102-
expecting_messages_from: echo_round_info.expecting_messages_from.clone(),
103-
echo_round_participation: EchoRoundParticipation::Default,
103+
main_round: communication_info,
104+
echo_round: None,
105+
expected_echos: None,
104106
};
105-
106107
Self {
107108
verifier,
108109
echo_broadcasts,
109-
echo_round_info,
110110
communication_info,
111+
expected_echos,
112+
banned_ids,
111113
main_round,
112114
payloads,
113115
artifacts,
@@ -197,23 +199,16 @@ where
197199
let message = message.normal_broadcast.deserialize::<EchoRoundMessage<SP>>(format)?;
198200

199201
// Check that the received message contains entries from `expected_echos`.
200-
// It is an unprovable fault.
202+
// Since we cannot guarantee the communication info for the echo round is in the associated data,
203+
// we cannot construct an evidence for this fault.
201204

202-
let mut expected_keys = self.echo_round_info.expected_echos.clone();
205+
let mut expected_keys = self.expected_echos.all().clone();
203206

204207
// We don't expect the node to send its echo the second time.
205208
expected_keys.remove(from);
206209

207210
let message_keys = message.message_hashes.keys().cloned().collect::<BTreeSet<_>>();
208211

209-
let missing_keys = expected_keys.difference(&message_keys).collect::<Vec<_>>();
210-
if !missing_keys.is_empty() {
211-
return Err(ReceiveError::unprovable(format!(
212-
"Missing echoed messages from: {:?}",
213-
missing_keys
214-
)));
215-
}
216-
217212
let extra_keys = message_keys.difference(&expected_keys).collect::<Vec<_>>();
218213
if !extra_keys.is_empty() {
219214
return Err(ReceiveError::unprovable(format!(
@@ -222,6 +217,14 @@ where
222217
)));
223218
}
224219

220+
// Check that the echos we received, minus the banned IDs, constitute a quorum.
221+
// This is also unprovable since the information about the IDs we banned is not available to third parties.
222+
223+
let expected_keys = message_keys.difference(&self.banned_ids).cloned().collect::<BTreeSet<_>>();
224+
if !self.expected_echos.is_quorum(&expected_keys) {
225+
return Err(ReceiveError::unprovable("Not enough echos to constitute a quorum"));
226+
}
227+
225228
// Check that every entry is equal to what we received previously (in the main round).
226229
// If there's a difference, it's a provable fault,
227230
// since we have both messages signed by `from`.

manul/src/session/session.rs

+26-47
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ use super::{
2323
LocalError, RemoteError,
2424
};
2525
use crate::protocol::{
26-
Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast, EchoRoundParticipation,
26+
Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast,
2727
EntryPoint, FinalizeOutcome, IdSet, NormalBroadcast, PartyId, Payload, Protocol, ProtocolMessage,
28-
ProtocolMessagePart, ReceiveError, ReceiveErrorType, RoundId, TransitionInfo,
28+
ProtocolMessagePart, ReceiveError, ReceiveErrorType, RoundCommunicationInfo, RoundId, TransitionInfo,
2929
};
3030

3131
/// A set of types needed to execute a session.
@@ -97,13 +97,6 @@ impl AsRef<[u8]> for SessionId {
9797
}
9898
}
9999

100-
#[derive(Debug)]
101-
pub(crate) struct EchoRoundInfo<Verifier> {
102-
pub(crate) message_destinations: BTreeSet<Verifier>,
103-
pub(crate) expecting_messages_from: IdSet<Verifier>,
104-
pub(crate) expected_echos: BTreeSet<Verifier>,
105-
}
106-
107100
/// An object encapsulating the currently active round, transport protocol,
108101
/// and the database of messages and errors from the previous rounds.
109102
#[derive(Debug)]
@@ -114,8 +107,9 @@ pub struct Session<P: Protocol<SP::Verifier>, SP: SessionParameters> {
114107
format: BoxedFormat,
115108
round: BoxedRound<SP::Verifier, P>,
116109
message_destinations: BTreeSet<SP::Verifier>,
117-
communication_info: CommunicationInfo<SP::Verifier>,
118-
echo_round_info: Option<EchoRoundInfo<SP::Verifier>>,
110+
main_round_cinfo: RoundCommunicationInfo<SP::Verifier>,
111+
echo_round_cinfo: RoundCommunicationInfo<SP::Verifier>,
112+
expected_echos: IdSet<SP::Verifier>,
119113
echo_broadcast: SignedMessagePart<EchoBroadcast>,
120114
normal_broadcast: SignedMessagePart<NormalBroadcast>,
121115
transition_info: TransitionInfo,
@@ -174,41 +168,21 @@ where
174168
let normal = round.as_ref().make_normal_broadcast(rng, &format)?;
175169
let normal_broadcast = SignedMessagePart::new::<SP>(rng, &signer, &session_id, &transition_info.id(), normal)?;
176170

177-
let communication_info = round.as_ref().communication_info();
178-
let message_destinations = communication_info
171+
let CommunicationInfo {
172+
main_round: main_round_cinfo,
173+
echo_round: echo_round_cinfo,
174+
expected_echos,
175+
} = round.as_ref().communication_info();
176+
177+
let echo_round_cinfo = echo_round_cinfo.unwrap_or(main_round_cinfo.clone());
178+
let expected_echos = expected_echos.unwrap_or(echo_round_cinfo.expecting_messages_from.clone());
179+
180+
let message_destinations = main_round_cinfo
179181
.message_destinations
180182
.difference(&transcript.banned_ids())
181183
.cloned()
182184
.collect::<BTreeSet<_>>();
183185

184-
let round_sends_echo_broadcast = !echo_broadcast.payload().is_none();
185-
let echo_round_info = match &communication_info.echo_round_participation {
186-
EchoRoundParticipation::Default => {
187-
if round_sends_echo_broadcast {
188-
// Add our own echo message to the expected list because we expect it to be sent back from other nodes.
189-
let mut expected_echos = communication_info.expecting_messages_from.all().clone();
190-
expected_echos.insert(verifier.clone());
191-
Some(EchoRoundInfo {
192-
message_destinations: communication_info.message_destinations.clone(),
193-
// TODO: this is not correct in general
194-
expecting_messages_from: IdSet::new_non_threshold(
195-
communication_info.message_destinations.clone(),
196-
),
197-
expected_echos,
198-
})
199-
} else {
200-
None
201-
}
202-
}
203-
EchoRoundParticipation::Send => None,
204-
EchoRoundParticipation::Receive { echo_targets } => Some(EchoRoundInfo {
205-
message_destinations: echo_targets.clone(),
206-
// TODO: this is not correct in general
207-
expecting_messages_from: IdSet::new_non_threshold(echo_targets.clone()),
208-
expected_echos: communication_info.expecting_messages_from.all().clone(),
209-
}),
210-
};
211-
212186
Ok(Self {
213187
session_id,
214188
signer,
@@ -219,8 +193,9 @@ where
219193
normal_broadcast,
220194
transition_info,
221195
message_destinations,
222-
communication_info,
223-
echo_round_info,
196+
main_round_cinfo,
197+
echo_round_cinfo,
198+
expected_echos,
224199
transcript,
225200
})
226201
}
@@ -343,7 +318,7 @@ where
343318

344319
let acceptable_round_ids = self
345320
.transition_info
346-
.simultaneous_rounds(self.echo_round_info.is_some())?;
321+
.simultaneous_rounds(self.echo_round_cinfo.is_some())?;
347322

348323
let message_for = if message_round_id == self.round_id() {
349324
if accum.message_is_being_processed(from) {
@@ -431,7 +406,7 @@ where
431406
/// Makes an accumulator for a new round.
432407
pub fn make_accumulator(&self) -> RoundAccumulator<P, SP> {
433408
RoundAccumulator::new(
434-
&self.communication_info.expecting_messages_from,
409+
&self.main_round_cinfo.expecting_messages_from,
435410
self.transcript.banned_ids(),
436411
)
437412
}
@@ -484,6 +459,8 @@ where
484459
let verifier = self.verifier().clone();
485460
let round_id = self.round_id();
486461

462+
let echo_round = !self.echo_broadcast.payload().is_none();
463+
487464
let transcript = self.transcript.update(
488465
&round_id,
489466
(verifier.clone(), self.echo_broadcast),
@@ -495,11 +472,13 @@ where
495472
accum.still_have_not_sent_messages,
496473
)?;
497474

498-
if let Some(echo_round_info) = self.echo_round_info {
475+
if echo_round {
499476
let round = BoxedRound::new_dynamic(EchoRound::<P, SP>::new(
500477
verifier,
501478
transcript.echo_broadcasts(&round_id)?,
502-
echo_round_info,
479+
self.echo_round_cinfo,
480+
self.expected_echos,
481+
transcript.banned_ids().clone(),
503482
self.round,
504483
accum.payloads,
505484
accum.artifacts,

0 commit comments

Comments
 (0)