extern crate alloc;
use alloc::vec::Vec;
use crate::metis::{Dotted, Rhapsody};
use super::wire::round_trip_rhapsody;
use super::{Fleet, REPLICAS};
pub(super) fn assert_convergence(fleet: &mut Fleet) {
let states: Vec<Dotted<Rhapsody>> = fleet.live.iter().map(|r| r.state().clone()).collect();
for i in 0..REPLICAS {
for j in 0..REPLICAS {
if i != j {
let pairwise = states[i].merge(&states[j]);
let order = pairwise.store().order();
let _ = fleet.ledger.observe(&order);
}
}
}
let mut states = states;
for _ in 0..REPLICAS {
for i in 0..REPLICAS {
for j in 0..REPLICAS {
if i != j {
states[i] = states[i].merge(&states[j]);
let order = states[i].store().order();
let _ = fleet.ledger.observe(&order);
}
}
}
}
let forward = states
.iter()
.fold(Dotted::<Rhapsody>::new(), |acc, s| acc.merge(s));
let backward = states
.iter()
.rev()
.fold(Dotted::<Rhapsody>::new(), |acc, s| acc.merge(s));
assert_eq!(forward, backward, "the fold must not depend on order");
let target = forward.store().order();
for state in &states {
assert_eq!(
state.store().order(),
target,
"every converged replica reads the one order",
);
}
round_trip_rhapsody(forward.store());
let _ = fleet.ledger.observe(&target);
if let Err(contradiction) = fleet.ledger.verdict() {
panic!(
"the run's observed orders admit no single total order \
(the strong list specification's order clause): {contradiction:?}",
);
}
}