Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime: allow backing multiple candidates of same parachain on different cores #3231

Merged
merged 63 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
cab6ab9
Switch statement table from ParaId to CoreIndex
sandreim Feb 1, 2024
d2df658
cargo lock
sandreim Feb 2, 2024
4a8b8d5
add experimental feature
sandreim Feb 6, 2024
9244632
inject core_index from statements
sandreim Feb 6, 2024
22e017b
temporary provisioner fix
sandreim Feb 6, 2024
9dc8927
Support injected `CoreIndex`
sandreim Feb 6, 2024
574b06a
Merge branch 'master' of github.com:paritytech/polkadot-sdk into sand…
sandreim Feb 6, 2024
fbb7351
cargo lock
sandreim Feb 6, 2024
c6b833e
Merge branch 'sandreim/backing_multiple_cores_per_para' of github.com…
sandreim Feb 6, 2024
6c72918
It was damn hard to fix these tests
sandreim Feb 12, 2024
fc5c109
These tests were easy to fix
sandreim Feb 12, 2024
33351b4
Fix comment
sandreim Feb 12, 2024
0d994bf
clippy was angry
sandreim Feb 12, 2024
534c019
A bit refactor and add a test
sandreim Feb 12, 2024
10d86dd
taplo happy
sandreim Feb 12, 2024
d990a65
Merge branch 'sandreim/backing_multiple_cores_per_para' of github.com…
sandreim Feb 13, 2024
fbe1ad5
BackedCandidate: make all members private and provide an interface
sandreim Feb 13, 2024
e74f038
refactor based on new BackedCandidate
sandreim Feb 13, 2024
d898740
Fix all parachain runtime tests affected
sandreim Feb 13, 2024
9e40490
fix more broken test on node side
sandreim Feb 13, 2024
42f46a0
wip new test
sandreim Feb 14, 2024
222609c
review feedback
sandreim Feb 14, 2024
532d363
Merge branch 'sandreim/backing_multiple_cores_per_para' of github.com…
sandreim Feb 14, 2024
ccb2a88
ElasticScalingCoreIndex
sandreim Feb 14, 2024
a5ba157
finish filtering of candidates for elastic scaling
sandreim Feb 14, 2024
a02e896
remove log
sandreim Feb 14, 2024
dd34850
more feedback
sandreim Feb 14, 2024
838a846
Merge remote-tracking branch 'origin/master' into sandreim/backing_mu…
alindima Feb 19, 2024
ad98f18
use next up on available instead of occupied core index
alindima Feb 19, 2024
606d7c4
ElasticScalingCoreIndex -> ElasticScalingMVP
alindima Feb 19, 2024
6fb6b73
Merge remote-tracking branch 'origin/sandreim/backing_multiple_cores_…
alindima Feb 20, 2024
10f6486
rename ElasticScalingCoreIndex
alindima Feb 20, 2024
f9e178d
address some comments
alindima Feb 20, 2024
ec7b660
+1
alindima Feb 20, 2024
578850b
more comments
alindima Feb 20, 2024
362ff1e
add a backing test
alindima Feb 20, 2024
2385369
add rstest
alindima Feb 20, 2024
c793b89
small nits and typos
alindima Feb 20, 2024
8398bb1
Merge remote-tracking branch 'origin/master' into sandreim/backing_mu…
alindima Feb 20, 2024
27ec25b
Merge remote-tracking branch 'origin/sandreim/backing_multiple_cores_…
alindima Feb 20, 2024
9f70276
Merge remote-tracking branch 'origin/master' into sandreim/backing_mu…
alindima Feb 21, 2024
19c9a67
review comments
alindima Feb 21, 2024
d7b6ce8
add zombienet test
alindima Feb 21, 2024
afed2a8
fix existing unit tests
alindima Feb 21, 2024
7ea040d
add prdoc
alindima Feb 21, 2024
79f281b
fix clippy
alindima Feb 21, 2024
7521ed9
try fixing prdoc
alindima Feb 21, 2024
9c3dd5c
cache Validator->Group mapping
alindima Feb 21, 2024
0b0b6d1
Merge remote-tracking branch 'origin/sandreim/backing_multiple_cores_…
alindima Feb 21, 2024
7976e2f
lockfile
alindima Feb 21, 2024
4d6e797
add tests for backedcandidate functions
alindima Feb 21, 2024
4c36440
newlines
alindima Feb 22, 2024
af1cd82
use Arc to avoid cloning
alindima Feb 22, 2024
5cc5b8b
Merge branch 'sandreim/backing_multiple_cores_per_para' into sandreim…
alindima Feb 22, 2024
dc57adb
add check for parachain stall to zombienet test
alindima Feb 22, 2024
bb5968c
add more unit tests
alindima Feb 22, 2024
1ca7a70
Merge remote-tracking branch 'origin/master' into sandreim/runtime_co…
alindima Feb 22, 2024
eb345b0
fix clippy
alindima Feb 22, 2024
058c0c2
refactor
alindima Feb 22, 2024
d4c58bd
fix some bugs and add more unit tests
alindima Feb 23, 2024
cb41758
update some comments
alindima Feb 23, 2024
bffa4e9
review comments
alindima Feb 23, 2024
5d3a85d
fix unit test
alindima Feb 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitlab/pipeline/zombienet/polkadot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ zombienet-polkadot-functional-0011-async-backing-6-seconds-rate:
--local-dir="${LOCAL_DIR}/functional"
--test="0011-async-backing-6-seconds-rate.zndsl"

zombienet-polkadot-functional-0012-elastic-scaling-mvp:
extends:
- .zombienet-polkadot-common
script:
- /home/nonroot/zombie-net/scripts/ci/run-test-local-env-manager.sh
--local-dir="${LOCAL_DIR}/functional"
--test="0012-elastic-scaling-mvp.zndsl"

zombienet-polkadot-smoke-0001-parachains-smoke-test:
extends:
- .zombienet-polkadot-common
Expand Down
37 changes: 37 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions polkadot/node/core/backing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ sc-keystore = { path = "../../../../substrate/client/keystore" }
sp-tracing = { path = "../../../../substrate/primitives/tracing" }
futures = { version = "0.3.21", features = ["thread-pool"] }
assert_matches = "1.4.0"
rstest = "0.18.2"
polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" }
test-helpers = { package = "polkadot-primitives-test-helpers", path = "../../../primitives/test-helpers" }
19 changes: 7 additions & 12 deletions polkadot/node/core/backing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ use std::{
sync::Arc,
};

use bitvec::{order::Lsb0 as BitOrderLsb0, vec::BitVec};
use bitvec::vec::BitVec;
use futures::{
channel::{mpsc, oneshot},
future::BoxFuture,
Expand Down Expand Up @@ -494,20 +494,15 @@ fn table_attested_to_backed(
}
vote_positions.sort_by_key(|(_orig, pos_in_group)| *pos_in_group);

if inject_core_index {
let core_index_to_inject: BitVec<u8, BitOrderLsb0> =
BitVec::from_vec(vec![core_index.0 as u8]);
validator_indices.extend(core_index_to_inject);
}

Some(BackedCandidate {
Some(BackedCandidate::new(
candidate,
validity_votes: vote_positions
vote_positions
.into_iter()
.map(|(pos_in_votes, _pos_in_group)| validity_votes[pos_in_votes].clone())
.collect(),
validator_indices,
})
inject_core_index.then_some(core_index),
))
}

async fn store_available_data(
Expand Down Expand Up @@ -1775,7 +1770,7 @@ async fn post_import_statement_actions<Context>(
&rp_state.table_context,
rp_state.inject_core_index,
) {
let para_id = backed.candidate.descriptor.para_id;
let para_id = backed.candidate().descriptor.para_id;
gum::debug!(
target: LOG_TARGET,
candidate_hash = ?candidate_hash,
Expand All @@ -1796,7 +1791,7 @@ async fn post_import_statement_actions<Context>(
// notify collator protocol.
ctx.send_message(CollatorProtocolMessage::Backed {
para_id,
para_head: backed.candidate.descriptor.para_head,
para_head: backed.candidate().descriptor.para_head,
})
.await;
// Notify statement distribution of backed candidate.
Expand Down
70 changes: 56 additions & 14 deletions polkadot/node/core/backing/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -79,6 +80,7 @@ pub(crate) struct TestState {
relay_parent: Hash,
minimum_backing_votes: u32,
disabled_validators: Vec<ValidatorIndex>,
node_features: NodeFeatures,
}

impl TestState {
Expand Down Expand Up @@ -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(),
}
}
}
Expand Down Expand Up @@ -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();
}
);

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion polkadot/node/core/provisioner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ async fn select_candidates(
// 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 c.candidate().commitments.new_validation_code.is_some() {
if with_validation_code {
return false
}
Expand Down
Loading
Loading