diff --git a/polkadot/node/core/dispute-coordinator/src/initialized.rs b/polkadot/node/core/dispute-coordinator/src/initialized.rs index e588a21b4f173..26b8abf806e95 100644 --- a/polkadot/node/core/dispute-coordinator/src/initialized.rs +++ b/polkadot/node/core/dispute-coordinator/src/initialized.rs @@ -852,9 +852,7 @@ impl Initialized { }; gum::trace!(target: LOG_TARGET, "Loaded recent disputes from db"); - let _ = tx.send( - recent_disputes.into_iter().map(|(k, v)| (k.0, k.1, v)).collect::>(), - ); + let _ = tx.send(recent_disputes); }, DisputeCoordinatorMessage::ActiveDisputes(tx) => { gum::trace!(target: LOG_TARGET, "DisputeCoordinatorMessage::ActiveDisputes"); @@ -866,10 +864,7 @@ impl Initialized { let _ = tx.send( get_active_with_status(recent_disputes.into_iter(), now) - .map(|((session_idx, candidate_hash), dispute_status)| { - (session_idx, candidate_hash, dispute_status) - }) - .collect(), + .collect::>(), ); }, DisputeCoordinatorMessage::QueryCandidateVotes(query, tx) => { diff --git a/polkadot/node/core/dispute-coordinator/src/tests.rs b/polkadot/node/core/dispute-coordinator/src/tests.rs index 3d59887e5d1f4..bd3ffc5d9eede 100644 --- a/polkadot/node/core/dispute-coordinator/src/tests.rs +++ b/polkadot/node/core/dispute-coordinator/src/tests.rs @@ -15,7 +15,7 @@ // along with Polkadot. If not, see . use std::{ - collections::HashMap, + collections::{BTreeMap, HashMap}, sync::{ atomic::{AtomicU64, Ordering as AtomicOrdering}, Arc, @@ -773,10 +773,9 @@ fn too_many_unconfirmed_statements_are_considered_spam() { msg: DisputeCoordinatorMessage::ActiveDisputes(tx), }) .await; - assert_eq!( rx.await.unwrap(), - vec![(session, candidate_hash1, DisputeStatus::Active)] + BTreeMap::from([((session, candidate_hash1), DisputeStatus::Active)]) ); let (tx, rx) = oneshot::channel(); @@ -910,7 +909,7 @@ fn approval_vote_import_works() { assert_eq!( rx.await.unwrap(), - vec![(session, candidate_hash1, DisputeStatus::Active)] + BTreeMap::from([((session, candidate_hash1), DisputeStatus::Active)]) ); let (tx, rx) = oneshot::channel(); @@ -1023,7 +1022,7 @@ fn dispute_gets_confirmed_via_participation() { assert_eq!( rx.await.unwrap(), - vec![(session, candidate_hash1, DisputeStatus::Active)] + BTreeMap::from([((session, candidate_hash1), DisputeStatus::Active)]) ); let (tx, rx) = oneshot::channel(); @@ -1168,7 +1167,7 @@ fn dispute_gets_confirmed_at_byzantine_threshold() { assert_eq!( rx.await.unwrap(), - vec![(session, candidate_hash1, DisputeStatus::Confirmed)] + BTreeMap::from([((session, candidate_hash1), DisputeStatus::Confirmed)]) ); let (tx, rx) = oneshot::channel(); @@ -1430,7 +1429,7 @@ fn conflicting_votes_lead_to_dispute_participation() { assert_eq!( rx.await.unwrap(), - vec![(session, candidate_hash, DisputeStatus::Active)] + BTreeMap::from([((session, candidate_hash), DisputeStatus::Active)]) ); let (tx, rx) = oneshot::channel(); diff --git a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/mod.rs b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/mod.rs index d7a5a8113369f..efab989cb0ec5 100644 --- a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/mod.rs +++ b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/mod.rs @@ -153,15 +153,15 @@ where ); gum::trace!(target: LOG_TARGET, ?leaf, "Filtering recent disputes"); - // 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::>(); - + .filter(|(key, dispute_status)| { + dispute_status.is_confirmed_concluded() || onchain.contains_key(key) + }) + .collect::>(); gum::trace!(target: LOG_TARGET, ?leaf, "Partitioning recent disputes"); let partitioned = partition_recent_disputes(recent_disputes, &onchain); metrics.on_partition_recent_disputes(&partitioned); @@ -337,53 +337,38 @@ fn concluded_onchain(onchain_state: &DisputeState) -> bool { } fn partition_recent_disputes( - recent: Vec<(SessionIndex, CandidateHash, DisputeStatus)>, + recent: BTreeMap<(SessionIndex, CandidateHash), DisputeStatus>, onchain: &HashMap<(SessionIndex, CandidateHash), DisputeState>, ) -> PartitionedDisputes { let mut partitioned = PartitionedDisputes::new(); - - // Drop any duplicates - let unique_recent = recent - .into_iter() - .map(|(session_index, candidate_hash, dispute_state)| { - ((session_index, candidate_hash), dispute_state) - }) - .collect::>(); - - // Split recent disputes in ACTIVE and INACTIVE let time_now = &secs_since_epoch(); - let (active, inactive): ( - Vec<(SessionIndex, CandidateHash, DisputeStatus)>, - Vec<(SessionIndex, CandidateHash, DisputeStatus)>, - ) = unique_recent - .into_iter() - .map(|((session_index, candidate_hash), dispute_state)| { - (session_index, candidate_hash, dispute_state) - }) - .partition(|(_, _, status)| !dispute_is_inactive(status, time_now)); - - // Split ACTIVE in three groups... - for (session_index, candidate_hash, _) in active { - match onchain.get(&(session_index, candidate_hash)) { - Some(d) => match concluded_onchain(d) { - true => partitioned.active_concluded_onchain.push((session_index, candidate_hash)), - false => - partitioned.active_unconcluded_onchain.push((session_index, candidate_hash)), - }, - None => partitioned.active_unknown_onchain.push((session_index, candidate_hash)), - }; - } - // ... and INACTIVE in three more - for (session_index, candidate_hash, _) in inactive { - match onchain.get(&(session_index, candidate_hash)) { - Some(onchain_state) => - if concluded_onchain(onchain_state) { - partitioned.inactive_concluded_onchain.push((session_index, candidate_hash)); - } else { - partitioned.inactive_unconcluded_onchain.push((session_index, candidate_hash)); + for ((session_index, candidate_hash), dispute_state) in recent { + let key = (session_index, candidate_hash); + if dispute_is_inactive(&dispute_state, time_now) { + match onchain.get(&key) { + Some(onchain_state) => + if concluded_onchain(onchain_state) { + partitioned + .inactive_concluded_onchain + .push((session_index, candidate_hash)); + } else { + partitioned + .inactive_unconcluded_onchain + .push((session_index, candidate_hash)); + }, + None => partitioned.inactive_unknown_onchain.push((session_index, candidate_hash)), + } + } else { + match onchain.get(&(session_index, candidate_hash)) { + Some(d) => match concluded_onchain(d) { + true => + partitioned.active_concluded_onchain.push((session_index, candidate_hash)), + false => + partitioned.active_unconcluded_onchain.push((session_index, candidate_hash)), }, - None => partitioned.inactive_unknown_onchain.push((session_index, candidate_hash)), + None => partitioned.active_unknown_onchain.push((session_index, candidate_hash)), + } } } @@ -441,7 +426,7 @@ fn is_vote_worth_to_keep( /// Request disputes identified by `CandidateHash` and the `SessionIndex`. async fn request_disputes( sender: &mut impl overseer::ProvisionerSenderTrait, -) -> Vec<(SessionIndex, CandidateHash, DisputeStatus)> { +) -> BTreeMap<(SessionIndex, CandidateHash), DisputeStatus> { let (tx, rx) = oneshot::channel(); let msg = DisputeCoordinatorMessage::RecentDisputes(tx); @@ -450,7 +435,7 @@ async fn request_disputes( let recent_disputes = rx.await.unwrap_or_else(|err| { gum::warn!(target: LOG_TARGET, err=?err, "Unable to gather recent disputes"); - Vec::new() + BTreeMap::new() }); recent_disputes } diff --git a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs index 1f814989fc6a8..45569a48bc872 100644 --- a/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs +++ b/polkadot/node/core/provisioner/src/disputes/prioritized_selection/tests.rs @@ -124,26 +124,24 @@ fn should_keep_vote_behaves() { #[test] fn partitioning_happy_case() { - let mut input = Vec::<(SessionIndex, CandidateHash, DisputeStatus)>::new(); + let mut input = BTreeMap::<(SessionIndex, CandidateHash), DisputeStatus>::new(); let mut onchain = HashMap::<(u32, CandidateHash), DisputeState>::new(); let time_now = secs_since_epoch(); // Create one dispute for each partition let inactive_unknown_onchain = ( - 0, - CandidateHash(Hash::random()), + (0, CandidateHash(Hash::random())), DisputeStatus::ConcludedFor(time_now - ACTIVE_DURATION_SECS * 2), ); - input.push(inactive_unknown_onchain); + input.insert(inactive_unknown_onchain.0, inactive_unknown_onchain.1); let inactive_unconcluded_onchain = ( - 1, - CandidateHash(Hash::random()), + (1, CandidateHash(Hash::random())), DisputeStatus::ConcludedFor(time_now - ACTIVE_DURATION_SECS * 2), ); - input.push(inactive_unconcluded_onchain); + input.insert(inactive_unconcluded_onchain.0, inactive_unconcluded_onchain.1); onchain.insert( - (inactive_unconcluded_onchain.0, inactive_unconcluded_onchain.1), + inactive_unconcluded_onchain.0, DisputeState { validators_for: bitvec![u8, Lsb0; 1, 1, 1, 0, 0, 0, 0, 0, 0], validators_against: bitvec![u8, Lsb0; 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -152,13 +150,13 @@ fn partitioning_happy_case() { }, ); - let active_unknown_onchain = (2, CandidateHash(Hash::random()), DisputeStatus::Active); - input.push(active_unknown_onchain); + let active_unknown_onchain = ((2, CandidateHash(Hash::random())), DisputeStatus::Active); + input.insert(active_unknown_onchain.0, active_unknown_onchain.1); - let active_unconcluded_onchain = (3, CandidateHash(Hash::random()), DisputeStatus::Active); - input.push(active_unconcluded_onchain); + let active_unconcluded_onchain = ((3, CandidateHash(Hash::random())), DisputeStatus::Active); + input.insert(active_unconcluded_onchain.0, active_unconcluded_onchain.1); onchain.insert( - (active_unconcluded_onchain.0, active_unconcluded_onchain.1), + active_unconcluded_onchain.0, DisputeState { validators_for: bitvec![u8, Lsb0; 1, 1, 1, 0, 0, 0, 0, 0, 0], validators_against: bitvec![u8, Lsb0; 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -167,10 +165,10 @@ fn partitioning_happy_case() { }, ); - let active_concluded_onchain = (4, CandidateHash(Hash::random()), DisputeStatus::Active); - input.push(active_concluded_onchain); + let active_concluded_onchain = ((4, CandidateHash(Hash::random())), DisputeStatus::Active); + input.insert(active_concluded_onchain.0, active_concluded_onchain.1); onchain.insert( - (active_concluded_onchain.0, active_concluded_onchain.1), + active_concluded_onchain.0, DisputeState { validators_for: bitvec![u8, Lsb0; 1, 1, 1, 1, 1, 1, 1, 1, 0], validators_against: bitvec![u8, Lsb0; 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -180,13 +178,12 @@ fn partitioning_happy_case() { ); let inactive_concluded_onchain = ( - 5, - CandidateHash(Hash::random()), + (5, CandidateHash(Hash::random())), DisputeStatus::ConcludedFor(time_now - ACTIVE_DURATION_SECS * 2), ); - input.push(inactive_concluded_onchain); + input.insert(inactive_concluded_onchain.0, inactive_concluded_onchain.1); onchain.insert( - (inactive_concluded_onchain.0, inactive_concluded_onchain.1), + inactive_concluded_onchain.0, DisputeState { validators_for: bitvec![u8, Lsb0; 1, 1, 1, 1, 1, 1, 1, 0, 0], validators_against: bitvec![u8, Lsb0; 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -199,40 +196,25 @@ fn partitioning_happy_case() { // Check results assert_eq!(result.inactive_unknown_onchain.len(), 1); - assert_eq!( - result.inactive_unknown_onchain.get(0).unwrap(), - &(inactive_unknown_onchain.0, inactive_unknown_onchain.1) - ); + assert_eq!(result.inactive_unknown_onchain.get(0).unwrap(), &inactive_unknown_onchain.0); assert_eq!(result.inactive_unconcluded_onchain.len(), 1); assert_eq!( result.inactive_unconcluded_onchain.get(0).unwrap(), - &(inactive_unconcluded_onchain.0, inactive_unconcluded_onchain.1) + &inactive_unconcluded_onchain.0 ); assert_eq!(result.active_unknown_onchain.len(), 1); - assert_eq!( - result.active_unknown_onchain.get(0).unwrap(), - &(active_unknown_onchain.0, active_unknown_onchain.1) - ); + assert_eq!(result.active_unknown_onchain.get(0).unwrap(), &active_unknown_onchain.0); assert_eq!(result.active_unconcluded_onchain.len(), 1); - assert_eq!( - result.active_unconcluded_onchain.get(0).unwrap(), - &(active_unconcluded_onchain.0, active_unconcluded_onchain.1) - ); + assert_eq!(result.active_unconcluded_onchain.get(0).unwrap(), &active_unconcluded_onchain.0); assert_eq!(result.active_concluded_onchain.len(), 1); - assert_eq!( - result.active_concluded_onchain.get(0).unwrap(), - &(active_concluded_onchain.0, active_concluded_onchain.1) - ); + assert_eq!(result.active_concluded_onchain.get(0).unwrap(), &active_concluded_onchain.0); assert_eq!(result.inactive_concluded_onchain.len(), 1); - assert_eq!( - result.inactive_concluded_onchain.get(0).unwrap(), - &(inactive_concluded_onchain.0, inactive_concluded_onchain.1) - ); + assert_eq!(result.inactive_concluded_onchain.get(0).unwrap(), &inactive_concluded_onchain.0); } // This test verifies the double voting behavior. Currently we don't care if a supermajority is @@ -242,20 +224,20 @@ fn partitioning_happy_case() { // in the future. Link to the PR with the discussions: https://github.com/paritytech/polkadot/pull/5567 #[test] fn partitioning_doubled_onchain_vote() { - let mut input = Vec::<(SessionIndex, CandidateHash, DisputeStatus)>::new(); + let mut input = BTreeMap::<(SessionIndex, CandidateHash), DisputeStatus>::new(); let mut onchain = HashMap::<(u32, CandidateHash), DisputeState>::new(); // Dispute A relies on a 'double onchain vote' to conclude. Validator with index 0 has voted // both `for` and `against`. Despite that this dispute should be considered 'can conclude // onchain'. - let dispute_a = (3, CandidateHash(Hash::random()), DisputeStatus::Active); + let dispute_a = ((3, CandidateHash(Hash::random())), DisputeStatus::Active); // Dispute B has supermajority + 1 votes, so the doubled onchain vote doesn't affect it. It // should be considered as 'can conclude onchain'. - let dispute_b = (4, CandidateHash(Hash::random()), DisputeStatus::Active); - input.push(dispute_a); - input.push(dispute_b); + let dispute_b = ((4, CandidateHash(Hash::random())), DisputeStatus::Active); + input.insert(dispute_a.0, dispute_a.1); + input.insert(dispute_b.0, dispute_b.1); onchain.insert( - (dispute_a.0, dispute_a.1), + dispute_a.0, DisputeState { validators_for: bitvec![u8, Lsb0; 1, 1, 1, 1, 1, 1, 1, 0, 0], validators_against: bitvec![u8, Lsb0; 1, 0, 0, 0, 0, 0, 0, 0, 0], @@ -264,7 +246,7 @@ fn partitioning_doubled_onchain_vote() { }, ); onchain.insert( - (dispute_b.0, dispute_b.1), + dispute_b.0, DisputeState { validators_for: bitvec![u8, Lsb0; 1, 1, 1, 1, 1, 1, 1, 1, 0], validators_against: bitvec![u8, Lsb0; 1, 0, 0, 0, 0, 0, 0, 0, 0], @@ -281,14 +263,14 @@ fn partitioning_doubled_onchain_vote() { #[test] fn partitioning_duplicated_dispute() { - let mut input = Vec::<(SessionIndex, CandidateHash, DisputeStatus)>::new(); + let mut input = BTreeMap::<(SessionIndex, CandidateHash), DisputeStatus>::new(); let mut onchain = HashMap::<(u32, CandidateHash), DisputeState>::new(); - let some_dispute = (3, CandidateHash(Hash::random()), DisputeStatus::Active); - input.push(some_dispute); - input.push(some_dispute); + let some_dispute = ((3, CandidateHash(Hash::random())), DisputeStatus::Active); + input.insert(some_dispute.0, some_dispute.1); + input.insert(some_dispute.0, some_dispute.1); onchain.insert( - (some_dispute.0, some_dispute.1), + some_dispute.0, DisputeState { validators_for: bitvec![u8, Lsb0; 1, 1, 1, 0, 0, 0, 0, 0, 0], validators_against: bitvec![u8, Lsb0; 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -300,10 +282,7 @@ fn partitioning_duplicated_dispute() { let result = partition_recent_disputes(input, &onchain); assert_eq!(result.active_unconcluded_onchain.len(), 1); - assert_eq!( - result.active_unconcluded_onchain.get(0).unwrap(), - &(some_dispute.0, some_dispute.1) - ); + assert_eq!(result.active_unconcluded_onchain.get(0).unwrap(), &some_dispute.0); } // @@ -355,7 +334,7 @@ fn leaf() -> ActivatedLeaf { } struct TestDisputes { - pub local_disputes: Vec<(SessionIndex, CandidateHash, DisputeStatus)>, + pub local_disputes: BTreeMap<(SessionIndex, CandidateHash), DisputeStatus>, pub votes_db: HashMap<(SessionIndex, CandidateHash), CandidateVotes>, pub onchain_disputes: HashMap<(u32, CandidateHash), DisputeState>, validators_count: usize, @@ -364,7 +343,7 @@ struct TestDisputes { impl TestDisputes { pub fn new(validators_count: usize) -> TestDisputes { TestDisputes { - local_disputes: Vec::<(SessionIndex, CandidateHash, DisputeStatus)>::new(), + local_disputes: BTreeMap::<(SessionIndex, CandidateHash), DisputeStatus>::new(), votes_db: HashMap::<(SessionIndex, CandidateHash), CandidateVotes>::new(), onchain_disputes: HashMap::<(u32, CandidateHash), DisputeState>::new(), validators_count, @@ -378,7 +357,7 @@ impl TestDisputes { local_votes_count: usize, dummy_receipt: CandidateReceipt, ) { - self.local_disputes.push(dispute); + self.local_disputes.insert((dispute.0, dispute.1), dispute.2); self.votes_db.insert( (dispute.0, dispute.1), CandidateVotes { diff --git a/polkadot/node/network/dispute-distribution/src/sender/mod.rs b/polkadot/node/network/dispute-distribution/src/sender/mod.rs index 8187f20146c7a..ff1263573cd88 100644 --- a/polkadot/node/network/dispute-distribution/src/sender/mod.rs +++ b/polkadot/node/network/dispute-distribution/src/sender/mod.rs @@ -15,7 +15,7 @@ // along with Polkadot. If not, see . use std::{ - collections::{HashMap, HashSet}, + collections::{BTreeMap, HashMap, HashSet}, pin::Pin, task::Poll, time::Duration, @@ -57,7 +57,7 @@ pub enum DisputeSenderMessage { /// A task finished. TaskFinish(TaskFinish), /// A request for active disputes to the dispute-coordinator finished. - ActiveDisputesReady(JfyiErrorResult>), + ActiveDisputesReady(JfyiErrorResult>), } /// The `DisputeSender` keeps track of all ongoing disputes we need to send statements out. @@ -255,10 +255,11 @@ impl DisputeSender { &mut self, ctx: &mut Context, runtime: &mut RuntimeInfo, - active_disputes: Vec<(SessionIndex, CandidateHash, DisputeStatus)>, + active_disputes: BTreeMap<(SessionIndex, CandidateHash), DisputeStatus>, have_new_sessions: bool, ) -> Result<()> { - let active_disputes: HashSet<_> = active_disputes.into_iter().map(|(_, c, _)| c).collect(); + let active_disputes: HashSet<_> = + active_disputes.into_iter().map(|((_, c), _)| c).collect(); // Cleanup obsolete senders (retain keeps order of remaining elements): self.disputes @@ -380,7 +381,7 @@ async fn get_active_session_indices( /// Retrieve Set of active disputes from the dispute coordinator. async fn get_active_disputes( sender: &mut Sender, -) -> JfyiErrorResult> +) -> JfyiErrorResult> where Sender: SubsystemSender, { diff --git a/polkadot/node/network/dispute-distribution/src/tests/mod.rs b/polkadot/node/network/dispute-distribution/src/tests/mod.rs index e0eae5703b7e6..b7615591496b4 100644 --- a/polkadot/node/network/dispute-distribution/src/tests/mod.rs +++ b/polkadot/node/network/dispute-distribution/src/tests/mod.rs @@ -18,7 +18,7 @@ //! Subsystem unit tests use std::{ - collections::HashSet, + collections::{BTreeMap, HashSet}, task::Poll, time::{Duration, Instant}, }; @@ -491,7 +491,7 @@ fn send_dispute_gets_cleaned_up() { MOCK_SESSION_INDEX, None, // No disputes any more: - Vec::new(), + BTreeMap::new(), ) .await; @@ -542,7 +542,7 @@ fn dispute_retries_and_works_across_session_boundaries() { Some(old_head), MOCK_SESSION_INDEX, None, - vec![(MOCK_SESSION_INDEX, candidate.hash(), DisputeStatus::Active)], + BTreeMap::from([((MOCK_SESSION_INDEX, candidate.hash()), DisputeStatus::Active)]), ) .await; @@ -557,7 +557,7 @@ fn dispute_retries_and_works_across_session_boundaries() { Some(old_head2), MOCK_NEXT_SESSION_INDEX, Some(MOCK_NEXT_SESSION_INFO.clone()), - vec![(MOCK_SESSION_INDEX, candidate.hash(), DisputeStatus::Active)], + BTreeMap::from([((MOCK_SESSION_INDEX, candidate.hash()), DisputeStatus::Active)]), ) .await; @@ -736,7 +736,7 @@ async fn activate_leaf( // New session if we expect the subsystem to request it. new_session: Option, // Currently active disputes to send to the subsystem. - active_disputes: Vec<(SessionIndex, CandidateHash, DisputeStatus)>, + active_disputes: BTreeMap<(SessionIndex, CandidateHash), DisputeStatus>, ) { handle .send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { @@ -851,7 +851,7 @@ async fn handle_subsystem_startup( Some(MOCK_SESSION_INFO.clone()), ongoing_dispute .into_iter() - .map(|c| (MOCK_SESSION_INDEX, c, DisputeStatus::Active)) + .map(|c| ((MOCK_SESSION_INDEX, c), DisputeStatus::Active)) .collect(), ) .await; diff --git a/polkadot/node/subsystem-types/src/messages.rs b/polkadot/node/subsystem-types/src/messages.rs index 9b4a3f99067e6..b4fa0a985b213 100644 --- a/polkadot/node/subsystem-types/src/messages.rs +++ b/polkadot/node/subsystem-types/src/messages.rs @@ -318,10 +318,10 @@ pub enum DisputeCoordinatorMessage { /// Fetch a list of all recent disputes the coordinator is aware of. /// These are disputes which have occurred any time in recent sessions, /// and which may have already concluded. - RecentDisputes(oneshot::Sender>), + RecentDisputes(oneshot::Sender>), /// Fetch a list of all active disputes that the coordinator is aware of. /// These disputes are either not yet concluded or recently concluded. - ActiveDisputes(oneshot::Sender>), + ActiveDisputes(oneshot::Sender>), /// Get candidate votes for a candidate. QueryCandidateVotes( Vec<(SessionIndex, CandidateHash)>, diff --git a/prdoc/pr_9309.prdoc b/prdoc/pr_9309.prdoc new file mode 100644 index 0000000000000..92a12be1dcb65 --- /dev/null +++ b/prdoc/pr_9309.prdoc @@ -0,0 +1,21 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Make RecentDisputes/ActiveDisputes use BTreeMap + +doc: + - audience: Node Dev + description: | + Make dispute-coordinator forward BTreeMap/BTreeSet to provisioner directly instead of converting it to Vec as before. + +crates: +- name: polkadot-node-primitives + bump: major +- name: polkadot-node-subsystem-types + bump: major +- name: polkadot-dispute-distribution + bump: major +- name: polkadot-node-core-dispute-coordinator + bump: major +- name: polkadot-node-core-provisioner + bump: major