aboutsummaryrefslogtreecommitdiffstats
path: root/src/remake/coordinator.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/remake/coordinator.rs')
-rw-r--r--src/remake/coordinator.rs43
1 files changed, 41 insertions, 2 deletions
diff --git a/src/remake/coordinator.rs b/src/remake/coordinator.rs
index 314cd87..0d7a434 100644
--- a/src/remake/coordinator.rs
+++ b/src/remake/coordinator.rs
@@ -138,7 +138,10 @@ async fn step<H: Host>(host: &H, id: &str) -> Result<bool, StoreError> {
decide_abort(
host,
id,
- format!("no majority in the voting period: {tally}"),
+ format!(
+ "no majority in the voting period: {tally}{}",
+ strict_hint(id, &record, &register)
+ ),
)
.await?;
return Ok(true);
@@ -149,12 +152,48 @@ async fn step<H: Host>(host: &H, id: &str) -> Result<bool, StoreError> {
return Ok(true);
}
if tally.out_of_reach() {
- decide_abort(host, id, format!("a majority is out of reach: {tally}")).await?;
+ decide_abort(
+ host,
+ id,
+ format!(
+ "a majority is out of reach: {tally}{}",
+ strict_hint(id, &record, &register)
+ ),
+ )
+ .await?;
return Ok(true);
}
Ok(false)
}
+/// For a strict remake `id` without a majority: who didn't vote, and why they may not
+/// have (`vote::strict_taken`), for its operator to tell from the reason. Nothing for
+/// another kind, or if all voted.
+fn strict_hint(id: &str, record: &Record, register: &records::Register) -> String {
+ if record.proposal.kind != "strict" {
+ return String::new();
+ }
+ let silent: Vec<&str> = record
+ .proposal
+ .electorate
+ .iter()
+ .filter(|member| {
+ register
+ .get(member.as_str())
+ .is_none_or(|votes| !votes.iter().any(|vote| vote.remake == id))
+ })
+ .map(String::as_str)
+ .collect();
+ if silent.is_empty() {
+ return String::new();
+ }
+ format!(
+ "; a strict remake, not voted for by {}: a member votes for one only with its \
+ manifest signed by a key of its --strict-keys (or it was away)",
+ silent.join(", ")
+ )
+}
+
/// Why remake `id` must be aborted whatever its votes, if it must.
fn obstacle(id: &str, record: &Record, all: &[(String, Record)]) -> Option<String> {
if let Some(request) = &record.abort_requested {