mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 17:01:09 +00:00
Allow at most one candidate with a code upgrade in a block (#2456)
* guide: max one candidate with upgrade per block * max one candidate with upgrade per block * ignore on runtime level too
This commit is contained in:
committed by
GitHub
parent
1e2161258b
commit
9e525e296d
@@ -448,7 +448,7 @@ async fn select_candidates(
|
||||
selected_candidates.clone(),
|
||||
tx,
|
||||
)).into()).await.map_err(|err| Error::GetBackedCandidatesSend(err))?;
|
||||
let candidates = rx.await.map_err(|err| Error::CanceledBackedCandidates(err))?;
|
||||
let mut candidates = rx.await.map_err(|err| Error::CanceledBackedCandidates(err))?;
|
||||
|
||||
// `selected_candidates` is generated in ascending order by core index, and `GetBackedCandidates`
|
||||
// _should_ preserve that property, but let's just make sure.
|
||||
@@ -466,6 +466,20 @@ async fn select_candidates(
|
||||
Err(Error::BackedCandidateOrderingProblem)?;
|
||||
}
|
||||
|
||||
// keep only one candidate with validation code.
|
||||
let mut with_validation_code = false;
|
||||
candidates.retain(|c| {
|
||||
if c.candidate.commitments.new_validation_code.is_some() {
|
||||
if with_validation_code {
|
||||
return false
|
||||
}
|
||||
|
||||
with_validation_code = true;
|
||||
}
|
||||
|
||||
true
|
||||
});
|
||||
|
||||
Ok(candidates)
|
||||
}
|
||||
|
||||
|
||||
@@ -426,4 +426,63 @@ mod select_candidates {
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selects_max_one_code_upgrade() {
|
||||
let mock_cores = mock_availability_cores();
|
||||
let n_cores = mock_cores.len();
|
||||
|
||||
let empty_hash = PersistedValidationData::<BlockNumber>::default().hash();
|
||||
|
||||
// why those particular indices? see the comments on mock_availability_cores()
|
||||
// the first candidate with code is included out of [1, 4, 7, 8, 10].
|
||||
let cores = [1, 7, 10];
|
||||
let cores_with_code = [1, 4, 8];
|
||||
|
||||
let committed_receipts: Vec<_> = (0..mock_cores.len())
|
||||
.map(|i| CommittedCandidateReceipt {
|
||||
descriptor: CandidateDescriptor {
|
||||
para_id: i.into(),
|
||||
persisted_validation_data_hash: empty_hash,
|
||||
..Default::default()
|
||||
},
|
||||
commitments: CandidateCommitments {
|
||||
new_validation_code: if cores_with_code.contains(&i) { Some(vec![].into()) } else { None },
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let candidates: Vec<_> = committed_receipts.iter().map(|r| r.to_plain()).collect();
|
||||
|
||||
let expected_candidates: Vec<_> = cores
|
||||
.iter()
|
||||
.map(|&idx| candidates[idx].clone())
|
||||
.collect();
|
||||
|
||||
let expected_backed: Vec<_> = cores
|
||||
.iter()
|
||||
.map(|&idx| BackedCandidate {
|
||||
candidate: committed_receipts[idx].clone(),
|
||||
validity_votes: Vec::new(),
|
||||
validator_indices: default_bitvec(n_cores),
|
||||
})
|
||||
.collect();
|
||||
|
||||
test_harness(|r| mock_overseer(r, expected_backed), |mut tx: mpsc::Sender<FromJobCommand>| async move {
|
||||
let result =
|
||||
select_candidates(&mock_cores, &[], &candidates, Default::default(), &mut tx)
|
||||
.await.unwrap();
|
||||
|
||||
result.into_iter()
|
||||
.for_each(|c|
|
||||
assert!(
|
||||
expected_candidates.iter().any(|c2| c.candidate.corresponds_to(c2)),
|
||||
"Failed to find candidate: {:?}",
|
||||
c,
|
||||
)
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user