diff --git a/crates/sui-core/src/authority_active.rs b/crates/sui-core/src/authority_active.rs
index 3b75774c0eb45..b788db8e2dfc0 100644
--- a/crates/sui-core/src/authority_active.rs
+++ b/crates/sui-core/src/authority_active.rs
@@ -38,7 +38,7 @@ use sui_types::{
};
use tokio::sync::Mutex;
use tokio::task::JoinHandle;
-use tracing::info;
+use tracing::{debug, info};
use crate::{
authority::AuthorityState,
@@ -67,6 +67,7 @@ const DELAY_FOR_1_RETRY_MS: u64 = 2_000;
const EXPONENTIAL_DELAY_BASIS: u64 = 2;
pub const MAX_RETRY_DELAY_MS: u64 = 30_000;
+#[derive(Debug)]
pub struct AuthorityHealth {
// Records the number of retries
pub retries: u32,
@@ -175,6 +176,19 @@ impl ActiveAuthority {
/// even if we have a few connections.
pub async fn minimum_wait_for_majority_honest_available(&self) -> Instant {
let lock = self.health.lock().await;
+
+ let health_overview: Vec<_> = lock
+ .iter()
+ .map(|(name, h)| {
+ (
+ *name,
+ h.retries,
+ h.no_contact_before - tokio::time::Instant::now(),
+ )
+ })
+ .collect();
+ debug!(health_overview = ?health_overview, "Current validator health metrics");
+
let (_, instant) = self.net.load().committee.robust_value(
lock.iter().map(|(name, h)| (*name, h.no_contact_before)),
// At least one honest node is at or above it.
diff --git a/crates/sui-core/src/authority_aggregator.rs b/crates/sui-core/src/authority_aggregator.rs
index a47c979410e33..9dbe01d681593 100644
--- a/crates/sui-core/src/authority_aggregator.rs
+++ b/crates/sui-core/src/authority_aggregator.rs
@@ -20,7 +20,7 @@ use sui_types::{
CheckpointContents, CheckpointRequest, CheckpointResponse,
},
};
-use tracing::{debug, info, instrument, trace, Instrument};
+use tracing::{debug, error, info, instrument, trace, Instrument};
use prometheus::{
register_histogram_with_registry, register_int_counter_with_registry, Histogram, IntCounter,
@@ -1606,7 +1606,12 @@ where
if effects.effects.is_object_mutated_here(obj_ref) {
is_ok = true;
} else {
- // TODO: Report a byzantine fault here
+ // TODO: Throw a byzantine fault here
+ error!(
+ ?object_id,
+ ?tx_digest,
+ "get_object_info_execute. Byzantine failure!"
+ );
continue;
}
}
diff --git a/crates/sui-types/src/committee.rs b/crates/sui-types/src/committee.rs
index ce1d629a9d880..fb991ded04666 100644
--- a/crates/sui-types/src/committee.rs
+++ b/crates/sui-types/src/committee.rs
@@ -231,7 +231,7 @@ impl Committee {
let mut total = 0;
for (v, s, a) in items {
total += s;
- if threshold < total {
+ if threshold <= total {
return (a, v);
}
}
@@ -323,4 +323,34 @@ mod test {
let res = committee.shuffle_by_stake(None, Some(&BTreeSet::new()));
assert_eq!(0, res.len());
}
+
+ #[test]
+ fn test_robust_value() {
+ let (_, sec1): (_, AuthorityKeyPair) = get_key_pair();
+ let (_, sec2): (_, AuthorityKeyPair) = get_key_pair();
+ let (_, sec3): (_, AuthorityKeyPair) = get_key_pair();
+ let (_, sec4): (_, AuthorityKeyPair) = get_key_pair();
+ let a1: AuthorityName = sec1.public().into();
+ let a2: AuthorityName = sec2.public().into();
+ let a3: AuthorityName = sec3.public().into();
+ let a4: AuthorityName = sec4.public().into();
+
+ let mut authorities = BTreeMap::new();
+ authorities.insert(a1, 1);
+ authorities.insert(a2, 1);
+ authorities.insert(a3, 1);
+ authorities.insert(a4, 1);
+ let committee = Committee::new(0, authorities).unwrap();
+ let items = vec![(a1, 666), (a2, 1), (a3, 2), (a4, 0)];
+ assert_eq!(
+ committee.robust_value(items.into_iter(), committee.quorum_threshold()),
+ (a3, 2)
+ );
+
+ let items = vec![(a1, "a"), (a2, "b"), (a3, "c"), (a4, "d")];
+ assert_eq!(
+ committee.robust_value(items.into_iter(), committee.quorum_threshold()),
+ (a3, "c")
+ );
+ }
}