Unverified Commit 16fb4698 authored by Bernhard Schuster's avatar Bernhard Schuster Committed by GitHub
Browse files

prefer code upgrades in inherent filtering (#4334)

* impl prefered items

Closes #4330

* do not stop attempting to select, just because one did not fit

* doc

* prefered -> preferred

* missing usage of the preferred indices

* sigh

* shuffle is not available for chacha

* remove duplicate weight addition

* ref vs no ref
parent 71e76705
Pipeline #167027 passed with stages
in 49 minutes and 32 seconds
...@@ -688,7 +688,7 @@ where ...@@ -688,7 +688,7 @@ where
DisputedBitfield::from(bitvec) DisputedBitfield::from(bitvec)
} }
/// Select a random subset /// Select a random subset, with preference for certain indices.
/// ///
/// Adds random items to the set until all candidates /// Adds random items to the set until all candidates
/// are tried or the remaining weight is depleted. /// are tried or the remaining weight is depleted.
...@@ -698,16 +698,39 @@ where ...@@ -698,16 +698,39 @@ where
fn random_sel<X, F: Fn(&X) -> Weight>( fn random_sel<X, F: Fn(&X) -> Weight>(
rng: &mut rand_chacha::ChaChaRng, rng: &mut rand_chacha::ChaChaRng,
selectables: Vec<X>, selectables: Vec<X>,
mut preferred_indices: Vec<usize>,
weight_fn: F, weight_fn: F,
weight_limit: Weight, weight_limit: Weight,
) -> (Weight, Vec<usize>) { ) -> (Weight, Vec<usize>) {
if selectables.is_empty() { if selectables.is_empty() {
return (0 as Weight, Vec::new()) return (0 as Weight, Vec::new())
} }
let mut indices = (0..selectables.len()).into_iter().collect::<Vec<_>>(); // all indices that are not part of the preferred set
let mut indices = (0..selectables.len())
.into_iter()
.filter(|idx| !preferred_indices.contains(idx))
.collect::<Vec<_>>();
let mut picked_indices = Vec::with_capacity(selectables.len().saturating_sub(1)); let mut picked_indices = Vec::with_capacity(selectables.len().saturating_sub(1));
let mut weight_acc = 0 as Weight; let mut weight_acc = 0 as Weight;
while !preferred_indices.is_empty() {
// randomly pick an index from the preferred set
let pick = rng.gen_range(0..preferred_indices.len());
// remove the index from the available set of preferred indices
let preferred_idx = preferred_indices.swap_remove(pick);
// preferred indices originate from outside
if let Some(item) = selectables.get(preferred_idx) {
let updated = weight_acc + weight_fn(item);
if updated > weight_limit {
continue
}
weight_acc = updated;
picked_indices.push(preferred_idx);
}
}
while !indices.is_empty() { while !indices.is_empty() {
// randomly pick an index // randomly pick an index
let pick = rng.gen_range(0..indices.len()); let pick = rng.gen_range(0..indices.len());
...@@ -715,11 +738,12 @@ fn random_sel<X, F: Fn(&X) -> Weight>( ...@@ -715,11 +738,12 @@ fn random_sel<X, F: Fn(&X) -> Weight>(
let idx = indices.swap_remove(pick); let idx = indices.swap_remove(pick);
let item = &selectables[idx]; let item = &selectables[idx];
weight_acc += weight_fn(item); let updated = weight_acc + weight_fn(item);
if weight_acc > weight_limit { if updated > weight_limit {
break continue
} }
weight_acc = updated;
picked_indices.push(idx); picked_indices.push(idx);
} }
...@@ -759,6 +783,16 @@ fn apply_weight_limit<T: Config + inclusion::Config>( ...@@ -759,6 +783,16 @@ fn apply_weight_limit<T: Config + inclusion::Config>(
return total return total
} }
// Prefer code upgrades, they tend to be large and hence stand no chance to be picked
// late while maintaining the weight bounds
let preferred_indices = candidates
.iter()
.enumerate()
.filter_map(|(idx, candidate)| {
candidate.candidate.commitments.new_validation_code.as_ref().map(|_code| idx)
})
.collect::<Vec<usize>>();
// There is weight remaining to be consumed by a subset of candidates // There is weight remaining to be consumed by a subset of candidates
// which are going to be picked now. // which are going to be picked now.
if let Some(remaining_weight) = remaining_weight.checked_sub(total_bitfields_weight) { if let Some(remaining_weight) = remaining_weight.checked_sub(total_bitfields_weight) {
...@@ -766,6 +800,7 @@ fn apply_weight_limit<T: Config + inclusion::Config>( ...@@ -766,6 +800,7 @@ fn apply_weight_limit<T: Config + inclusion::Config>(
random_sel::<BackedCandidate<<T as frame_system::Config>::Hash>, _>( random_sel::<BackedCandidate<<T as frame_system::Config>::Hash>, _>(
rng, rng,
candidates.clone(), candidates.clone(),
preferred_indices,
|c| backed_candidate_weight::<T>(c), |c| backed_candidate_weight::<T>(c),
remaining_weight, remaining_weight,
); );
...@@ -788,6 +823,7 @@ fn apply_weight_limit<T: Config + inclusion::Config>( ...@@ -788,6 +823,7 @@ fn apply_weight_limit<T: Config + inclusion::Config>(
let (total, indices) = random_sel::<UncheckedSignedAvailabilityBitfield, _>( let (total, indices) = random_sel::<UncheckedSignedAvailabilityBitfield, _>(
rng, rng,
bitfields.clone(), bitfields.clone(),
vec![],
|_| <<T as Config>::WeightInfo as WeightInfo>::enter_bitfields(), |_| <<T as Config>::WeightInfo as WeightInfo>::enter_bitfields(),
remaining_weight, remaining_weight,
); );
...@@ -944,6 +980,10 @@ fn sanitize_backed_candidates<T: crate::inclusion::Config, F: Fn(CandidateHash) ...@@ -944,6 +980,10 @@ fn sanitize_backed_candidates<T: crate::inclusion::Config, F: Fn(CandidateHash)
backed_candidates backed_candidates
} }
/// Derive entropy from babe provided per block randomness.
///
/// In the odd case none is available, uses the `parent_hash` and
/// a const value, while emitting a warning.
fn compute_entropy<T: Config>(parent_hash: T::Hash) -> [u8; 32] { fn compute_entropy<T: Config>(parent_hash: T::Hash) -> [u8; 32] {
const CANDIDATE_SEED_SUBJECT: [u8; 32] = *b"candidate-seed-selection-subject"; const CANDIDATE_SEED_SUBJECT: [u8; 32] = *b"candidate-seed-selection-subject";
let vrf_random = CurrentBlockRandomness::<T>::random(&CANDIDATE_SEED_SUBJECT[..]).0; let vrf_random = CurrentBlockRandomness::<T>::random(&CANDIDATE_SEED_SUBJECT[..]).0;
...@@ -1026,6 +1066,7 @@ fn limit_disputes<T: Config>( ...@@ -1026,6 +1066,7 @@ fn limit_disputes<T: Config>(
let (acc_remote_disputes_weight, indices) = random_sel::<u32, _>( let (acc_remote_disputes_weight, indices) = random_sel::<u32, _>(
rng, rng,
d, d,
vec![],
|v| <<T as Config>::WeightInfo as WeightInfo>::enter_variable_disputes(*v), |v| <<T as Config>::WeightInfo as WeightInfo>::enter_variable_disputes(*v),
remaining_weight, remaining_weight,
); );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment