Add root timeout handling (#153)

* Add handling of root timeout

* Use StandardQc instead of Qc for high_qc

Since high_qc is guaranteed to be a standard qc, let's just use
StandardQc as a type in all messages that use it.
This commit is contained in:
Giacomo Pasini 2023-05-22 15:23:30 +02:00 committed by GitHub
parent bc453b686f
commit 6c64720e39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 8 deletions

View File

@ -79,7 +79,7 @@ impl<O: Overlay> Carnot<O> {
if timeout_qc.view < new_state.current_view {
return new_state;
}
new_state.update_high_qc(timeout_qc.high_qc.clone());
new_state.update_high_qc(Qc::Standard(timeout_qc.high_qc.clone()));
new_state.update_timeout_qc(timeout_qc.clone());
new_state.current_view = timeout_qc.view + 1;
@ -167,9 +167,9 @@ impl<O: Overlay> Carnot<O> {
.iter()
.map(|nv| &nv.high_qc)
.chain(std::iter::once(&timeout_qc.high_qc))
.max_by_key(|qc| qc.view())
.max_by_key(|qc| qc.view)
.unwrap();
new_state.update_high_qc(high_qc.clone());
new_state.update_high_qc(Qc::Standard(high_qc.clone()));
let new_view_msg = NewView {
view: new_view,
@ -209,7 +209,7 @@ impl<O: Overlay> Carnot<O> {
{
let timeout_msg = Timeout {
view: new_state.current_view,
high_qc: Qc::Standard(new_state.local_high_qc.clone()),
high_qc: new_state.local_high_qc.clone(),
sender: new_state.id,
timeout_qc: new_state.last_view_timeout_qc.clone(),
};

View File

@ -39,7 +39,7 @@ pub struct Vote {
pub struct Timeout {
pub view: View,
pub sender: NodeId,
pub high_qc: Qc,
pub high_qc: StandardQc,
pub timeout_qc: Option<TimeoutQc>,
}
@ -51,14 +51,14 @@ pub struct NewView {
pub view: View,
pub sender: NodeId,
pub timeout_qc: TimeoutQc,
pub high_qc: Qc,
pub high_qc: StandardQc,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TimeoutQc {
pub view: View,
pub high_qc: Qc,
pub high_qc: StandardQc,
pub sender: NodeId,
}

View File

@ -338,7 +338,23 @@ where
}
Event::RootTimeout { timeouts } => {
tracing::debug!("root timeout {:?}", timeouts);
// timeout detected
// TODO: filter timeouts upon reception
assert!(timeouts.iter().all(|t| t.view == carnot.current_view()));
let high_qc = timeouts
.iter()
.map(|t| &t.high_qc)
.chain(std::iter::once(&carnot.high_qc()))
.max_by_key(|qc| qc.view)
.expect("empty root committee")
.clone();
if carnot.is_member_of_root_committee() {
let timeout_qc = TimeoutQc {
view: carnot.current_view(),
high_qc,
sender: carnot.id(),
};
output = Some(Output::BroadcastTimeoutQc { timeout_qc });
}
}
Event::ProposeBlock { qc } => {
tracing::debug!("proposing block");