mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 13:21:10 +00:00
Provisioner should ignore unconfirmed disputes (#6294)
* Fix typos * Filter unconfirmed disputes in provisioner - random_selection * Rework dispute coordinator to return `DisputeStatus` with `ActiveDisputes` message. * Rework the random_selection implementation of `select_disptues` in `provisioner` to return only confirmed disputes. * Filter unconfirmed disputes in provisioner - prioritized_selection * Add test for unconfirmed disputes handling * Fix `dispute-distribution` tests
This commit is contained in:
committed by
GitHub
parent
40221806d4
commit
a0f4287dd9
@@ -139,6 +139,13 @@ where
|
||||
onchain.len(),
|
||||
);
|
||||
|
||||
// Filter out unconfirmed disputes. However if the dispute is already onchain - don't skip it.
|
||||
// In this case we'd better push as much fresh votes as possible to bring it to conclusion faster.
|
||||
let recent_disputes = recent_disputes
|
||||
.into_iter()
|
||||
.filter(|d| d.2.is_confirmed_concluded() || onchain.contains_key(&(d.0, d.1)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let partitioned = partition_recent_disputes(recent_disputes, &onchain);
|
||||
metrics.on_partition_recent_disputes(&partitioned);
|
||||
|
||||
|
||||
@@ -426,7 +426,7 @@ impl TestDisputes {
|
||||
pub fn add_unconfirmed_disputes_concluded_onchain(
|
||||
&mut self,
|
||||
dispute_count: usize,
|
||||
) -> (u32, usize) {
|
||||
) -> (SessionIndex, usize) {
|
||||
let local_votes_count = self.validators_count * 90 / 100;
|
||||
let onchain_votes_count = self.validators_count * 80 / 100;
|
||||
let session_idx = 0;
|
||||
@@ -444,7 +444,7 @@ impl TestDisputes {
|
||||
pub fn add_unconfirmed_disputes_unconcluded_onchain(
|
||||
&mut self,
|
||||
dispute_count: usize,
|
||||
) -> (u32, usize) {
|
||||
) -> (SessionIndex, usize) {
|
||||
let local_votes_count = self.validators_count * 90 / 100;
|
||||
let onchain_votes_count = self.validators_count * 40 / 100;
|
||||
let session_idx = 1;
|
||||
@@ -459,22 +459,25 @@ impl TestDisputes {
|
||||
(session_idx, (local_votes_count - onchain_votes_count) * dispute_count)
|
||||
}
|
||||
|
||||
pub fn add_unconfirmed_disputes_unknown_onchain(
|
||||
pub fn add_confirmed_disputes_unknown_onchain(
|
||||
&mut self,
|
||||
dispute_count: usize,
|
||||
) -> (u32, usize) {
|
||||
) -> (SessionIndex, usize) {
|
||||
let local_votes_count = self.validators_count * 90 / 100;
|
||||
let session_idx = 2;
|
||||
let lf = leaf();
|
||||
let dummy_receipt = test_helpers::dummy_candidate_receipt(lf.hash.clone());
|
||||
for _ in 0..dispute_count {
|
||||
let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Active);
|
||||
let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Confirmed);
|
||||
self.add_offchain_dispute(d.clone(), local_votes_count, dummy_receipt.clone());
|
||||
}
|
||||
(session_idx, local_votes_count * dispute_count)
|
||||
}
|
||||
|
||||
pub fn add_concluded_disputes_known_onchain(&mut self, dispute_count: usize) -> (u32, usize) {
|
||||
pub fn add_concluded_disputes_known_onchain(
|
||||
&mut self,
|
||||
dispute_count: usize,
|
||||
) -> (SessionIndex, usize) {
|
||||
let local_votes_count = self.validators_count * 90 / 100;
|
||||
let onchain_votes_count = self.validators_count * 75 / 100;
|
||||
let session_idx = 3;
|
||||
@@ -488,7 +491,10 @@ impl TestDisputes {
|
||||
(session_idx, (local_votes_count - onchain_votes_count) * dispute_count)
|
||||
}
|
||||
|
||||
pub fn add_concluded_disputes_unknown_onchain(&mut self, dispute_count: usize) -> (u32, usize) {
|
||||
pub fn add_concluded_disputes_unknown_onchain(
|
||||
&mut self,
|
||||
dispute_count: usize,
|
||||
) -> (SessionIndex, usize) {
|
||||
let local_votes_count = self.validators_count * 90 / 100;
|
||||
let session_idx = 4;
|
||||
let lf = leaf();
|
||||
@@ -500,6 +506,40 @@ impl TestDisputes {
|
||||
(session_idx, local_votes_count * dispute_count)
|
||||
}
|
||||
|
||||
pub fn add_unconfirmed_disputes_known_onchain(
|
||||
&mut self,
|
||||
dispute_count: usize,
|
||||
) -> (SessionIndex, usize) {
|
||||
let local_votes_count = self.validators_count * 10 / 100;
|
||||
let onchain_votes_count = self.validators_count * 10 / 100;
|
||||
let session_idx = 5;
|
||||
let lf = leaf();
|
||||
let dummy_receipt = test_helpers::dummy_candidate_receipt(lf.hash.clone());
|
||||
for _ in 0..dispute_count {
|
||||
let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Active);
|
||||
self.add_offchain_dispute(d.clone(), local_votes_count, dummy_receipt.clone());
|
||||
self.add_onchain_dispute(d, onchain_votes_count);
|
||||
}
|
||||
|
||||
(session_idx, (local_votes_count - onchain_votes_count) * dispute_count)
|
||||
}
|
||||
|
||||
pub fn add_unconfirmed_disputes_unknown_onchain(
|
||||
&mut self,
|
||||
dispute_count: usize,
|
||||
) -> (SessionIndex, usize) {
|
||||
let local_votes_count = self.validators_count * 10 / 100;
|
||||
let session_idx = 6;
|
||||
let lf = leaf();
|
||||
let dummy_receipt = test_helpers::dummy_candidate_receipt(lf.hash.clone());
|
||||
for _ in 0..dispute_count {
|
||||
let d = (session_idx, CandidateHash(Hash::random()), DisputeStatus::Active);
|
||||
self.add_offchain_dispute(d.clone(), local_votes_count, dummy_receipt.clone());
|
||||
}
|
||||
|
||||
(session_idx, local_votes_count * dispute_count)
|
||||
}
|
||||
|
||||
fn generate_local_votes<T: Clone>(
|
||||
statement_kind: T,
|
||||
start_idx: usize,
|
||||
@@ -554,9 +594,9 @@ fn normal_flow() {
|
||||
// concluded disputes known onchain - these should be ignored
|
||||
let (_, _) = input.add_concluded_disputes_known_onchain(DISPUTES_PER_BATCH);
|
||||
|
||||
// active disputes unknown onchain
|
||||
// confirmed disputes unknown onchain
|
||||
let (second_idx, second_votes) =
|
||||
input.add_unconfirmed_disputes_unknown_onchain(DISPUTES_PER_BATCH);
|
||||
input.add_confirmed_disputes_unknown_onchain(DISPUTES_PER_BATCH);
|
||||
|
||||
let metrics = metrics::Metrics::new_dummy();
|
||||
let mut vote_queries: usize = 0;
|
||||
@@ -635,8 +675,8 @@ fn many_batches() {
|
||||
// concluded disputes known onchain
|
||||
input.add_concluded_disputes_known_onchain(DISPUTES_PER_PARTITION);
|
||||
|
||||
// active disputes unknown onchain
|
||||
input.add_unconfirmed_disputes_unknown_onchain(DISPUTES_PER_PARTITION);
|
||||
// confirmed disputes unknown onchain
|
||||
input.add_confirmed_disputes_unknown_onchain(DISPUTES_PER_PARTITION);
|
||||
|
||||
let metrics = metrics::Metrics::new_dummy();
|
||||
let mut vote_queries: usize = 0;
|
||||
@@ -720,3 +760,30 @@ fn votes_above_limit() {
|
||||
ACCEPTABLE_RUNTIME_VOTES_QUERIES_COUNT
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unconfirmed_are_handled_correctly() {
|
||||
const VALIDATOR_COUNT: usize = 10;
|
||||
const DISPUTES_PER_PARTITION: usize = 50;
|
||||
|
||||
let mut input = TestDisputes::new(VALIDATOR_COUNT);
|
||||
|
||||
// Add unconfirmed known onchain -> this should be pushed
|
||||
let (pushed_idx, _) = input.add_unconfirmed_disputes_known_onchain(DISPUTES_PER_PARTITION);
|
||||
|
||||
// Add unconfirmed unknown onchain -> this should be ignored
|
||||
input.add_unconfirmed_disputes_unknown_onchain(DISPUTES_PER_PARTITION);
|
||||
|
||||
let metrics = metrics::Metrics::new_dummy();
|
||||
let mut vote_queries: usize = 0;
|
||||
test_harness(
|
||||
|r| mock_overseer(r, &mut input, &mut vote_queries),
|
||||
|mut tx: TestSubsystemSender| async move {
|
||||
let lf = leaf();
|
||||
let result = select_disputes(&mut tx, &metrics, &lf).await;
|
||||
|
||||
assert!(result.len() == DISPUTES_PER_PARTITION);
|
||||
result.iter().for_each(|d| assert!(d.session == pushed_idx));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -42,51 +42,35 @@ enum RequestType {
|
||||
}
|
||||
|
||||
/// Request open disputes identified by `CandidateHash` and the `SessionIndex`.
|
||||
async fn request_disputes(
|
||||
/// Returns only confirmed/concluded disputes. The rest are filtered out.
|
||||
async fn request_confirmed_disputes(
|
||||
sender: &mut impl overseer::ProvisionerSenderTrait,
|
||||
active_or_recent: RequestType,
|
||||
) -> Vec<(SessionIndex, CandidateHash)> {
|
||||
let disputes = match active_or_recent {
|
||||
RequestType::Recent => {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let msg = DisputeCoordinatorMessage::RecentDisputes(tx);
|
||||
sender.send_unbounded_message(msg);
|
||||
let recent_disputes = match rx.await {
|
||||
Ok(r) => r,
|
||||
Err(oneshot::Canceled) => {
|
||||
gum::warn!(
|
||||
target: LOG_TARGET,
|
||||
"Channel closed: unable to gather {:?} disputes",
|
||||
active_or_recent
|
||||
);
|
||||
Vec::new()
|
||||
},
|
||||
};
|
||||
recent_disputes
|
||||
.into_iter()
|
||||
.map(|(sesion_idx, candodate_hash, _)| (sesion_idx, candodate_hash))
|
||||
.collect::<Vec<_>>()
|
||||
},
|
||||
RequestType::Active => {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let msg = DisputeCoordinatorMessage::ActiveDisputes(tx);
|
||||
sender.send_unbounded_message(msg);
|
||||
let active_disputes = match rx.await {
|
||||
Ok(r) => r,
|
||||
Err(oneshot::Canceled) => {
|
||||
gum::warn!(
|
||||
target: LOG_TARGET,
|
||||
"Unable to gather {:?} disputes",
|
||||
active_or_recent
|
||||
);
|
||||
Vec::new()
|
||||
},
|
||||
};
|
||||
active_disputes
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let msg = match active_or_recent {
|
||||
RequestType::Recent => DisputeCoordinatorMessage::RecentDisputes(tx),
|
||||
RequestType::Active => DisputeCoordinatorMessage::ActiveDisputes(tx),
|
||||
};
|
||||
|
||||
sender.send_unbounded_message(msg);
|
||||
let disputes = match rx.await {
|
||||
Ok(r) => r,
|
||||
Err(oneshot::Canceled) => {
|
||||
gum::warn!(
|
||||
target: LOG_TARGET,
|
||||
"Channel closed: unable to gather {:?} disputes",
|
||||
active_or_recent
|
||||
);
|
||||
Vec::new()
|
||||
},
|
||||
};
|
||||
|
||||
disputes
|
||||
.into_iter()
|
||||
.filter(|d| d.2.is_confirmed_concluded())
|
||||
.map(|d| (d.0, d.1))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Extend `acc` by `n` random, picks of not-yet-present in `acc` items of `recent` without repetition and additions of recent.
|
||||
@@ -132,7 +116,7 @@ where
|
||||
// In case of an overload condition, we limit ourselves to active disputes, and fill up to the
|
||||
// upper bound of disputes to pass to wasm `fn create_inherent_data`.
|
||||
// If the active ones are already exceeding the bounds, randomly select a subset.
|
||||
let recent = request_disputes(sender, RequestType::Recent).await;
|
||||
let recent = request_confirmed_disputes(sender, RequestType::Recent).await;
|
||||
let disputes = if recent.len() > MAX_DISPUTES_FORWARDED_TO_RUNTIME {
|
||||
gum::warn!(
|
||||
target: LOG_TARGET,
|
||||
@@ -140,7 +124,7 @@ where
|
||||
recent.len(),
|
||||
MAX_DISPUTES_FORWARDED_TO_RUNTIME
|
||||
);
|
||||
let mut active = request_disputes(sender, RequestType::Active).await;
|
||||
let mut active = request_confirmed_disputes(sender, RequestType::Active).await;
|
||||
let n_active = active.len();
|
||||
let active = if active.len() > MAX_DISPUTES_FORWARDED_TO_RUNTIME {
|
||||
let mut picked = Vec::with_capacity(MAX_DISPUTES_FORWARDED_TO_RUNTIME);
|
||||
|
||||
Reference in New Issue
Block a user