mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-08 15:57:21 +00:00
d5d916a915
* chore/provisioner: move metrics to a separate module * avoid the duplicate names * reduce all checks * fixup tests * Update node/core/provisioner/src/lib.rs Co-authored-by: Zeke Mostov <z.mostov@gmail.com> * chore: fmt * chore: spellcheck * doc * remove the enum anti-pattern * guide update - remove all the responsibilities * add another trivial check * Update node/core/provisioner/src/metrics.rs Co-authored-by: Andronik Ordian <write@reusable.software> * Update roadmap/implementers-guide/src/node/utility/provisioner.md Co-authored-by: Andronik Ordian <write@reusable.software> * Update node/core/provisioner/src/metrics.rs Co-authored-by: Andronik Ordian <write@reusable.software> Co-authored-by: Zeke Mostov <z.mostov@gmail.com> Co-authored-by: Andronik Ordian <write@reusable.software>
159 lines
4.9 KiB
Rust
159 lines
4.9 KiB
Rust
// Copyright 2020 Parity Technologies (UK) Ltd.
|
|
// This file is part of Polkadot.
|
|
|
|
// Polkadot is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
|
|
// Polkadot is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
use super::*;
|
|
use futures::{channel::mpsc, future};
|
|
|
|
fn default_bitvec(n_cores: usize) -> bitvec::vec::BitVec<bitvec::order::Lsb0, u8> {
|
|
bitvec::vec::BitVec::repeat(false, n_cores)
|
|
}
|
|
|
|
use crate::collect_backed_candidates;
|
|
use polkadot_node_subsystem::messages::AllMessages;
|
|
use polkadot_node_subsystem_test_helpers::TestSubsystemSender;
|
|
use polkadot_primitives::v1::{
|
|
BlockNumber, CandidateCommitments, CandidateDescriptor, CommittedCandidateReceipt, Hash,
|
|
PersistedValidationData,
|
|
};
|
|
|
|
fn test_harness<OverseerFactory, Overseer, TestFactory, Test>(
|
|
overseer_factory: OverseerFactory,
|
|
test_factory: TestFactory,
|
|
) where
|
|
OverseerFactory: FnOnce(mpsc::UnboundedReceiver<AllMessages>) -> Overseer,
|
|
Overseer: Future<Output = ()>,
|
|
TestFactory: FnOnce(TestSubsystemSender) -> Test,
|
|
Test: Future<Output = ()>,
|
|
{
|
|
let (tx, rx) = polkadot_node_subsystem_test_helpers::sender_receiver();
|
|
let overseer = overseer_factory(rx);
|
|
let test = test_factory(tx);
|
|
|
|
futures::pin_mut!(overseer, test);
|
|
|
|
let _ = futures::executor::block_on(future::join(overseer, test));
|
|
}
|
|
|
|
async fn mock_overseer(
|
|
mut receiver: mpsc::UnboundedReceiver<AllMessages>,
|
|
expected: Vec<BackedCandidate>,
|
|
) {
|
|
while let Some(from_job) = receiver.next().await {
|
|
match from_job {
|
|
AllMessages::CandidateBacking(CandidateBackingMessage::GetBackedCandidates(
|
|
_,
|
|
_,
|
|
sender,
|
|
)) => {
|
|
let _ = sender.send(expected.clone());
|
|
},
|
|
_ => panic!("Unexpected message: {:?}", from_job),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn can_succeed() {
|
|
test_harness(
|
|
|r| mock_overseer(r, Vec::new()),
|
|
|mut tx: TestSubsystemSender| async move {
|
|
collect_backed_candidates(Vec::new(), Default::default(), &mut tx)
|
|
.await
|
|
.unwrap();
|
|
},
|
|
)
|
|
}
|
|
|
|
// this tests that only the appropriate candidates get selected.
|
|
// To accomplish this, we supply a candidate list containing one candidate per possible core;
|
|
// the candidate selection algorithm must filter them to the appropriate set
|
|
#[test]
|
|
fn selects_correct_candidates() {
|
|
let empty_hash = PersistedValidationData::<Hash, BlockNumber>::default().hash();
|
|
|
|
let candidate_template = CandidateReceipt {
|
|
descriptor: CandidateDescriptor {
|
|
persisted_validation_data_hash: empty_hash,
|
|
..Default::default()
|
|
},
|
|
commitments_hash: CandidateCommitments::default().hash(),
|
|
};
|
|
let n_cores = 5;
|
|
let candidate_receipts: Vec<_> = std::iter::repeat(candidate_template)
|
|
.take(n_cores)
|
|
.enumerate()
|
|
.map(|(idx, mut candidate)| {
|
|
candidate.descriptor.para_id = idx.into();
|
|
candidate
|
|
})
|
|
.cycle()
|
|
.take(n_cores * 4)
|
|
.enumerate()
|
|
.map(|(idx, mut candidate_receipt)| {
|
|
if idx < n_cores {
|
|
// first go-around: use candidates which should work
|
|
candidate_receipt
|
|
} else if idx < n_cores * 2 {
|
|
// for the second repetition of the candidates, give them the wrong hash
|
|
candidate_receipt.descriptor.persisted_validation_data_hash = Default::default();
|
|
candidate_receipt
|
|
} else if idx < n_cores * 3 {
|
|
// third go-around: right hash, wrong para_id
|
|
candidate_receipt.descriptor.para_id = idx.into();
|
|
candidate_receipt
|
|
} else {
|
|
// fourth go-around: wrong relay parent, this is the only thing that is checked
|
|
candidate_receipt.descriptor.relay_parent = Hash::repeat_byte(0xFF);
|
|
candidate_receipt
|
|
}
|
|
})
|
|
.collect();
|
|
// candidates now contains 1/3 valid canidates, and 2/3 invalid
|
|
// but we don't check them in them here, so they should be passed alright
|
|
|
|
let expected_candidate_receipts =
|
|
candidate_receipts.iter().take(n_cores * 3).cloned().collect::<Vec<_>>();
|
|
|
|
let expected_backed = expected_candidate_receipts
|
|
.iter()
|
|
.map(|candidate_receipt| BackedCandidate {
|
|
candidate: CommittedCandidateReceipt {
|
|
descriptor: candidate_receipt.descriptor.clone(),
|
|
..Default::default()
|
|
},
|
|
validity_votes: Vec::new(),
|
|
validator_indices: default_bitvec(n_cores),
|
|
})
|
|
.collect();
|
|
|
|
test_harness(
|
|
|r| mock_overseer(r, expected_backed),
|
|
|mut tx: TestSubsystemSender| async move {
|
|
let result = collect_backed_candidates(candidate_receipts, Default::default(), &mut tx)
|
|
.await
|
|
.unwrap();
|
|
|
|
result.into_iter().for_each(|c| {
|
|
assert!(
|
|
expected_candidate_receipts.iter().any(|c2| c.candidate.corresponds_to(c2)),
|
|
"Failed to find candidate: {:?}",
|
|
c,
|
|
)
|
|
});
|
|
},
|
|
)
|
|
}
|