Approval Checking Improvements Omnibus (#2480)

* add tracing to approval voting

* notify if session info is not working

* add dispute period to chain specs

* propagate genesis session to parachains runtime

* use `on_genesis_session`

* protect against zero cores in computation

* tweak voting rule to be based off of best and add logs

* genesis configuration should use VRF slots only

* swallow more keystore errors

* add some docs

* make validation-worker args non-optional and update clap

* better tracing for bitfield signing and provisioner

* pass amount of bits in bitfields to inclusion instead of recomputing

* debug -> warn for some logs

* better tracing for availability recovery

* a little av-store tracing

* bridge: forward availability recovery messages

* add missing try_from impl

* some more tracing

* improve approval distribution tracing

* guide: hold onto pending approval messages until NewBlocks

* Hold onto pending approval messages until NewBlocks

* guide: adjust comment

* process all actions for one wakeup at a time

* vec

* fix network bridge test

* replace randomness-collective-flip with Babe

* remove PairNotFound
This commit is contained in:
Robert Habermeier
2021-02-23 14:12:28 -06:00
committed by GitHub
parent 3c4ed7b234
commit 3300b53306
27 changed files with 647 additions and 132 deletions
+38 -12
View File
@@ -238,17 +238,14 @@ impl<T: Config> Module<T> {
/// Process a set of incoming bitfields. Return a vec of cores freed by candidates
/// becoming available.
pub(crate) fn process_bitfields(
expected_bits: usize,
signed_bitfields: SignedAvailabilityBitfields,
core_lookup: impl Fn(CoreIndex) -> Option<ParaId>,
) -> Result<Vec<CoreIndex>, DispatchError> {
let validators = Validators::get();
let session_index = shared::Module::<T>::session_index();
let config = <configuration::Module<T>>::config();
let parachains = <paras::Module<T>>::parachains();
let n_bits = parachains.len() + config.parathread_cores as usize;
let mut assigned_paras_record: Vec<_> = (0..n_bits)
let mut assigned_paras_record: Vec<_> = (0..expected_bits)
.map(|bit_index| core_lookup(CoreIndex::from(bit_index as u32)))
.map(|core_para| core_para.map(|p| (p, PendingAvailability::<T>::get(&p))))
.collect();
@@ -256,7 +253,7 @@ impl<T: Config> Module<T> {
// do sanity checks on the bitfields:
// 1. no more than one bitfield per validator
// 2. bitfields are ascending by validator index.
// 3. each bitfield has exactly `n_bits`
// 3. each bitfield has exactly `expected_bits`
// 4. signature is valid.
{
let occupied_bitmask: BitVec<BitOrderLsb0, u8> = assigned_paras_record.iter()
@@ -274,7 +271,7 @@ impl<T: Config> Module<T> {
for signed_bitfield in &signed_bitfields {
ensure!(
signed_bitfield.payload().0.len() == n_bits,
signed_bitfield.payload().0.len() == expected_bits,
Error::<T>::WrongBitfieldSize,
);
@@ -336,7 +333,7 @@ impl<T: Config> Module<T> {
let threshold = availability_threshold(validators.len());
let mut freed_cores = Vec::with_capacity(n_bits);
let mut freed_cores = Vec::with_capacity(expected_bits);
for (para_id, pending_availability) in assigned_paras_record.into_iter()
.filter_map(|x| x)
.filter_map(|(id, p)| p.map(|p| (id, p)))
@@ -1060,10 +1057,12 @@ mod tests {
}
}
fn default_bitfield() -> AvailabilityBitfield {
let n_bits = Paras::parachains().len() + Configuration::config().parathread_cores as usize;
fn expected_bits() -> usize {
Paras::parachains().len() + Configuration::config().parathread_cores as usize
}
AvailabilityBitfield(bitvec::bitvec![BitOrderLsb0, u8; 0; n_bits])
fn default_bitfield() -> AvailabilityBitfield {
AvailabilityBitfield(bitvec::bitvec![BitOrderLsb0, u8; 0; expected_bits()])
}
fn default_availability_votes() -> BitVec<BitOrderLsb0, u8> {
@@ -1228,7 +1227,8 @@ mod tests {
core if core == CoreIndex::from(0) => Some(chain_a),
core if core == CoreIndex::from(1) => Some(chain_b),
core if core == CoreIndex::from(2) => Some(thread_a),
_ => panic!("Core out of bounds for 2 parachains and 1 parathread core."),
core if core == CoreIndex::from(3) => None, // for the expected_cores() + 1 test below.
_ => panic!("out of bounds for testing"),
};
// wrong number of bits.
@@ -1244,6 +1244,25 @@ mod tests {
));
assert!(Inclusion::process_bitfields(
expected_bits(),
vec![signed],
&core_lookup,
).is_err());
}
// wrong number of bits: other way around.
{
let bare_bitfield = default_bitfield();
let signed = block_on(sign_bitfield(
&keystore,
&validators[0],
0,
bare_bitfield,
&signing_context,
));
assert!(Inclusion::process_bitfields(
expected_bits() + 1,
vec![signed],
&core_lookup,
).is_err());
@@ -1261,6 +1280,7 @@ mod tests {
));
assert!(Inclusion::process_bitfields(
expected_bits(),
vec![signed.clone(), signed],
&core_lookup,
).is_err());
@@ -1286,6 +1306,7 @@ mod tests {
));
assert!(Inclusion::process_bitfields(
expected_bits(),
vec![signed_1, signed_0],
&core_lookup,
).is_err());
@@ -1304,6 +1325,7 @@ mod tests {
));
assert!(Inclusion::process_bitfields(
expected_bits(),
vec![signed],
&core_lookup,
).is_err());
@@ -1321,6 +1343,7 @@ mod tests {
));
assert!(Inclusion::process_bitfields(
expected_bits(),
vec![signed],
&core_lookup,
).is_ok());
@@ -1355,6 +1378,7 @@ mod tests {
));
assert!(Inclusion::process_bitfields(
expected_bits(),
vec![signed],
&core_lookup,
).is_ok());
@@ -1393,6 +1417,7 @@ mod tests {
// no core is freed
assert_eq!(
Inclusion::process_bitfields(
expected_bits(),
vec![signed],
&core_lookup,
),
@@ -1516,6 +1541,7 @@ mod tests {
}).collect();
assert!(Inclusion::process_bitfields(
expected_bits(),
signed_bitfields,
&core_lookup,
).is_ok());
@@ -107,7 +107,9 @@ decl_module! {
// Process new availability bitfields, yielding any availability cores whose
// work has now concluded.
let expected_bits = <scheduler::Module<T>>::availability_cores().len();
let freed_concluded = <inclusion::Module<T>>::process_bitfields(
expected_bits,
signed_bitfields,
<scheduler::Module<T>>::core_para,
)?;
+32 -8
View File
@@ -229,11 +229,17 @@ impl<T: Config> Module<T> {
validators.clone()
};
BufferedSessionChanges::mutate(|v| v.push(BufferedSessionChange {
validators,
queued,
session_index,
}));
if session_index == 0 {
// Genesis session should be immediately enacted.
Self::apply_new_session(0, validators, queued);
} else {
BufferedSessionChanges::mutate(|v| v.push(BufferedSessionChange {
validators,
queued,
session_index,
}));
}
}
}
@@ -244,10 +250,10 @@ impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Module<T> {
impl<T: pallet_session::Config + Config> OneSessionHandler<T::AccountId> for Module<T> {
type Key = ValidatorId;
fn on_genesis_session<'a, I: 'a>(_validators: I)
fn on_genesis_session<'a, I: 'a>(validators: I)
where I: Iterator<Item=(&'a T::AccountId, Self::Key)>
{
<Module<T>>::on_new_session(false, 0, validators, None);
}
fn on_new_session<'a, I: 'a>(changed: bool, validators: I, queued: I)
@@ -266,7 +272,7 @@ mod tests {
use primitives::v1::{Id as ParaId};
use crate::mock::{
new_test_ext,
Initializer, System, Dmp, Paras, Configuration, MockGenesisConfig,
Initializer, System, Dmp, Paras, Configuration, SessionInfo, MockGenesisConfig,
};
use frame_support::{
@@ -274,6 +280,24 @@ mod tests {
traits::{OnFinalize, OnInitialize},
};
#[test]
fn session_0_is_instantly_applied() {
new_test_ext(Default::default()).execute_with(|| {
Initializer::on_new_session(
false,
0,
Vec::new().into_iter(),
Some(Vec::new().into_iter()),
);
let v = <BufferedSessionChanges>::get();
assert!(v.is_empty());
assert_eq!(SessionInfo::earliest_stored_session(), 0);
assert!(SessionInfo::session_info(0).is_some());
});
}
#[test]
fn session_change_before_initialize_is_still_buffered_after() {
new_test_ext(Default::default()).execute_with(|| {