avoid expect, on free availability core (#3994)

* MVP fix

* bump spec version rococo

* fmt

* better var names

* remove duplicate desc

* expand comment
This commit is contained in:
Bernhard Schuster
2021-10-03 13:09:53 +02:00
committed by GitHub
parent c48b2f08ad
commit 5a1dc74a9a
2 changed files with 25 additions and 13 deletions
+24 -12
View File
@@ -240,8 +240,10 @@ impl<T: Config> Pallet<T> {
for _ in <AvailabilityBitfields<T>>::drain() {}
}
/// Process a set of incoming bitfields. Return a `vec` of cores freed by candidates
/// becoming available.
/// Process a set of incoming bitfields.
///
/// Returns a `Vec` of `CandidateHash`es and their respective `AvailabilityCore`s that became available,
/// and cores free.
pub(crate) fn process_bitfields(
expected_bits: usize,
unchecked_bitfields: UncheckedSignedAvailabilityBitfields,
@@ -250,10 +252,12 @@ impl<T: Config> Pallet<T> {
let validators = shared::Pallet::<T>::active_validator_keys();
let session_index = shared::Pallet::<T>::session_index();
let mut assigned_paras_record: Vec<_> = (0..expected_bits)
let mut assigned_paras_record = (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();
.map(|opt_para_id| {
opt_para_id.map(|para_id| (para_id, PendingAvailability::<T>::get(&para_id)))
})
.collect::<Vec<_>>();
// do sanity checks on the bitfields:
// 1. no more than one bitfield per validator
@@ -320,17 +324,25 @@ impl<T: Config> Pallet<T> {
for (bit_idx, _) in
signed_bitfield.payload().0.iter().enumerate().filter(|(_, is_av)| **is_av)
{
let (_, pending_availability) = assigned_paras_record[bit_idx]
.as_mut()
.expect("validator bitfields checked not to contain bits corresponding to unoccupied cores; qed");
let pending_availability = if let Some((_, pending_availability)) =
assigned_paras_record[bit_idx].as_mut()
{
pending_availability
} else {
// For honest validators, this happens in case of unoccupied cores,
// which in turn happens in case of a disputed candidate.
// A malicious one might include arbitrary indices, but they are represented
// by `None` values and will be sorted out in the next if case.
continue
};
// defensive check - this is constructed by loading the availability bitfield record,
// which is always `Some` if the core is occupied - that's why we're here.
let val_idx = signed_bitfield.validator_index().0 as usize;
if let Some(mut bit) = pending_availability
.as_mut()
.and_then(|r| r.availability_votes.get_mut(val_idx))
{
if let Some(mut bit) =
pending_availability.as_mut().and_then(|candidate_pending_availability| {
candidate_pending_availability.availability_votes.get_mut(val_idx)
}) {
*bit = true;
} else if cfg!(debug_assertions) {
ensure!(false, Error::<T>::InternalError);