diff --git a/Cargo.lock b/Cargo.lock index a856a331b626d..f9ff5a2ea94dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20587,7 +20587,10 @@ dependencies = [ "anyhow", "assert_matches", "async-trait", + "chrono", "criterion", + "cumulus-zombienet-sdk-helpers", + "env_logger 0.11.3", "futures", "futures-timer", "indexmap 2.9.0", @@ -20601,6 +20604,7 @@ dependencies = [ "sc-transaction-pool-api", "sc-utils", "serde", + "serde_json", "sp-api 26.0.0", "sp-blockchain", "sp-consensus", @@ -20619,6 +20623,7 @@ dependencies = [ "tokio-stream", "tracing", "tracing-subscriber", + "zombienet-configuration", "zombienet-sdk", ] @@ -24914,9 +24919,9 @@ version = "4.0.0-dev" [[package]] name = "substrate-txtesttool" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4116d4d42f14bc24166fd5b3d1d7b90e000e563fa648a87cb9cf27055c53625" +checksum = "c8e742db3b239740f3ec7d4cfa5cdbc06a9820ed2dd48b073aa3b5de99bb7aed" dependencies = [ "async-trait", "average", diff --git a/Cargo.toml b/Cargo.toml index 043f2abe82fe3..b47d7d30f76d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1436,7 +1436,7 @@ trybuild = { version = "1.0.103" } tt-call = { version = "1.0.8" } tuplex = { version = "0.1", default-features = false } twox-hash = { version = "1.6.3", default-features = false } -txtesttool = { version = "0.5.0", package = "substrate-txtesttool" } +txtesttool = { version = "0.6.0", package = "substrate-txtesttool" } unsigned-varint = { version = "0.7.2" } url = { version = "2.5.4" } verifiable = { version = "0.1", default-features = false } @@ -1465,6 +1465,7 @@ xcm-runtime-apis = { path = "polkadot/xcm/xcm-runtime-apis", default-features = xcm-simulator = { path = "polkadot/xcm/xcm-simulator", default-features = false } yet-another-parachain-runtime = { path = "cumulus/parachains/runtimes/testing/yet-another-parachain" } zeroize = { version = "1.7.0", default-features = false } +zombienet-configuration = { version = "0.3.6" } zombienet-orchestrator = { version = "0.3.6" } zombienet-sdk = { version = "0.3.6" } zstd = { version = "0.12.4", default-features = false } diff --git a/prdoc/pr_8152.prdoc b/prdoc/pr_8152.prdoc new file mode 100644 index 0000000000000..41e3e1184a63d --- /dev/null +++ b/prdoc/pr_8152.prdoc @@ -0,0 +1,7 @@ +title: '`fatxpool`: some more integration tests' +doc: +- audience: Node Dev + description: Some new test cases and improvements of zombienet integration tests for `fatxpool`. +crates: +- name: sc-transaction-pool + bump: minor diff --git a/substrate/client/transaction-pool/Cargo.toml b/substrate/client/transaction-pool/Cargo.toml index b51ceb45d0986..4e4ec9ef8b675 100644 --- a/substrate/client/transaction-pool/Cargo.toml +++ b/substrate/client/transaction-pool/Cargo.toml @@ -48,9 +48,14 @@ tracing = { workspace = true, default-features = true } [dev-dependencies] anyhow = { workspace = true } assert_matches = { workspace = true } +chrono = { workspace = true } criterion = { workspace = true, default-features = true } +cumulus-zombienet-sdk-helpers = { workspace = true } +env_logger = { workspace = true } rstest = { workspace = true } sc-block-builder = { workspace = true, default-features = true } +serde = { workspace = true } +serde_json = { workspace = true } sp-consensus = { workspace = true, default-features = true } substrate-test-runtime = { workspace = true } substrate-test-runtime-client = { workspace = true } @@ -59,4 +64,5 @@ thiserror = { workspace = true } tokio = { workspace = true, features = ["rt-multi-thread"] } tracing-subscriber = { workspace = true } txtesttool = { workspace = true } +zombienet-configuration = { workspace = true } zombienet-sdk = { workspace = true } diff --git a/substrate/client/transaction-pool/tests/integration.rs b/substrate/client/transaction-pool/tests/integration.rs index 200266848d8a2..f723a81a284e0 100644 --- a/substrate/client/transaction-pool/tests/integration.rs +++ b/substrate/client/transaction-pool/tests/integration.rs @@ -16,18 +16,19 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -// Testsuite of fatp integration tests. +//! Testsuite of transaction pool integration tests. + pub mod zombienet; +use std::time::Duration; + use crate::zombienet::{ - default_zn_scenario_builder, - relaychain_rococo_local_network_spec::{ - parachain_asset_hub_network_spec::HIGH_POOL_LIMIT_FATP as PARACHAIN_HIGH_POOL_LIMIT_FATP, - HIGH_POOL_LIMIT_FATP as RELAYCHAIN_HIGH_POOL_LIMIT_FATP, - }, - NetworkSpawner, + default_zn_scenario_builder, relaychain_rococo_local_network_spec as relay, + relaychain_rococo_local_network_spec::parachain_asset_hub_network_spec as para, NetworkSpawner, }; -use txtesttool::execution_log::ExecutionLog; +use futures::future::join_all; +use tracing::info; +use txtesttool::{execution_log::ExecutionLog, scenario::ScenarioExecutor}; use zombienet::DEFAULT_SEND_FUTURE_AND_READY_TXS_TESTS_TIMEOUT_IN_SECS; // Test which sends future and ready txs from many accounts @@ -35,7 +36,7 @@ use zombienet::DEFAULT_SEND_FUTURE_AND_READY_TXS_TESTS_TIMEOUT_IN_SECS; #[tokio::test(flavor = "multi_thread")] #[ignore] async fn send_future_and_ready_from_many_accounts_to_parachain() { - let net = NetworkSpawner::from_toml_with_env_logger(PARACHAIN_HIGH_POOL_LIMIT_FATP) + let net = NetworkSpawner::from_toml_with_env_logger(para::HIGH_POOL_LIMIT_FATP) .await .unwrap(); @@ -86,7 +87,7 @@ async fn send_future_and_ready_from_many_accounts_to_parachain() { #[tokio::test(flavor = "multi_thread")] #[ignore] async fn send_future_and_ready_from_many_accounts_to_relaychain() { - let net = NetworkSpawner::from_toml_with_env_logger(RELAYCHAIN_HIGH_POOL_LIMIT_FATP) + let net = NetworkSpawner::from_toml_with_env_logger(relay::HIGH_POOL_LIMIT_FATP) .await .unwrap(); @@ -133,3 +134,241 @@ async fn send_future_and_ready_from_many_accounts_to_relaychain() { assert_eq!(finalized_future, 10_000); assert_eq!(finalized_ready, 10_000); } + +// Test which sends 5m transactions to parachain. Long execution time expected. +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn send_5m_from_many_accounts_to_parachain() { + let net = NetworkSpawner::from_toml_with_env_logger(para::HIGH_POOL_LIMIT_FATP) + .await + .unwrap(); + + // Wait for the parachain collator to start block production. + net.wait_for_block_production("charlie").await.unwrap(); + + // Create txs executor. + let ws = net.node_rpc_uri("charlie").unwrap(); + let executor = default_zn_scenario_builder(&net) + .with_rpc_uri(ws) + .with_start_id(0) + .with_last_id(999) + .with_txs_count(5_000) + .with_executor_id("txs-executor".to_string()) + .with_send_threshold(7500) + .build() + .await; + + // Execute transactions and fetch the execution logs. + let execution_logs = executor.execute().await; + let finalized_txs = execution_logs.values().filter_map(|tx_log| tx_log.finalized()).count(); + + assert_eq!(finalized_txs, 5_000_000); +} + +// Test which sends 5m transactions to relaychain. Long execution time expected. +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn send_5m_from_many_accounts_to_relaychain() { + let net = NetworkSpawner::from_toml_with_env_logger(relay::HIGH_POOL_LIMIT_FATP) + .await + .unwrap(); + + // Wait for the parachain collator to start block production. + net.wait_for_block_production("alice").await.unwrap(); + + // Create txs executor. + let ws = net.node_rpc_uri("alice").unwrap(); + let executor = default_zn_scenario_builder(&net) + .with_rpc_uri(ws.clone()) + .with_start_id(0) + .with_last_id(999) + .with_txs_count(5000) + .with_executor_id("txs-executor".to_string()) + .with_send_threshold(7500) + .build() + .await; + + // Execute transactions and fetch the execution logs. + let execution_logs = executor.execute().await; + let finalized_txs = execution_logs.values().filter_map(|tx_log| tx_log.finalized()).count(); + + assert_eq!(finalized_txs, 5_000_000); +} + +/// Internal test that allows to observe how transcactions are gossiped in the network. Requires +/// external tool to track transactions presence at nodes. Was used to evaluate some metrics of +/// existing transaction protocol. +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn gossiping() { + let net = NetworkSpawner::from_toml_with_env_logger(relay::HIGH_POOL_LIMIT_FATP_TRACE) + .await + .unwrap(); + + // Wait for the parachain collator to start block production. + net.wait_for_block_production("a00").await.unwrap(); + + // Create the txs executor. + let ws = net.node_rpc_uri("a00").unwrap(); + let executor = default_zn_scenario_builder(&net) + .with_rpc_uri(ws) + .with_start_id(0) + .with_last_id(999) + .with_executor_id("txs-executor".to_string()) + .build() + .await; + + // Execute transactions and fetch the execution logs. + let execution_logs = executor.execute().await; + let finalized_txs = execution_logs.values().filter_map(|tx_log| tx_log.finalized()).count(); + + assert_eq!(finalized_txs, 1000); + + tracing::info!("BASEDIR: {:?}", net.base_dir_path()); +} + +/// Creates new transaction scenario executor and sends given batch of ready transactions to the +/// specified node. Single transaction is sent from single account. +async fn send_batch( + net: &NetworkSpawner, + node_name: &str, + from: u32, + to: u32, + prio: u32, +) -> ScenarioExecutor { + let ws = net.node_rpc_uri(node_name).unwrap(); + info!(from, to, prio, "send_batch"); + default_zn_scenario_builder(net) + .with_rpc_uri(ws) + .with_start_id(from) + .with_last_id(to) + .with_txs_count(1) + .with_tip(prio.into()) + .with_executor_id(format!("txs-executor_{}_{}_{}", from, to, prio)) + .with_send_threshold(usize::MAX) + .with_legacy_backend(true) + .build() + .await +} + +/// Repeatedly sends batches of transactions to the specified node with priority provided by +/// closure. +/// +/// This function loops indefinitely, adjusting the priority of the transaction batch each time +/// based on the provided function. Each batch is executed by an executor that times out after +/// period duration if not completed. +/// +/// The progress of transactions is intentionally not monitored; the utility is intended for +/// transaction pool limits testing, where the accuracy of execution is challenging to monitor. +async fn batch_loop( + net: &NetworkSpawner, + node_name: &str, + from: u32, + to: u32, + priority: F, + period: std::time::Duration, +) where + F: Fn(u32) -> u32, +{ + let mut prio = 0; + loop { + prio = priority(prio); + let executor = send_batch(&net, node_name, from, to, prio).await; + let start = std::time::Instant::now(); + let _results = tokio::time::timeout(period, executor.execute()).await; + let elapsed = start.elapsed(); + if elapsed < period { + tokio::time::sleep(period - elapsed).await; + } + } +} + +/// Tests the transaction pool limits by continuously sending transaction batches to a parachain +/// network node. This test checks the pool's behavior under high load by simulating multiple +/// senders with increasing priorities. +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_limits_increasing_prio_parachain() { + let net = NetworkSpawner::from_toml_with_env_logger(para::LOW_POOL_LIMIT_FATP) + .await + .unwrap(); + + net.wait_for_block_production("charlie").await.unwrap(); + + let mut executors = vec![]; + let senders_count = 25; + let sender_batch = 2000; + + for i in 0..senders_count { + let from = 0 + i * sender_batch; + let to = from + sender_batch - 1; + executors.push(batch_loop( + &net, + "charlie", + from, + to, + |prio| prio + 1, + Duration::from_secs(60), + )); + } + + let _results = join_all(executors).await; +} + +/// Tests the transaction pool limits by continuously sending transaction batches to a relaychain +/// network node. This test checks the pool's behavior under high load by simulating multiple +/// senders with increasing priorities. +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_limits_increasing_prio_relaychain() { + let net = NetworkSpawner::from_toml_with_env_logger(relay::LOW_POOL_LIMIT_FATP) + .await + .unwrap(); + + net.wait_for_block_production("alice").await.unwrap(); + + let mut executors = vec![]; + //this looks like current limit of what we can handle. A bit choky but almost no empty blocks. + let senders_count = 50; + let sender_batch = 2000; + + for i in 0..senders_count { + let from = 0 + i * sender_batch; + let to = from + sender_batch - 1; + executors.push(batch_loop( + &net, + "alice", + from, + to, + |prio| prio + 1, + Duration::from_secs(15), + )); + } + + let _results = join_all(executors).await; +} + +/// Tests the transaction pool limits by continuously sending transaction batches to a relaychain +/// network node. This test checks the pool's behavior under high load by simulating multiple +/// senders with increasing priorities. +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn test_limits_same_prio_relaychain() { + let net = NetworkSpawner::from_toml_with_env_logger(relay::LOW_POOL_LIMIT_FATP) + .await + .unwrap(); + + net.wait_for_block_production("alice").await.unwrap(); + + let mut executors = vec![]; + let senders_count = 50; + let sender_batch = 2000; + + for i in 0..senders_count { + let from = 0 + i * sender_batch; + let to = from + sender_batch - 1; + executors.push(batch_loop(&net, "alice", from, to, |prio| prio, Duration::from_secs(15))); + } + + let _results = join_all(executors).await; +} diff --git a/substrate/client/transaction-pool/tests/zombienet/mod.rs b/substrate/client/transaction-pool/tests/zombienet/mod.rs index 206c69b0c657b..3c55d207ab24d 100644 --- a/substrate/client/transaction-pool/tests/zombienet/mod.rs +++ b/substrate/client/transaction-pool/tests/zombienet/mod.rs @@ -20,10 +20,12 @@ //! across integration tests for transaction pool. use anyhow::anyhow; +use std::time::SystemTime; use tracing_subscriber::EnvFilter; use txtesttool::scenario::{ChainType, ScenarioBuilder}; use zombienet_sdk::{ - subxt::SubstrateConfig, LocalFileSystem, Network, NetworkConfig, NetworkConfigExt, + subxt::SubstrateConfig, GlobalSettingsBuilder, LocalFileSystem, Network, NetworkConfig, + NetworkConfigBuilder, NetworkConfigExt, WithRelaychain, }; /// Gathers TOML files paths for relaychains and for parachains' (that use rococo-local based @@ -31,6 +33,10 @@ use zombienet_sdk::{ pub mod relaychain_rococo_local_network_spec { pub const HIGH_POOL_LIMIT_FATP: &'static str = "tests/zombienet/network-specs/rococo-local-high-pool-limit-fatp.toml"; + pub const LOW_POOL_LIMIT_FATP: &'static str = + "tests/zombienet/network-specs/rococo-local-low-pool-limit-fatp.toml"; + pub const HIGH_POOL_LIMIT_FATP_TRACE: &'static str = + "tests/zombienet/network-specs/rococo-local-gossiping.toml"; /// Network specs used for fork-aware tx pool testing of parachains. pub mod parachain_asset_hub_network_spec { @@ -41,6 +47,8 @@ pub mod relaychain_rococo_local_network_spec { } } +mod yap_test; + /// Default time that we expect to need for a full run of current tests that send future and ready /// txs to parachain or relaychain networks. pub const DEFAULT_SEND_FUTURE_AND_READY_TXS_TESTS_TIMEOUT_IN_SECS: u64 = 1500; @@ -60,12 +68,57 @@ pub enum Error { /// Result of work related to network spawning. pub type Result = std::result::Result; +/// Environment variable defining the location of zombienet network base dir. +const TXPOOL_TEST_DIR_ENV: &str = "TXPOOL_TEST_DIR"; + /// Provides logic to spawn a network based on a Zombienet toml file. pub struct NetworkSpawner { network: Network, } impl NetworkSpawner { + /// Initialize the network spawner using given `builder` closure. + pub async fn with_closure(builder: F) -> Result + where + F: FnOnce() -> NetworkConfigBuilder, + { + let _ = env_logger::try_init_from_env( + env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"), + ); + + let config_builder = builder(); + + let net_config = config_builder + .with_global_settings(|global_settings| match NetworkSpawner::base_dir_from_env() { + Some(val) => global_settings.with_base_dir(val), + _ => global_settings, + }) + .build() + .map_err(|errs| { + let msg = errs.into_iter().map(|e| e.to_string()).collect::>().join(", "); + Error::NetworkInit(anyhow!(msg)) + })?; + + Ok(NetworkSpawner { + network: net_config + .spawn_native() + .await + .map_err(|err| Error::NetworkInit(anyhow!(err.to_string())))?, + }) + } + + /// Generates a directory path from an environment variable and the current timestamp. + /// The format is "/test_YMD_HMS" + pub fn base_dir_from_env() -> Option { + std::env::var(TXPOOL_TEST_DIR_ENV) + .map(|pool_test_dir| { + let datetime: chrono::DateTime = SystemTime::now().into(); + let formatted_date = datetime.format("%Y%m%d_%H%M%S"); + format!("{}/test_{}", pool_test_dir, formatted_date) + }) + .ok() + } + /// Initialize the network spawner based on a Zombienet toml file pub async fn from_toml_with_env_logger(toml_path: &'static str) -> Result { // Initialize the subscriber with a default log level of INFO if RUST_LOG is not set @@ -76,7 +129,15 @@ impl NetworkSpawner { .with_env_filter(env_filter) // Use the env filter .init(); - let net_config = NetworkConfig::load_from_toml(toml_path).map_err(Error::NetworkInit)?; + let net_config = if let Some(base_dir) = Self::base_dir_from_env() { + let settings = GlobalSettingsBuilder::new().with_base_dir(base_dir).build().unwrap(); + NetworkConfig::load_from_toml_with_settings(toml_path, &settings) + .map_err(Error::NetworkInit)? + } else { + tracing::info!("'{TXPOOL_TEST_DIR_ENV}' env not set, proceeding with defaults."); + NetworkConfig::load_from_toml(toml_path).map_err(Error::NetworkInit)? + }; + Ok(NetworkSpawner { network: net_config .spawn_native() @@ -164,4 +225,5 @@ pub fn default_zn_scenario_builder(net_spawner: &NetworkSpawner) -> ScenarioBuil .with_block_monitoring(shared_params.does_block_monitoring) .with_chain_type(shared_params.chain_type) .with_base_dir_path(net_spawner.base_dir_path().unwrap().to_string()) + .with_timeout_in_secs(21600) //6 hours } diff --git a/substrate/client/transaction-pool/tests/zombienet/network-specs/asset-hub-high-pool-limit-fatp.toml b/substrate/client/transaction-pool/tests/zombienet/network-specs/asset-hub-high-pool-limit-fatp.toml index 8ca7a134e18ae..fc0d034307fac 100644 --- a/substrate/client/transaction-pool/tests/zombienet/network-specs/asset-hub-high-pool-limit-fatp.toml +++ b/substrate/client/transaction-pool/tests/zombienet/network-specs/asset-hub-high-pool-limit-fatp.toml @@ -40,7 +40,7 @@ default_args = [ ] [parachains.genesis.runtimeGenesis.patch.balances] devAccounts = [ - 100, + 1000, 1000000000000000000, "//Sender//{}", ] diff --git a/substrate/client/transaction-pool/tests/zombienet/network-specs/asset-hub-low-pool-limit-fatp.toml b/substrate/client/transaction-pool/tests/zombienet/network-specs/asset-hub-low-pool-limit-fatp.toml index 2a4a276eb1913..3c0b603d09e19 100644 --- a/substrate/client/transaction-pool/tests/zombienet/network-specs/asset-hub-low-pool-limit-fatp.toml +++ b/substrate/client/transaction-pool/tests/zombienet/network-specs/asset-hub-low-pool-limit-fatp.toml @@ -24,9 +24,9 @@ default_command = "polkadot-parachain" default_args = [ "--force-authoring", "--pool-kbytes 2048000", - "--pool-limit 300", + "--pool-limit 10000", "--pool-type=fork-aware", - "--rpc-max-connections 15000", + "--rpc-max-connections 100000", "--rpc-max-response-size 150", "--rpc-max-subscriptions-per-connection=128000", "--state-pruning=1024", @@ -36,10 +36,11 @@ default_args = [ "-lsub-libp2p=info", "-lsync=info", "-ltxpool=debug", + "-ltxpoolstat=debug", ] [parachains.genesis.runtimeGenesis.patch.balances] devAccounts = [ - 100, + 80000, 1000000000000000000, "//Sender//{}", ] diff --git a/substrate/client/transaction-pool/tests/zombienet/network-specs/rococo-local-gossiping.toml b/substrate/client/transaction-pool/tests/zombienet/network-specs/rococo-local-gossiping.toml new file mode 100644 index 0000000000000..4c62372a6a275 --- /dev/null +++ b/substrate/client/transaction-pool/tests/zombienet/network-specs/rococo-local-gossiping.toml @@ -0,0 +1,112 @@ +[settings] +timeout = 1500 + +[relaychain] +default_image = "parity/polkadot:latest" +default_command = "polkadot" +chain = "rococo-local" +default_args = [ + # "--network-backend litep2p", + "--pool-kbytes 2048000", + "--pool-limit 500000", + "--pool-type=fork-aware", + "--rpc-max-connections 15000", + "--rpc-max-response-size 150", + "--rpc-max-subscriptions-per-connection=128000", + "--state-pruning=1024", + "-ltxpool=trace", + "-lsync=trace", + "--out-peers=3", + "--in-peers=3", +] +[relaychain.genesis.runtimeGenesis.patch.balances] +devAccounts = [ + 1000, + 1000000000000000000, + "//Sender//{}", +] + +[[relaychain.nodes]] +name = "a00" +rpc_port = 9944 +validator = true + +[[relaychain.nodes]] +name = "b00" +validator=true + +[[relaychain.nodes]] +name = "b01" +validator=true + +[[relaychain.nodes]] +name = "b02" +validator=true + +[[relaychain.nodes]] +name = "b03" +validator=true + +[[relaychain.nodes]] +name = "b04" +validator=true + +[[relaychain.nodes]] +name = "b05" +validator=true + +[[relaychain.nodes]] +name = "b06" +validator=true + +[[relaychain.nodes]] +name = "b07" +validator=true + +[[relaychain.nodes]] +name = "b08" +validator=true + +[[relaychain.nodes]] +name = "b09" +validator=true + +[[relaychain.nodes]] +name = "b10" +validator=true + +[[relaychain.nodes]] +name = "b11" +validator=true + +[[relaychain.nodes]] +name = "b12" +validator=true + +[[relaychain.nodes]] +name = "b13" +validator=true + +[[relaychain.nodes]] +name = "b14" +validator=true + +[[relaychain.nodes]] +name = "b15" +validator=true + +[[relaychain.nodes]] +name = "b16" +validator=true + +[[relaychain.nodes]] +name = "b17" +validator=true + +[[relaychain.nodes]] +name = "b18" +validator=true + +[[relaychain.nodes]] +name = "b19" +validator=true diff --git a/substrate/client/transaction-pool/tests/zombienet/network-specs/rococo-local-high-pool-limit-fatp.toml b/substrate/client/transaction-pool/tests/zombienet/network-specs/rococo-local-high-pool-limit-fatp.toml index a67e0a4f444e5..5b601c1055750 100644 --- a/substrate/client/transaction-pool/tests/zombienet/network-specs/rococo-local-high-pool-limit-fatp.toml +++ b/substrate/client/transaction-pool/tests/zombienet/network-specs/rococo-local-high-pool-limit-fatp.toml @@ -18,7 +18,7 @@ default_args = [ ] [relaychain.genesis.runtimeGenesis.patch.balances] devAccounts = [ - 100, + 1000, 1000000000000000000, "//Sender//{}", ] diff --git a/substrate/client/transaction-pool/tests/zombienet/network-specs/rococo-local-low-pool-limit-fatp.toml b/substrate/client/transaction-pool/tests/zombienet/network-specs/rococo-local-low-pool-limit-fatp.toml new file mode 100644 index 0000000000000..df5b3a3e288ad --- /dev/null +++ b/substrate/client/transaction-pool/tests/zombienet/network-specs/rococo-local-low-pool-limit-fatp.toml @@ -0,0 +1,42 @@ +[settings] +timeout = 1500 + +[relaychain] +default_image = "parity/polkadot:latest" +default_command = "polkadot" +chain = "rococo-local" +default_args = [ + "--pool-kbytes 2048000", + "--pool-limit 100000", + "--pool-type=fork-aware", + "--rpc-max-connections 15000", + "--rpc-max-response-size 150", + "--rpc-max-subscriptions-per-connection=128000", + "--state-pruning=1024", + "-lsync=info", + "-ltxpool=debug", + "-ltxpoolstat=debug", +] +[relaychain.genesis.runtimeGenesis.patch.balances] +devAccounts = [ + 100000, + 1000000000000000000, + "//Sender//{}", +] + +[[relaychain.nodes]] +# command = "/home/miszka/parity/14-txpool-forks/polkadot-sdk-master-02/target/release-tokio-console/polkadot" +name = "alice" +rpc_port = 9944 +validator = false + +[[relaychain.nodes]] +name = "bob" +rpc_port = 9945 +validator = true + + +[[relaychain.nodes]] +name = "charlie" +rpc_port = 9946 +validator = true diff --git a/substrate/client/transaction-pool/tests/zombienet/yap_test.rs b/substrate/client/transaction-pool/tests/zombienet/yap_test.rs new file mode 100644 index 0000000000000..19ae86b361cfb --- /dev/null +++ b/substrate/client/transaction-pool/tests/zombienet/yap_test.rs @@ -0,0 +1,145 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program 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. + +// This program 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 this program. If not, see . + +// Test inspired (copied) from: +// https://github.com/paritytech/polkadot-sdk/blob/85b71daf7aac59da4d2186b45d589c7c619f0981/polkadot/zombienet-sdk-tests/tests/elastic_scaling/slot_based_3cores.rs#L21 +// and patched as in: +// https://github.com/paritytech/polkadot-sdk/pull/7220#issuecomment-2808830472 + +use crate::zombienet::{NetworkSpawner, ScenarioBuilderSharedParams}; +use cumulus_zombienet_sdk_helpers::create_assign_core_call; +use serde_json::json; +use txtesttool::{execution_log::ExecutionLog, scenario::ScenarioBuilder}; +use zombienet_sdk::{ + subxt::{OnlineClient, PolkadotConfig}, + subxt_signer::sr25519::dev, + NetworkConfigBuilder, +}; + +#[tokio::test(flavor = "multi_thread")] +#[ignore] +async fn slot_based_3cores_test() -> Result<(), anyhow::Error> { + let spawner = NetworkSpawner::with_closure(|| { + let images = zombienet_sdk::environment::get_images_from_env(); + let names = ["alice", "bob", "charlie"]; + NetworkConfigBuilder::new() + .with_relaychain(|r| { + let r = r + .with_chain("rococo-local") + .with_default_command("polkadot") + .with_default_image(images.polkadot.as_str()) + .with_default_args(vec![("-lparachain=debug").into()]) + .with_genesis_overrides(json!({ + "configuration": { + "config": { + "scheduler_params": { + // Num cores is 2, because 1 extra will be added automatically when registering the para. + "num_cores": 2, + "max_validators_per_core": 1 + } + } + } + })) + .with_default_resources(|resources| { + resources.with_request_cpu(4).with_request_memory("4G") + }) + // Have to set a `with_node` outside of the loop below, so that `r` has the + // right type. + .with_node(|node| node.with_name(names[0])); + + (1..3).fold(r, |acc, i| acc.with_node(|node| node.with_name(names[i]))) + }) + .with_parachain(|p| { + // Para 2200 uses the new RFC103-enabled collator which sends the UMP signal + // commitment for selecting the core index + p.with_id(2200) + .with_default_command("polkadot-parachain") + .with_default_image(images.cumulus.as_str()) + .with_chain("yap-rococo-local-2200") + .with_genesis_overrides(json!({ + "balances": { + "devAccounts": [ + 100000, 1000000000000000000u64, "//Sender//{}" + ] + } + })) + .with_default_args(vec![ + "--authoring=slot-based".into(), + "--rpc-max-subscriptions-per-connection=256000".into(), + "--rpc-max-connections=128000".into(), + "--rpc-max-response-size=150".into(), + "--pool-limit=2500000".into(), + "--pool-kbytes=4048000".into(), + "--pool-type=fork-aware".into(), + ("-lparachain=debug,aura=debug,txpool=debug,txpoolstat=debug").into(), + ]) + .with_collator(|n| n.with_name("dave").with_rpc_port(9944)) + }) + }) + .await + .unwrap(); + + let relay_node = spawner.network().get_node("alice")?; + + let relay_client: OnlineClient = relay_node.wait_client().await?; + let alice = dev::alice(); + + let assign_cores_call = create_assign_core_call(&[(0, 2200), (1, 2200)]); + // Assign two extra cores to each parachain. + relay_client + .tx() + .sign_and_submit_then_watch_default(&assign_cores_call, &alice) + .await? + .wait_for_finalized_success() + .await?; + + tracing::info!("2 more cores assigned to the parachain"); + + // Wait for the parachain collator to start block production. + spawner.wait_for_block_production("dave").await.unwrap(); + + // Create txs executor. + let ws = spawner.node_rpc_uri("dave").unwrap(); + let executor = { + let shared_params = ScenarioBuilderSharedParams::default(); + ScenarioBuilder::new() + .with_watched_txs(shared_params.watched_txs) + .with_send_threshold(shared_params.send_threshold) + .with_block_monitoring(shared_params.does_block_monitoring) + .with_chain_type(shared_params.chain_type) + .with_base_dir_path(spawner.base_dir_path().unwrap().to_string()) + .with_timeout_in_secs(21600) //6 hours + .with_legacy_backend(true) + } + .with_rpc_uri(ws) + .with_start_id(0) + .with_last_id(99999) + .with_txs_count(150) + .with_executor_id("txs-executor".to_string()) + .with_send_threshold(25000) + .build() + .await; + + // Execute transactions and fetch the execution logs. + let execution_logs = executor.execute().await; + let finalized_txs = execution_logs.values().filter_map(|tx_log| tx_log.finalized()).count(); + + assert_eq!(finalized_txs, 15_000_000); + + Ok(()) +}