mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 22:11:06 +00:00
Runtime: allow backing multiple candidates of same parachain on different cores (#3231)
Fixes https://github.com/paritytech/polkadot-sdk/issues/3144 Builds on top of https://github.com/paritytech/polkadot-sdk/pull/3229 ### Summary Some preparations for Runtime to support elastic scaling, guarded by config node features bit `FeatureIndex::ElasticScalingMVP`. This PR introduces a per-candidate `CoreIndex` but does it in a hacky way to avoid changing `CandidateCommitments`, `CandidateReceipts` primitives and networking protocols. #### Including `CoreIndex` in `BackedCandidate` If the `ElasticScalingMVP` feature bit is enabled then `BackedCandidate::validator_indices` is extended by 8 bits. The value stored in these bits represents the assumed core index for the candidate. It is temporary solution which works by creating a mapping from `BackedCandidate` to `CoreIndex` by assuming the `CoreIndex` can be discovered by checking in which validator group the validator that signed the statement is. TODO: - [x] fix tests - [x] add new tests - [x] Bump runtime API for Kusama, so we have that node features thing! -> https://github.com/polkadot-fellows/runtimes/pull/194 --------- Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> Signed-off-by: alindima <alin@parity.io> Co-authored-by: alindima <alin@parity.io>
This commit is contained in:
@@ -33,9 +33,10 @@ use polkadot_node_subsystem::{
|
||||
};
|
||||
use polkadot_node_subsystem_test_helpers as test_helpers;
|
||||
use polkadot_primitives::{
|
||||
CandidateDescriptor, GroupRotationInfo, HeadData, PersistedValidationData, PvfExecKind,
|
||||
ScheduledCore, SessionIndex, LEGACY_MIN_BACKING_VOTES,
|
||||
vstaging::node_features, CandidateDescriptor, GroupRotationInfo, HeadData,
|
||||
PersistedValidationData, PvfExecKind, ScheduledCore, SessionIndex, LEGACY_MIN_BACKING_VOTES,
|
||||
};
|
||||
use rstest::rstest;
|
||||
use sp_application_crypto::AppCrypto;
|
||||
use sp_keyring::Sr25519Keyring;
|
||||
use sp_keystore::Keystore;
|
||||
@@ -79,6 +80,7 @@ pub(crate) struct TestState {
|
||||
relay_parent: Hash,
|
||||
minimum_backing_votes: u32,
|
||||
disabled_validators: Vec<ValidatorIndex>,
|
||||
node_features: NodeFeatures,
|
||||
}
|
||||
|
||||
impl TestState {
|
||||
@@ -157,6 +159,7 @@ impl Default for TestState {
|
||||
relay_parent,
|
||||
minimum_backing_votes: LEGACY_MIN_BACKING_VOTES,
|
||||
disabled_validators: Vec::new(),
|
||||
node_features: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,7 +301,7 @@ async fn test_startup(virtual_overseer: &mut VirtualOverseer, test_state: &TestS
|
||||
AllMessages::RuntimeApi(
|
||||
RuntimeApiMessage::Request(_parent, RuntimeApiRequest::NodeFeatures(_session_index, tx))
|
||||
) => {
|
||||
tx.send(Ok(Default::default())).unwrap();
|
||||
tx.send(Ok(test_state.node_features.clone())).unwrap();
|
||||
}
|
||||
);
|
||||
|
||||
@@ -494,9 +497,20 @@ fn backing_second_works() {
|
||||
}
|
||||
|
||||
// Test that the candidate reaches quorum successfully.
|
||||
#[test]
|
||||
fn backing_works() {
|
||||
let test_state = TestState::default();
|
||||
#[rstest]
|
||||
#[case(true)]
|
||||
#[case(false)]
|
||||
fn backing_works(#[case] elastic_scaling_mvp: bool) {
|
||||
let mut test_state = TestState::default();
|
||||
if elastic_scaling_mvp {
|
||||
test_state
|
||||
.node_features
|
||||
.resize((node_features::FeatureIndex::ElasticScalingMVP as u8 + 1) as usize, false);
|
||||
test_state
|
||||
.node_features
|
||||
.set(node_features::FeatureIndex::ElasticScalingMVP as u8 as usize, true);
|
||||
}
|
||||
|
||||
test_harness(test_state.keystore.clone(), |mut virtual_overseer| async move {
|
||||
test_startup(&mut virtual_overseer, &test_state).await;
|
||||
|
||||
@@ -647,6 +661,31 @@ fn backing_works() {
|
||||
|
||||
virtual_overseer.send(FromOrchestra::Communication { msg: statement }).await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let msg = CandidateBackingMessage::GetBackedCandidates(
|
||||
vec![(candidate_a_hash, test_state.relay_parent)],
|
||||
tx,
|
||||
);
|
||||
|
||||
virtual_overseer.send(FromOrchestra::Communication { msg }).await;
|
||||
|
||||
let candidates = rx.await.unwrap();
|
||||
assert_eq!(1, candidates.len());
|
||||
assert_eq!(candidates[0].validity_votes().len(), 3);
|
||||
|
||||
let (validator_indices, maybe_core_index) =
|
||||
candidates[0].validator_indices_and_core_index(elastic_scaling_mvp);
|
||||
if elastic_scaling_mvp {
|
||||
assert_eq!(maybe_core_index.unwrap(), CoreIndex(0));
|
||||
} else {
|
||||
assert!(maybe_core_index.is_none());
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
validator_indices,
|
||||
bitvec::bitvec![u8, bitvec::order::Lsb0; 1, 1, 0, 1].as_bitslice()
|
||||
);
|
||||
|
||||
virtual_overseer
|
||||
.send(FromOrchestra::Signal(OverseerSignal::ActiveLeaves(
|
||||
ActiveLeavesUpdate::stop_work(test_state.relay_parent),
|
||||
@@ -919,20 +958,20 @@ fn backing_works_while_validation_ongoing() {
|
||||
|
||||
let candidates = rx.await.unwrap();
|
||||
assert_eq!(1, candidates.len());
|
||||
assert_eq!(candidates[0].validity_votes.len(), 3);
|
||||
assert_eq!(candidates[0].validity_votes().len(), 3);
|
||||
|
||||
assert!(candidates[0]
|
||||
.validity_votes
|
||||
.validity_votes()
|
||||
.contains(&ValidityAttestation::Implicit(signed_a.signature().clone())));
|
||||
assert!(candidates[0]
|
||||
.validity_votes
|
||||
.validity_votes()
|
||||
.contains(&ValidityAttestation::Explicit(signed_b.signature().clone())));
|
||||
assert!(candidates[0]
|
||||
.validity_votes
|
||||
.validity_votes()
|
||||
.contains(&ValidityAttestation::Explicit(signed_c.signature().clone())));
|
||||
assert_eq!(
|
||||
candidates[0].validator_indices,
|
||||
bitvec::bitvec![u8, bitvec::order::Lsb0; 1, 0, 1, 1],
|
||||
candidates[0].validator_indices_and_core_index(false),
|
||||
(bitvec::bitvec![u8, bitvec::order::Lsb0; 1, 0, 1, 1].as_bitslice(), None)
|
||||
);
|
||||
|
||||
virtual_overseer
|
||||
@@ -1604,8 +1643,11 @@ fn candidate_backing_reorders_votes() {
|
||||
let expected_attestations =
|
||||
vec![fake_attestation(1).into(), fake_attestation(3).into(), fake_attestation(5).into()];
|
||||
|
||||
assert_eq!(backed.validator_indices, expected_bitvec);
|
||||
assert_eq!(backed.validity_votes, expected_attestations);
|
||||
assert_eq!(
|
||||
backed.validator_indices_and_core_index(false),
|
||||
(expected_bitvec.as_bitslice(), None)
|
||||
);
|
||||
assert_eq!(backed.validity_votes(), expected_attestations);
|
||||
}
|
||||
|
||||
// Test whether we retry on failed PoV fetching.
|
||||
|
||||
Reference in New Issue
Block a user