Skip to content

Commit

Permalink
elastic scaling RFC 103 end-to-end test (#6452)
Browse files Browse the repository at this point in the history
Adds a new zombienet-sdk test which verifies that elastic scaling works
correctly both with the MVP and the new RFC 103 implementation which
sends the core selector as a UMP signal.

Also enables the V2 receipts node feature for testnet genesis config.

Part of #5049

---------

Co-authored-by: Javier Viola <[email protected]>
Co-authored-by: Javier Viola <[email protected]>
  • Loading branch information
3 people authored Dec 18, 2024
1 parent 4a0e3f6 commit f24007e
Show file tree
Hide file tree
Showing 19 changed files with 369 additions and 41 deletions.
19 changes: 19 additions & 0 deletions .gitlab/pipeline/zombienet/polkadot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
LOCAL_SDK_TEST: "/builds/parity/mirrors/polkadot-sdk/polkadot/zombienet-sdk-tests"
FF_DISABLE_UMASK_FOR_DOCKER_EXECUTOR: 1
RUN_IN_CONTAINER: "1"
# don't retry sdk tests
NEXTEST_RETRIES: 0
artifacts:
name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
when: always
Expand Down Expand Up @@ -190,6 +192,7 @@ zombienet-polkadot-elastic-scaling-0001-basic-3cores-6s-blocks:
--local-dir="${LOCAL_DIR}/elastic_scaling"
--test="0002-elastic-scaling-doesnt-break-parachains.zndsl"


.zombienet-polkadot-functional-0012-spam-statement-distribution-requests:
extends:
- .zombienet-polkadot-common
Expand Down Expand Up @@ -397,3 +400,19 @@ zombienet-polkadot-malus-0001-dispute-valid:
- unset NEXTEST_FAILURE_OUTPUT
- unset NEXTEST_SUCCESS_OUTPUT
- cargo nextest run --archive-file ./artifacts/polkadot-zombienet-tests.tar.zst --no-capture -- smoke::coretime_revenue::coretime_revenue_test

zombienet-polkadot-elastic-scaling-slot-based-3cores:
extends:
- .zombienet-polkadot-common
needs:
- job: build-polkadot-zombienet-tests
artifacts: true
before_script:
- !reference [ ".zombienet-polkadot-common", "before_script" ]
- export POLKADOT_IMAGE="${ZOMBIENET_INTEGRATION_TEST_IMAGE}"
- export CUMULUS_IMAGE="docker.io/paritypr/test-parachain:${PIPELINE_IMAGE_TAG}"
script:
# we want to use `--no-capture` in zombienet tests.
- unset NEXTEST_FAILURE_OUTPUT
- unset NEXTEST_SUCCESS_OUTPUT
- cargo nextest run --archive-file ./artifacts/polkadot-zombienet-tests.tar.zst --no-capture -- elastic_scaling::slot_based_3cores::slot_based_3cores_test
25 changes: 13 additions & 12 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1389,7 +1389,7 @@ xcm-procedural = { path = "polkadot/xcm/procedural", default-features = false }
xcm-runtime-apis = { path = "polkadot/xcm/xcm-runtime-apis", default-features = false }
xcm-simulator = { path = "polkadot/xcm/xcm-simulator", default-features = false }
zeroize = { version = "1.7.0", default-features = false }
zombienet-sdk = { version = "0.2.16" }
zombienet-sdk = { version = "0.2.19" }
zstd = { version = "0.12.4", default-features = false }

[profile.release]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ polkadot-runtime-common = { workspace = true }
# Cumulus
cumulus-pallet-aura-ext = { workspace = true }
pallet-message-queue = { workspace = true }
cumulus-pallet-parachain-system = { workspace = true, features = ["experimental-ump-signals"] }
cumulus-pallet-parachain-system = { workspace = true }
cumulus-pallet-xcm = { workspace = true }
cumulus-pallet-xcmp-queue = { workspace = true }
cumulus-ping = { workspace = true }
Expand Down
1 change: 1 addition & 0 deletions cumulus/test/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,4 @@ std = [
]
increment-spec-version = []
elastic-scaling = []
experimental-ump-signals = ["cumulus-pallet-parachain-system/experimental-ump-signals"]
8 changes: 8 additions & 0 deletions cumulus/test/runtime/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ fn main() {
.with_current_project()
.enable_feature("elastic-scaling")
.import_memory()
.set_file_name("wasm_binary_elastic_scaling_mvp.rs")
.build();

WasmBuilder::new()
.with_current_project()
.enable_feature("elastic-scaling")
.enable_feature("experimental-ump-signals")
.import_memory()
.set_file_name("wasm_binary_elastic_scaling.rs")
.build();
}
Expand Down
5 changes: 5 additions & 0 deletions cumulus/test/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ pub mod wasm_spec_version_incremented {
include!(concat!(env!("OUT_DIR"), "/wasm_binary_spec_version_incremented.rs"));
}

pub mod elastic_scaling_mvp {
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary_elastic_scaling_mvp.rs"));
}

pub mod elastic_scaling {
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary_elastic_scaling.rs"));
Expand Down
10 changes: 10 additions & 0 deletions cumulus/test/service/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,13 @@ pub fn get_elastic_scaling_chain_spec(id: Option<ParaId>) -> ChainSpec {
.expect("WASM binary was not built, please build it!"),
)
}

/// Get the chain spec for a specific parachain ID.
pub fn get_elastic_scaling_mvp_chain_spec(id: Option<ParaId>) -> ChainSpec {
get_chain_spec_with_extra_endowed(
id,
Default::default(),
cumulus_test_runtime::elastic_scaling_mvp::WASM_BINARY
.expect("WASM binary was not built, please build it!"),
)
}
8 changes: 7 additions & 1 deletion cumulus/test/service/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,16 @@ impl SubstrateCli for TestCollatorCli {
tracing::info!("Using default test service chain spec.");
Box::new(cumulus_test_service::get_chain_spec(Some(ParaId::from(2000)))) as Box<_>
},
"elastic-scaling-mvp" => {
tracing::info!("Using elastic-scaling mvp chain spec.");
Box::new(cumulus_test_service::get_elastic_scaling_mvp_chain_spec(Some(
ParaId::from(2100),
))) as Box<_>
},
"elastic-scaling" => {
tracing::info!("Using elastic-scaling chain spec.");
Box::new(cumulus_test_service::get_elastic_scaling_chain_spec(Some(ParaId::from(
2100,
2200,
)))) as Box<_>
},
path => {
Expand Down
4 changes: 3 additions & 1 deletion polkadot/runtime/rococo/src/genesis_config_presets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ fn default_parachains_host_configuration(
allowed_ancestry_len: 2,
},
node_features: bitvec::vec::BitVec::from_element(
1u8 << (FeatureIndex::ElasticScalingMVP as usize),
1u8 << (FeatureIndex::ElasticScalingMVP as usize) |
1u8 << (FeatureIndex::EnableAssignmentsV2 as usize) |
1u8 << (FeatureIndex::CandidateReceiptV2 as usize),
),
scheduler_params: SchedulerParams {
lookahead: 2,
Expand Down
3 changes: 2 additions & 1 deletion polkadot/runtime/westend/src/genesis_config_presets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ fn default_parachains_host_configuration(
},
node_features: bitvec::vec::BitVec::from_element(
1u8 << (FeatureIndex::ElasticScalingMVP as usize) |
1u8 << (FeatureIndex::EnableAssignmentsV2 as usize),
1u8 << (FeatureIndex::EnableAssignmentsV2 as usize) |
1u8 << (FeatureIndex::CandidateReceiptV2 as usize),
),
scheduler_params: SchedulerParams {
lookahead: 2,
Expand Down
65 changes: 44 additions & 21 deletions polkadot/zombienet-sdk-tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,47 @@ fn make_env_key(k: &str) -> String {
replace_dashes(&k.to_ascii_uppercase())
}

fn wasm_sub_path(chain: &str) -> String {
let (package, runtime_name) =
if let Some(cumulus_test_runtime) = chain.strip_prefix("cumulus-test-runtime-") {
(
"cumulus-test-runtime".to_string(),
format!("wasm_binary_{}.rs", replace_dashes(cumulus_test_runtime)),
)
} else {
(format!("{chain}-runtime"), replace_dashes(&format!("{chain}-runtime")))
};

format!("{}/{}.wasm", package, runtime_name)
}

fn find_wasm(chain: &str) -> Option<PathBuf> {
const PROFILES: [&str; 2] = ["release", "testnet"];
let manifest_path = env::var("CARGO_WORKSPACE_ROOT_DIR").unwrap();
let manifest_path = manifest_path.strip_suffix('/').unwrap();
debug_output!("manifest_path is : {}", manifest_path);
let package = format!("{chain}-runtime");

let sub_path = wasm_sub_path(chain);

let profile = PROFILES.into_iter().find(|p| {
let full_path = format!(
"{}/target/{}/wbuild/{}/{}.wasm",
manifest_path,
p,
&package,
replace_dashes(&package)
);
let full_path = format!("{}/target/{}/wbuild/{}", manifest_path, p, sub_path);
debug_output!("checking wasm at : {}", full_path);
matches!(path::PathBuf::from(&full_path).try_exists(), Ok(true))
});

debug_output!("profile is : {:?}", profile);
profile.map(|profile| {
PathBuf::from(&format!(
"{}/target/{}/wbuild/{}/{}.wasm",
manifest_path,
profile,
&package,
replace_dashes(&package)
))
PathBuf::from(&format!("{}/target/{}/wbuild/{}", manifest_path, profile, sub_path))
})
}

// based on https://gist.github.com/s0me0ne-unkn0wn/bbd83fe32ce10327086adbf13e750eec
fn build_wasm(chain: &str) -> PathBuf {
let package = format!("{chain}-runtime");
let package = if chain.starts_with("cumulus-test-runtime-") {
String::from("cumulus-test-runtime")
} else {
format!("{chain}-runtime")
};

let cargo = env::var("CARGO").unwrap();
let target = env::var("TARGET").unwrap();
Expand All @@ -81,11 +89,7 @@ fn build_wasm(chain: &str) -> PathBuf {
.status()
.unwrap();

let wasm_path = &format!(
"{target_dir}/{target}/release/wbuild/{}/{}.wasm",
&package,
replace_dashes(&package)
);
let wasm_path = &format!("{target_dir}/{target}/release/wbuild/{}", wasm_sub_path(chain));
PathBuf::from(wasm_path)
}

Expand Down Expand Up @@ -128,6 +132,10 @@ fn main() {
const METADATA_DIR: &str = "metadata-files";
const CHAINS: [&str; 2] = ["rococo", "coretime-rococo"];

// Add some cumulus test runtimes if needed. Formatted like
// "cumulus-test-runtime-elastic-scaling".
const CUMULUS_TEST_RUNTIMES: [&str; 0] = [];

let metadata_path = format!("{manifest_path}/{METADATA_DIR}");

for chain in CHAINS {
Expand All @@ -145,6 +153,21 @@ fn main() {
};
}

for chain in CUMULUS_TEST_RUNTIMES {
let full_path = format!("{metadata_path}/{chain}-local.scale");
let output_path = path::PathBuf::from(&full_path);

match output_path.try_exists() {
Ok(true) => {
debug_output!("got: {}", full_path);
},
_ => {
debug_output!("needs: {}", full_path);
fetch_metadata_file(chain, &output_path);
},
};
}

substrate_build_script_utils::generate_cargo_keys();
substrate_build_script_utils::rerun_if_git_head_changed();
println!("cargo:rerun-if-changed={}", metadata_path);
Expand Down
60 changes: 60 additions & 0 deletions polkadot/zombienet-sdk-tests/tests/elastic_scaling/helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

use super::rococo;
use std::{collections::HashMap, ops::Range};
use subxt::{OnlineClient, PolkadotConfig};

// Helper function for asserting the throughput of parachains (total number of backed candidates in
// a window of relay chain blocks), after the first session change.
pub async fn assert_para_throughput(
relay_client: &OnlineClient<PolkadotConfig>,
stop_at: u32,
expected_candidate_ranges: HashMap<u32, Range<u32>>,
) -> Result<(), anyhow::Error> {
let mut blocks_sub = relay_client.blocks().subscribe_finalized().await?;
let mut candidate_count: HashMap<u32, u32> = HashMap::new();
let mut current_block_count = 0;
let mut had_first_session_change = false;

while let Some(block) = blocks_sub.next().await {
let block = block?;
log::debug!("Finalized relay chain block {}", block.number());
let events = block.events().await?;
let is_session_change = events.has::<rococo::session::events::NewSession>()?;

if !had_first_session_change && is_session_change {
had_first_session_change = true;
}

if had_first_session_change && !is_session_change {
current_block_count += 1;

for event in events.find::<rococo::para_inclusion::events::CandidateBacked>() {
*(candidate_count.entry(event?.0.descriptor.para_id.0).or_default()) += 1;
}
}

if current_block_count == stop_at {
break;
}
}

log::info!(
"Reached {} finalized relay chain blocks that contain backed candidates. The per-parachain distribution is: {:#?}",
stop_at,
candidate_count
);

for (para_id, expected_candidate_range) in expected_candidate_ranges {
let actual = candidate_count
.get(&para_id)
.expect("ParaId did not have any backed candidates");
assert!(
expected_candidate_range.contains(actual),
"Candidate count {actual} not within range {expected_candidate_range:?}"
);
}

Ok(())
}
8 changes: 8 additions & 0 deletions polkadot/zombienet-sdk-tests/tests/elastic_scaling/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

#[subxt::subxt(runtime_metadata_path = "metadata-files/rococo-local.scale")]
pub mod rococo {}

mod helpers;
mod slot_based_3cores;
Loading

0 comments on commit f24007e

Please sign in to comment.