// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see .
use super::*;
use ::test_helpers::{dummy_candidate_descriptor, dummy_hash};
use bitvec::bitvec;
use polkadot_primitives::{OccupiedCore, ScheduledCore};
const MOCK_GROUP_SIZE: usize = 5;
pub fn occupied_core(para_id: u32) -> CoreState {
let mut candidate_descriptor = dummy_candidate_descriptor(dummy_hash());
candidate_descriptor.para_id = para_id.into();
CoreState::Occupied(OccupiedCore {
group_responsible: para_id.into(),
next_up_on_available: None,
occupied_since: 100_u32,
time_out_at: 200_u32,
next_up_on_time_out: None,
availability: bitvec![u8, bitvec::order::Lsb0; 0; 32],
candidate_descriptor,
candidate_hash: Default::default(),
})
}
pub fn build_occupied_core(para_id: u32, builder: Builder) -> CoreState
where
Builder: FnOnce(&mut OccupiedCore),
{
let mut core = match occupied_core(para_id) {
CoreState::Occupied(core) => core,
_ => unreachable!(),
};
builder(&mut core);
CoreState::Occupied(core)
}
pub fn default_bitvec(size: usize) -> CoreAvailability {
bitvec![u8, bitvec::order::Lsb0; 0; size]
}
pub fn scheduled_core(id: u32) -> ScheduledCore {
ScheduledCore { para_id: id.into(), collator: None }
}
mod select_availability_bitfields {
use super::{super::*, default_bitvec, occupied_core};
use polkadot_primitives::{ScheduledCore, SigningContext, ValidatorId, ValidatorIndex};
use sp_application_crypto::AppCrypto;
use sp_keystore::{testing::MemoryKeystore, Keystore, KeystorePtr};
use std::sync::Arc;
fn signed_bitfield(
keystore: &KeystorePtr,
field: CoreAvailability,
validator_idx: ValidatorIndex,
) -> SignedAvailabilityBitfield {
let public = Keystore::sr25519_generate_new(&**keystore, ValidatorId::ID, None)
.expect("generated sr25519 key");
SignedAvailabilityBitfield::sign(
&keystore,
field.into(),
&>::default(),
validator_idx,
&public.into(),
)
.ok()
.flatten()
.expect("Should be signed")
}
#[test]
fn not_more_than_one_per_validator() {
let keystore: KeystorePtr = Arc::new(MemoryKeystore::new());
let mut bitvec = default_bitvec(2);
bitvec.set(0, true);
bitvec.set(1, true);
let cores = vec![occupied_core(0), occupied_core(1)];
// we pass in three bitfields with two validators
// this helps us check the postcondition that we get two bitfields back, for which the
// validators differ
let bitfields = vec![
signed_bitfield(&keystore, bitvec.clone(), ValidatorIndex(0)),
signed_bitfield(&keystore, bitvec.clone(), ValidatorIndex(1)),
signed_bitfield(&keystore, bitvec, ValidatorIndex(1)),
];
let mut selected_bitfields =
select_availability_bitfields(&cores, &bitfields, &Hash::repeat_byte(0));
selected_bitfields.sort_by_key(|bitfield| bitfield.validator_index());
assert_eq!(selected_bitfields.len(), 2);
assert_eq!(selected_bitfields[0], bitfields[0]);
// we don't know which of the (otherwise equal) bitfields will be selected
assert!(selected_bitfields[1] == bitfields[1] || selected_bitfields[1] == bitfields[2]);
}
#[test]
fn each_corresponds_to_an_occupied_core() {
let keystore: KeystorePtr = Arc::new(MemoryKeystore::new());
let bitvec = default_bitvec(3);
// invalid: bit on free core
let mut bitvec0 = bitvec.clone();
bitvec0.set(0, true);
// invalid: bit on scheduled core
let mut bitvec1 = bitvec.clone();
bitvec1.set(1, true);
// valid: bit on occupied core.
let mut bitvec2 = bitvec.clone();
bitvec2.set(2, true);
let cores = vec![
CoreState::Free,
CoreState::Scheduled(ScheduledCore { para_id: Default::default(), collator: None }),
occupied_core(2),
];
let bitfields = vec![
signed_bitfield(&keystore, bitvec0, ValidatorIndex(0)),
signed_bitfield(&keystore, bitvec1, ValidatorIndex(1)),
signed_bitfield(&keystore, bitvec2.clone(), ValidatorIndex(2)),
];
let selected_bitfields =
select_availability_bitfields(&cores, &bitfields, &Hash::repeat_byte(0));
// selects only the valid bitfield
assert_eq!(selected_bitfields.len(), 1);
assert_eq!(selected_bitfields[0].payload().0, bitvec2);
}
#[test]
fn more_set_bits_win_conflicts() {
let keystore: KeystorePtr = Arc::new(MemoryKeystore::new());
let mut bitvec = default_bitvec(2);
bitvec.set(0, true);
let mut bitvec1 = bitvec.clone();
bitvec1.set(1, true);
let cores = vec![occupied_core(0), occupied_core(1)];
let bitfields = vec![
signed_bitfield(&keystore, bitvec, ValidatorIndex(1)),
signed_bitfield(&keystore, bitvec1.clone(), ValidatorIndex(1)),
];
let selected_bitfields =
select_availability_bitfields(&cores, &bitfields, &Hash::repeat_byte(0));
assert_eq!(selected_bitfields.len(), 1);
assert_eq!(selected_bitfields[0].payload().0, bitvec1.clone());
}
#[test]
fn more_complex_bitfields() {
let keystore: KeystorePtr = Arc::new(MemoryKeystore::new());
let cores = vec![occupied_core(0), occupied_core(1), occupied_core(2), occupied_core(3)];
let mut bitvec0 = default_bitvec(4);
bitvec0.set(0, true);
bitvec0.set(2, true);
let mut bitvec1 = default_bitvec(4);
bitvec1.set(1, true);
let mut bitvec2 = default_bitvec(4);
bitvec2.set(2, true);
let mut bitvec3 = default_bitvec(4);
bitvec3.set(0, true);
bitvec3.set(1, true);
bitvec3.set(2, true);
bitvec3.set(3, true);
// these are out of order but will be selected in order. The better
// bitfield for 3 will be selected.
let bitfields = vec![
signed_bitfield(&keystore, bitvec2.clone(), ValidatorIndex(3)),
signed_bitfield(&keystore, bitvec3.clone(), ValidatorIndex(3)),
signed_bitfield(&keystore, bitvec0.clone(), ValidatorIndex(0)),
signed_bitfield(&keystore, bitvec2.clone(), ValidatorIndex(2)),
signed_bitfield(&keystore, bitvec1.clone(), ValidatorIndex(1)),
];
let selected_bitfields =
select_availability_bitfields(&cores, &bitfields, &Hash::repeat_byte(0));
assert_eq!(selected_bitfields.len(), 4);
assert_eq!(selected_bitfields[0].payload().0, bitvec0);
assert_eq!(selected_bitfields[1].payload().0, bitvec1);
assert_eq!(selected_bitfields[2].payload().0, bitvec2);
assert_eq!(selected_bitfields[3].payload().0, bitvec3);
}
}
pub(crate) mod common {
use super::super::*;
use futures::channel::mpsc;
use polkadot_node_subsystem::messages::AllMessages;
use polkadot_node_subsystem_test_helpers::TestSubsystemSender;
pub fn test_harness(
overseer_factory: OverseerFactory,
test_factory: TestFactory,
) where
OverseerFactory: FnOnce(mpsc::UnboundedReceiver) -> Overseer,
Overseer: Future