mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 05:51:02 +00:00
inclusion: split CandidatePendingAvailability according to the guide (#1413)
* inclusion: split PendingAvailability storage into descriptor and commitments * inclusion: fix tests * implementers-guide: update CandidatePendingAvailability type * inclusion: simplify process_candidates a bit * implementers-guide: more updates to the inclusion module * inclusion: fix copy-paste errors in tests * inclusion: revert some of the changes * inclusion: lazy commitments loading and a test * guide: revert enact_candidate changes * inclusion: test process_bitfield for no commitments * Grammar Co-authored-by: Robert Habermeier <rphmeier@gmail.com> Co-authored-by: Robert Habermeier <rphmeier@gmail.com>
This commit is contained in:
@@ -14,7 +14,7 @@ struct AvailabilityBitfield {
|
|||||||
|
|
||||||
struct CandidatePendingAvailability {
|
struct CandidatePendingAvailability {
|
||||||
core: CoreIndex, // availability core
|
core: CoreIndex, // availability core
|
||||||
receipt: CandidateReceipt,
|
descriptor: CandidateDescriptor,
|
||||||
availability_votes: Bitfield, // one bit per validator.
|
availability_votes: Bitfield, // one bit per validator.
|
||||||
relay_parent_number: BlockNumber, // number of the relay-parent.
|
relay_parent_number: BlockNumber, // number of the relay-parent.
|
||||||
backed_in_number: BlockNumber,
|
backed_in_number: BlockNumber,
|
||||||
@@ -65,7 +65,6 @@ All failed checks should lead to an unrecoverable error making the block invalid
|
|||||||
1. If the core assignment includes a specific collator, ensure the backed candidate is issued by that collator.
|
1. If the core assignment includes a specific collator, ensure the backed candidate is issued by that collator.
|
||||||
1. Ensure that any code upgrade scheduled by the candidate does not happen within `config.validation_upgrade_frequency` of `Paras::last_code_upgrade(para_id, true)`, if any, comparing against the value of `Paras::FutureCodeUpgrades` for the given para ID.
|
1. Ensure that any code upgrade scheduled by the candidate does not happen within `config.validation_upgrade_frequency` of `Paras::last_code_upgrade(para_id, true)`, if any, comparing against the value of `Paras::FutureCodeUpgrades` for the given para ID.
|
||||||
1. Check the collator's signature on the candidate data.
|
1. Check the collator's signature on the candidate data.
|
||||||
1. Transform each [`CommittedCandidateReceipt`](../types/candidate.md#committed-candidate-receipt) into the corresponding [`CandidateReceipt`](../types/candidate.md#candidate-receipt), setting the commitments aside.
|
|
||||||
1. check the backing of the candidate using the signatures and the bitfields, comparing against the validators assigned to the groups, fetched with the `group_validators` lookup.
|
1. check the backing of the candidate using the signatures and the bitfields, comparing against the validators assigned to the groups, fetched with the `group_validators` lookup.
|
||||||
1. check that the upward messages, when combined with the existing queue size, are not exceeding `config.max_upward_queue_count` and `config.watermark_upward_queue_size` parameters.
|
1. check that the upward messages, when combined with the existing queue size, are not exceeding `config.max_upward_queue_count` and `config.watermark_upward_queue_size` parameters.
|
||||||
1. create an entry in the `PendingAvailability` map for each backed candidate with a blank `availability_votes` bitfield.
|
1. create an entry in the `PendingAvailability` map for each backed candidate with a blank `availability_votes` bitfield.
|
||||||
@@ -81,7 +80,7 @@ All failed checks should lead to an unrecoverable error making the block invalid
|
|||||||
```rust
|
```rust
|
||||||
fn collect_pending(f: impl Fn(CoreIndex, BlockNumber) -> bool) -> Vec<u32> {
|
fn collect_pending(f: impl Fn(CoreIndex, BlockNumber) -> bool) -> Vec<u32> {
|
||||||
// sweep through all paras pending availability. if the predicate returns true, when given the core index and
|
// sweep through all paras pending availability. if the predicate returns true, when given the core index and
|
||||||
// the block number the candidate has been pending availability since, then clean up the corresponding storage for that candidate.
|
// the block number the candidate has been pending availability since, then clean up the corresponding storage for that candidate and the commitments.
|
||||||
// return a vector of cleaned-up core IDs.
|
// return a vector of cleaned-up core IDs.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -22,14 +22,15 @@
|
|||||||
|
|
||||||
use sp_std::prelude::*;
|
use sp_std::prelude::*;
|
||||||
use primitives::v1::{
|
use primitives::v1::{
|
||||||
ValidatorId, CommittedCandidateReceipt, ValidatorIndex, Id as ParaId,
|
ValidatorId, CandidateCommitments, CandidateDescriptor, ValidatorIndex, Id as ParaId,
|
||||||
AvailabilityBitfield as AvailabilityBitfield, SignedAvailabilityBitfields, SigningContext,
|
AvailabilityBitfield as AvailabilityBitfield, SignedAvailabilityBitfields, SigningContext,
|
||||||
BackedCandidate, CoreIndex, GroupIndex, CoreAssignment,
|
BackedCandidate, CoreIndex, GroupIndex, CoreAssignment, CommittedCandidateReceipt,
|
||||||
};
|
};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
decl_storage, decl_module, decl_error, ensure, dispatch::DispatchResult, IterableStorageMap,
|
decl_storage, decl_module, decl_error, ensure, dispatch::DispatchResult, IterableStorageMap,
|
||||||
weights::Weight,
|
weights::Weight,
|
||||||
traits::Get,
|
traits::Get,
|
||||||
|
debug,
|
||||||
};
|
};
|
||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
|
use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
|
||||||
@@ -58,8 +59,8 @@ pub struct AvailabilityBitfieldRecord<N> {
|
|||||||
pub struct CandidatePendingAvailability<H, N> {
|
pub struct CandidatePendingAvailability<H, N> {
|
||||||
/// The availability core this is assigned to.
|
/// The availability core this is assigned to.
|
||||||
core: CoreIndex,
|
core: CoreIndex,
|
||||||
/// The candidate receipt itself.
|
/// The candidate descriptor.
|
||||||
receipt: CommittedCandidateReceipt<H>,
|
descriptor: CandidateDescriptor<H>,
|
||||||
/// The received availability votes. One bit per validator.
|
/// The received availability votes. One bit per validator.
|
||||||
availability_votes: BitVec<BitOrderLsb0, u8>,
|
availability_votes: BitVec<BitOrderLsb0, u8>,
|
||||||
/// The block number of the relay-parent of the receipt.
|
/// The block number of the relay-parent of the receipt.
|
||||||
@@ -80,6 +81,10 @@ decl_storage! {
|
|||||||
PendingAvailability: map hasher(twox_64_concat) ParaId
|
PendingAvailability: map hasher(twox_64_concat) ParaId
|
||||||
=> Option<CandidatePendingAvailability<T::Hash, T::BlockNumber>>;
|
=> Option<CandidatePendingAvailability<T::Hash, T::BlockNumber>>;
|
||||||
|
|
||||||
|
/// The commitments of candidates pending availability, by ParaId.
|
||||||
|
PendingAvailabilityCommitments: map hasher(twox_64_concat) ParaId
|
||||||
|
=> Option<CandidateCommitments>;
|
||||||
|
|
||||||
/// The current validators, by their parachain session keys.
|
/// The current validators, by their parachain session keys.
|
||||||
Validators get(fn validators) config(validators): Vec<ValidatorId>;
|
Validators get(fn validators) config(validators): Vec<ValidatorId>;
|
||||||
|
|
||||||
@@ -146,6 +151,7 @@ impl<T: Trait> Module<T> {
|
|||||||
) {
|
) {
|
||||||
// unlike most drain methods, drained elements are not cleared on `Drop` of the iterator
|
// unlike most drain methods, drained elements are not cleared on `Drop` of the iterator
|
||||||
// and require consumption.
|
// and require consumption.
|
||||||
|
for _ in <PendingAvailabilityCommitments>::drain() { }
|
||||||
for _ in <PendingAvailability<T>>::drain() { }
|
for _ in <PendingAvailability<T>>::drain() { }
|
||||||
for _ in <AvailabilityBitfields<T>>::drain() { }
|
for _ in <AvailabilityBitfields<T>>::drain() { }
|
||||||
|
|
||||||
@@ -227,14 +233,14 @@ impl<T: Trait> Module<T> {
|
|||||||
for (bit_idx, _)
|
for (bit_idx, _)
|
||||||
in signed_bitfield.payload().0.iter().enumerate().filter(|(_, is_av)| **is_av)
|
in signed_bitfield.payload().0.iter().enumerate().filter(|(_, is_av)| **is_av)
|
||||||
{
|
{
|
||||||
let record = assigned_paras_record[bit_idx]
|
let (_, pending_availability) = assigned_paras_record[bit_idx]
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.expect("validator bitfields checked not to contain bits corresponding to unoccupied cores; qed");
|
.expect("validator bitfields checked not to contain bits corresponding to unoccupied cores; qed");
|
||||||
|
|
||||||
// defensive check - this is constructed by loading the availability bitfield record,
|
// 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.
|
// which is always `Some` if the core is occupied - that's why we're here.
|
||||||
let val_idx = signed_bitfield.validator_index() as usize;
|
let val_idx = signed_bitfield.validator_index() as usize;
|
||||||
if let Some(mut bit) = record.1.as_mut()
|
if let Some(mut bit) = pending_availability.as_mut()
|
||||||
.and_then(|r| r.availability_votes.get_mut(val_idx))
|
.and_then(|r| r.availability_votes.get_mut(val_idx))
|
||||||
{
|
{
|
||||||
*bit = true;
|
*bit = true;
|
||||||
@@ -261,9 +267,25 @@ impl<T: Trait> Module<T> {
|
|||||||
{
|
{
|
||||||
if pending_availability.availability_votes.count_ones() >= threshold {
|
if pending_availability.availability_votes.count_ones() >= threshold {
|
||||||
<PendingAvailability<T>>::remove(¶_id);
|
<PendingAvailability<T>>::remove(¶_id);
|
||||||
|
let commitments = match <PendingAvailabilityCommitments>::take(¶_id) {
|
||||||
|
Some(commitments) => commitments,
|
||||||
|
None => {
|
||||||
|
debug::warn!(r#"
|
||||||
|
Inclusion::process_bitfields:
|
||||||
|
PendingAvailability and PendingAvailabilityCommitments
|
||||||
|
are out of sync, did someone mess with the storage?
|
||||||
|
"#);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let receipt = CommittedCandidateReceipt {
|
||||||
|
descriptor: pending_availability.descriptor,
|
||||||
|
commitments,
|
||||||
|
};
|
||||||
Self::enact_candidate(
|
Self::enact_candidate(
|
||||||
pending_availability.relay_parent_number,
|
pending_availability.relay_parent_number,
|
||||||
pending_availability.receipt,
|
receipt,
|
||||||
);
|
);
|
||||||
|
|
||||||
freed_cores.push(pending_availability.core);
|
freed_cores.push(pending_availability.core);
|
||||||
@@ -358,7 +380,7 @@ impl<T: Trait> Module<T> {
|
|||||||
for (i, assignment) in scheduled[skip..].iter().enumerate() {
|
for (i, assignment) in scheduled[skip..].iter().enumerate() {
|
||||||
check_assignment_in_order(assignment)?;
|
check_assignment_in_order(assignment)?;
|
||||||
|
|
||||||
if candidate.descriptor().para_id == assignment.para_id {
|
if para_id == assignment.para_id {
|
||||||
if let Some(required_collator) = assignment.required_collator() {
|
if let Some(required_collator) = assignment.required_collator() {
|
||||||
ensure!(
|
ensure!(
|
||||||
required_collator == &candidate.descriptor().collator,
|
required_collator == &candidate.descriptor().collator,
|
||||||
@@ -367,7 +389,8 @@ impl<T: Trait> Module<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ensure!(
|
ensure!(
|
||||||
<PendingAvailability<T>>::get(&assignment.para_id).is_none(),
|
<PendingAvailability<T>>::get(¶_id).is_none() &&
|
||||||
|
<PendingAvailabilityCommitments>::get(¶_id).is_none(),
|
||||||
Error::<T>::CandidateScheduledBeforeParaFree,
|
Error::<T>::CandidateScheduledBeforeParaFree,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -427,13 +450,15 @@ impl<T: Trait> Module<T> {
|
|||||||
// initialize all availability votes to 0.
|
// initialize all availability votes to 0.
|
||||||
let availability_votes: BitVec<BitOrderLsb0, u8>
|
let availability_votes: BitVec<BitOrderLsb0, u8>
|
||||||
= bitvec::bitvec![BitOrderLsb0, u8; 0; validators.len()];
|
= bitvec::bitvec![BitOrderLsb0, u8; 0; validators.len()];
|
||||||
|
let (descriptor, commitments) = (candidate.candidate.descriptor, candidate.candidate.commitments);
|
||||||
<PendingAvailability<T>>::insert(¶_id, CandidatePendingAvailability {
|
<PendingAvailability<T>>::insert(¶_id, CandidatePendingAvailability {
|
||||||
core,
|
core,
|
||||||
receipt: candidate.candidate,
|
descriptor,
|
||||||
availability_votes,
|
availability_votes,
|
||||||
relay_parent_number,
|
relay_parent_number,
|
||||||
backed_in_number: now,
|
backed_in_number: now,
|
||||||
});
|
});
|
||||||
|
<PendingAvailabilityCommitments>::insert(¶_id, commitments);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(core_indices)
|
Ok(core_indices)
|
||||||
@@ -482,6 +507,7 @@ impl<T: Trait> Module<T> {
|
|||||||
|
|
||||||
for para_id in cleaned_up_ids {
|
for para_id in cleaned_up_ids {
|
||||||
<PendingAvailability<T>>::remove(¶_id);
|
<PendingAvailability<T>>::remove(¶_id);
|
||||||
|
<PendingAvailabilityCommitments>::remove(¶_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleaned_up_cores
|
cleaned_up_cores
|
||||||
@@ -713,31 +739,38 @@ mod tests {
|
|||||||
|
|
||||||
let paras = vec![(chain_a, true), (chain_b, true), (thread_a, false)];
|
let paras = vec![(chain_a, true), (chain_b, true), (thread_a, false)];
|
||||||
new_test_ext(genesis_config(paras)).execute_with(|| {
|
new_test_ext(genesis_config(paras)).execute_with(|| {
|
||||||
|
let default_candidate = TestCandidateBuilder::default().build();
|
||||||
<PendingAvailability<Test>>::insert(chain_a, CandidatePendingAvailability {
|
<PendingAvailability<Test>>::insert(chain_a, CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(0),
|
core: CoreIndex::from(0),
|
||||||
receipt: Default::default(),
|
descriptor: default_candidate.descriptor.clone(),
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: 0,
|
relay_parent_number: 0,
|
||||||
backed_in_number: 0,
|
backed_in_number: 0,
|
||||||
});
|
});
|
||||||
|
PendingAvailabilityCommitments::insert(chain_a, default_candidate.commitments.clone());
|
||||||
|
|
||||||
<PendingAvailability<Test>>::insert(chain_b, CandidatePendingAvailability {
|
<PendingAvailability<Test>>::insert(&chain_b, CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(1),
|
core: CoreIndex::from(1),
|
||||||
receipt: Default::default(),
|
descriptor: default_candidate.descriptor,
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: 0,
|
relay_parent_number: 0,
|
||||||
backed_in_number: 0,
|
backed_in_number: 0,
|
||||||
});
|
});
|
||||||
|
PendingAvailabilityCommitments::insert(chain_b, default_candidate.commitments);
|
||||||
|
|
||||||
run_to_block(5, |_| None);
|
run_to_block(5, |_| None);
|
||||||
|
|
||||||
assert!(<PendingAvailability<Test>>::get(&chain_a).is_some());
|
assert!(<PendingAvailability<Test>>::get(&chain_a).is_some());
|
||||||
assert!(<PendingAvailability<Test>>::get(&chain_b).is_some());
|
assert!(<PendingAvailability<Test>>::get(&chain_b).is_some());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::get(&chain_a).is_some());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::get(&chain_b).is_some());
|
||||||
|
|
||||||
Inclusion::collect_pending(|core, _since| core == CoreIndex::from(0));
|
Inclusion::collect_pending(|core, _since| core == CoreIndex::from(0));
|
||||||
|
|
||||||
assert!(<PendingAvailability<Test>>::get(&chain_a).is_none());
|
assert!(<PendingAvailability<Test>>::get(&chain_a).is_none());
|
||||||
assert!(<PendingAvailability<Test>>::get(&chain_b).is_some());
|
assert!(<PendingAvailability<Test>>::get(&chain_b).is_some());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::get(&chain_a).is_none());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::get(&chain_b).is_some());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,13 +901,15 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(core_lookup(CoreIndex::from(0)), Some(chain_a));
|
assert_eq!(core_lookup(CoreIndex::from(0)), Some(chain_a));
|
||||||
|
|
||||||
|
let default_candidate = TestCandidateBuilder::default().build();
|
||||||
<PendingAvailability<Test>>::insert(chain_a, CandidatePendingAvailability {
|
<PendingAvailability<Test>>::insert(chain_a, CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(0),
|
core: CoreIndex::from(0),
|
||||||
receipt: Default::default(),
|
descriptor: default_candidate.descriptor,
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: 0,
|
relay_parent_number: 0,
|
||||||
backed_in_number: 0,
|
backed_in_number: 0,
|
||||||
});
|
});
|
||||||
|
PendingAvailabilityCommitments::insert(chain_a, default_candidate.commitments);
|
||||||
|
|
||||||
*bare_bitfield.0.get_mut(0).unwrap() = true;
|
*bare_bitfield.0.get_mut(0).unwrap() = true;
|
||||||
let signed = sign_bitfield(
|
let signed = sign_bitfield(
|
||||||
@@ -888,6 +923,42 @@ mod tests {
|
|||||||
vec![signed],
|
vec![signed],
|
||||||
&core_lookup,
|
&core_lookup,
|
||||||
).is_ok());
|
).is_ok());
|
||||||
|
|
||||||
|
<PendingAvailability<Test>>::remove(chain_a);
|
||||||
|
PendingAvailabilityCommitments::remove(chain_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bitfield signed with pending bit signed, but no commitments.
|
||||||
|
{
|
||||||
|
let mut bare_bitfield = default_bitfield();
|
||||||
|
|
||||||
|
assert_eq!(core_lookup(CoreIndex::from(0)), Some(chain_a));
|
||||||
|
|
||||||
|
let default_candidate = TestCandidateBuilder::default().build();
|
||||||
|
<PendingAvailability<Test>>::insert(chain_a, CandidatePendingAvailability {
|
||||||
|
core: CoreIndex::from(0),
|
||||||
|
descriptor: default_candidate.descriptor,
|
||||||
|
availability_votes: default_availability_votes(),
|
||||||
|
relay_parent_number: 0,
|
||||||
|
backed_in_number: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
*bare_bitfield.0.get_mut(0).unwrap() = true;
|
||||||
|
let signed = sign_bitfield(
|
||||||
|
&validators[0],
|
||||||
|
0,
|
||||||
|
bare_bitfield,
|
||||||
|
&signing_context,
|
||||||
|
);
|
||||||
|
|
||||||
|
// no core is freed
|
||||||
|
assert_eq!(
|
||||||
|
Inclusion::process_bitfields(
|
||||||
|
vec![signed],
|
||||||
|
&core_lookup,
|
||||||
|
),
|
||||||
|
Ok(vec![]),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -924,29 +995,35 @@ mod tests {
|
|||||||
_ => panic!("Core out of bounds for 2 parachains and 1 parathread core."),
|
_ => panic!("Core out of bounds for 2 parachains and 1 parathread core."),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let candidate_a = TestCandidateBuilder {
|
||||||
|
para_id: chain_a,
|
||||||
|
head_data: vec![1, 2, 3, 4].into(),
|
||||||
|
..Default::default()
|
||||||
|
}.build();
|
||||||
|
|
||||||
<PendingAvailability<Test>>::insert(chain_a, CandidatePendingAvailability {
|
<PendingAvailability<Test>>::insert(chain_a, CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(0),
|
core: CoreIndex::from(0),
|
||||||
receipt: TestCandidateBuilder {
|
descriptor: candidate_a.descriptor,
|
||||||
para_id: chain_a,
|
|
||||||
head_data: vec![1, 2, 3, 4].into(),
|
|
||||||
..Default::default()
|
|
||||||
}.build(),
|
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: 0,
|
relay_parent_number: 0,
|
||||||
backed_in_number: 0,
|
backed_in_number: 0,
|
||||||
});
|
});
|
||||||
|
PendingAvailabilityCommitments::insert(chain_a, candidate_a.commitments);
|
||||||
|
|
||||||
|
let candidate_b = TestCandidateBuilder {
|
||||||
|
para_id: chain_b,
|
||||||
|
head_data: vec![5, 6, 7, 8].into(),
|
||||||
|
..Default::default()
|
||||||
|
}.build();
|
||||||
|
|
||||||
<PendingAvailability<Test>>::insert(chain_b, CandidatePendingAvailability {
|
<PendingAvailability<Test>>::insert(chain_b, CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(1),
|
core: CoreIndex::from(1),
|
||||||
receipt: TestCandidateBuilder {
|
descriptor: candidate_b.descriptor,
|
||||||
para_id: chain_b,
|
|
||||||
head_data: vec![5, 6, 7, 8].into(),
|
|
||||||
..Default::default()
|
|
||||||
}.build(),
|
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: 0,
|
relay_parent_number: 0,
|
||||||
backed_in_number: 0,
|
backed_in_number: 0,
|
||||||
});
|
});
|
||||||
|
PendingAvailabilityCommitments::insert(chain_b, candidate_b.commitments);
|
||||||
|
|
||||||
// this bitfield signals that a and b are available.
|
// this bitfield signals that a and b are available.
|
||||||
let a_and_b_available = {
|
let a_and_b_available = {
|
||||||
@@ -996,6 +1073,8 @@ mod tests {
|
|||||||
// chain A had 4 signing off, which is >= threshold.
|
// chain A had 4 signing off, which is >= threshold.
|
||||||
// chain B has 3 signing off, which is < threshold.
|
// chain B has 3 signing off, which is < threshold.
|
||||||
assert!(<PendingAvailability<Test>>::get(&chain_a).is_none());
|
assert!(<PendingAvailability<Test>>::get(&chain_a).is_none());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::get(&chain_a).is_none());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::get(&chain_b).is_some());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
<PendingAvailability<Test>>::get(&chain_b).unwrap().availability_votes,
|
<PendingAvailability<Test>>::get(&chain_b).unwrap().availability_votes,
|
||||||
{
|
{
|
||||||
@@ -1053,7 +1132,7 @@ mod tests {
|
|||||||
|
|
||||||
let chain_a_assignment = CoreAssignment {
|
let chain_a_assignment = CoreAssignment {
|
||||||
core: CoreIndex::from(0),
|
core: CoreIndex::from(0),
|
||||||
para_id: chain_b,
|
para_id: chain_a,
|
||||||
kind: AssignmentKind::Parachain,
|
kind: AssignmentKind::Parachain,
|
||||||
group_idx: GroupIndex::from(0),
|
group_idx: GroupIndex::from(0),
|
||||||
};
|
};
|
||||||
@@ -1067,7 +1146,7 @@ mod tests {
|
|||||||
|
|
||||||
let thread_a_assignment = CoreAssignment {
|
let thread_a_assignment = CoreAssignment {
|
||||||
core: CoreIndex::from(2),
|
core: CoreIndex::from(2),
|
||||||
para_id: chain_b,
|
para_id: thread_a,
|
||||||
kind: AssignmentKind::Parathread(thread_collator.clone(), 0),
|
kind: AssignmentKind::Parathread(thread_collator.clone(), 0),
|
||||||
group_idx: GroupIndex::from(2),
|
group_idx: GroupIndex::from(2),
|
||||||
};
|
};
|
||||||
@@ -1296,13 +1375,15 @@ mod tests {
|
|||||||
BackingKind::Threshold,
|
BackingKind::Threshold,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let candidate = TestCandidateBuilder::default().build();
|
||||||
<PendingAvailability<Test>>::insert(&chain_a, CandidatePendingAvailability {
|
<PendingAvailability<Test>>::insert(&chain_a, CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(0),
|
core: CoreIndex::from(0),
|
||||||
receipt: Default::default(),
|
descriptor: candidate.descriptor,
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: 3,
|
relay_parent_number: 3,
|
||||||
backed_in_number: 4,
|
backed_in_number: 4,
|
||||||
});
|
});
|
||||||
|
<PendingAvailabilityCommitments>::insert(&chain_a, candidate.commitments);
|
||||||
|
|
||||||
assert!(Inclusion::process_candidates(
|
assert!(Inclusion::process_candidates(
|
||||||
vec![backed],
|
vec![backed],
|
||||||
@@ -1311,6 +1392,41 @@ mod tests {
|
|||||||
).is_err());
|
).is_err());
|
||||||
|
|
||||||
<PendingAvailability<Test>>::remove(&chain_a);
|
<PendingAvailability<Test>>::remove(&chain_a);
|
||||||
|
<PendingAvailabilityCommitments>::remove(&chain_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// messed up commitments storage - do not panic - reject.
|
||||||
|
{
|
||||||
|
let mut candidate = TestCandidateBuilder {
|
||||||
|
para_id: chain_a,
|
||||||
|
relay_parent: System::parent_hash(),
|
||||||
|
pov_hash: Hash::from([1; 32]),
|
||||||
|
..Default::default()
|
||||||
|
}.build();
|
||||||
|
|
||||||
|
collator_sign_candidate(
|
||||||
|
Sr25519Keyring::One,
|
||||||
|
&mut candidate,
|
||||||
|
);
|
||||||
|
|
||||||
|
// this is not supposed to happen
|
||||||
|
<PendingAvailabilityCommitments>::insert(&chain_a, candidate.commitments.clone());
|
||||||
|
|
||||||
|
let backed = back_candidate(
|
||||||
|
candidate,
|
||||||
|
&validators,
|
||||||
|
group_validators(GroupIndex::from(0)).unwrap().as_ref(),
|
||||||
|
&signing_context,
|
||||||
|
BackingKind::Threshold,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(Inclusion::process_candidates(
|
||||||
|
vec![backed],
|
||||||
|
vec![chain_a_assignment.clone()],
|
||||||
|
&group_validators,
|
||||||
|
).is_err());
|
||||||
|
|
||||||
|
<PendingAvailabilityCommitments>::remove(&chain_a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// interfering code upgrade - reject
|
// interfering code upgrade - reject
|
||||||
@@ -1483,34 +1599,46 @@ mod tests {
|
|||||||
<PendingAvailability<Test>>::get(&chain_a),
|
<PendingAvailability<Test>>::get(&chain_a),
|
||||||
Some(CandidatePendingAvailability {
|
Some(CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(0),
|
core: CoreIndex::from(0),
|
||||||
receipt: candidate_a,
|
descriptor: candidate_a.descriptor,
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: System::block_number() - 1,
|
relay_parent_number: System::block_number() - 1,
|
||||||
backed_in_number: System::block_number(),
|
backed_in_number: System::block_number(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
<PendingAvailabilityCommitments>::get(&chain_a),
|
||||||
|
Some(candidate_a.commitments),
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
<PendingAvailability<Test>>::get(&chain_b),
|
<PendingAvailability<Test>>::get(&chain_b),
|
||||||
Some(CandidatePendingAvailability {
|
Some(CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(1),
|
core: CoreIndex::from(1),
|
||||||
receipt: candidate_b,
|
descriptor: candidate_b.descriptor,
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: System::block_number() - 1,
|
relay_parent_number: System::block_number() - 1,
|
||||||
backed_in_number: System::block_number(),
|
backed_in_number: System::block_number(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
<PendingAvailabilityCommitments>::get(&chain_b),
|
||||||
|
Some(candidate_b.commitments),
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
<PendingAvailability<Test>>::get(&thread_a),
|
<PendingAvailability<Test>>::get(&thread_a),
|
||||||
Some(CandidatePendingAvailability {
|
Some(CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(2),
|
core: CoreIndex::from(2),
|
||||||
receipt: candidate_c,
|
descriptor: candidate_c.descriptor,
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: System::block_number() - 1,
|
relay_parent_number: System::block_number() - 1,
|
||||||
backed_in_number: System::block_number(),
|
backed_in_number: System::block_number(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
<PendingAvailabilityCommitments>::get(&thread_a),
|
||||||
|
Some(candidate_c.commitments),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1568,21 +1696,24 @@ mod tests {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let candidate = TestCandidateBuilder::default().build();
|
||||||
<PendingAvailability<Test>>::insert(&chain_a, CandidatePendingAvailability {
|
<PendingAvailability<Test>>::insert(&chain_a, CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(0),
|
core: CoreIndex::from(0),
|
||||||
receipt: Default::default(),
|
descriptor: candidate.descriptor.clone(),
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: 5,
|
relay_parent_number: 5,
|
||||||
backed_in_number: 6,
|
backed_in_number: 6,
|
||||||
});
|
});
|
||||||
|
<PendingAvailabilityCommitments>::insert(&chain_a, candidate.commitments.clone());
|
||||||
|
|
||||||
<PendingAvailability<Test>>::insert(&chain_b, CandidatePendingAvailability {
|
<PendingAvailability<Test>>::insert(&chain_b, CandidatePendingAvailability {
|
||||||
core: CoreIndex::from(1),
|
core: CoreIndex::from(1),
|
||||||
receipt: Default::default(),
|
descriptor: candidate.descriptor,
|
||||||
availability_votes: default_availability_votes(),
|
availability_votes: default_availability_votes(),
|
||||||
relay_parent_number: 6,
|
relay_parent_number: 6,
|
||||||
backed_in_number: 7,
|
backed_in_number: 7,
|
||||||
});
|
});
|
||||||
|
<PendingAvailabilityCommitments>::insert(&chain_b, candidate.commitments);
|
||||||
|
|
||||||
run_to_block(11, |_| None);
|
run_to_block(11, |_| None);
|
||||||
|
|
||||||
@@ -1595,6 +1726,8 @@ mod tests {
|
|||||||
|
|
||||||
assert!(<PendingAvailability<Test>>::get(&chain_a).is_some());
|
assert!(<PendingAvailability<Test>>::get(&chain_a).is_some());
|
||||||
assert!(<PendingAvailability<Test>>::get(&chain_b).is_some());
|
assert!(<PendingAvailability<Test>>::get(&chain_b).is_some());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::get(&chain_a).is_some());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::get(&chain_b).is_some());
|
||||||
|
|
||||||
run_to_block(12, |n| match n {
|
run_to_block(12, |n| match n {
|
||||||
12 => Some(SessionChangeNotification {
|
12 => Some(SessionChangeNotification {
|
||||||
@@ -1617,10 +1750,12 @@ mod tests {
|
|||||||
|
|
||||||
assert!(<PendingAvailability<Test>>::get(&chain_a).is_none());
|
assert!(<PendingAvailability<Test>>::get(&chain_a).is_none());
|
||||||
assert!(<PendingAvailability<Test>>::get(&chain_b).is_none());
|
assert!(<PendingAvailability<Test>>::get(&chain_b).is_none());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::get(&chain_a).is_none());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::get(&chain_b).is_none());
|
||||||
|
|
||||||
assert!(<AvailabilityBitfields<Test>>::iter().collect::<Vec<_>>().is_empty());
|
assert!(<AvailabilityBitfields<Test>>::iter().collect::<Vec<_>>().is_empty());
|
||||||
assert!(<PendingAvailability<Test>>::iter().collect::<Vec<_>>().is_empty());
|
assert!(<PendingAvailability<Test>>::iter().collect::<Vec<_>>().is_empty());
|
||||||
|
assert!(<PendingAvailabilityCommitments>::iter().collect::<Vec<_>>().is_empty());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user