-
Notifications
You must be signed in to change notification settings - Fork 823
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
fork-aware-tx-pool: add heavy load tests based on zombienet #7257
base: master
Are you sure you want to change the base?
Changes from all commits
0283ab9
67c2ee9
7afefe1
6d10819
0e084ab
daba086
f73874a
21fda5f
ef9b658
90ab08d
94b8891
136b95a
5556573
13cffe6
8ec35b9
0b81d99
5f82daf
e90b9d6
11fee80
fbc25ff
b912e05
bf02c0b
c30f602
f275ba3
8de7754
e59e4bf
2507d2c
032e631
0e5b5a9
3f27669
9a665b6
b1c9938
7cbf852
63a9943
2b06198
254ae67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// 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 <https://www.gnu.org/licenses/>. | ||
|
||
// Testsuite of fatp integration tests. | ||
|
||
pub mod zombienet; | ||
|
||
use tracing::{info_span, Instrument}; | ||
use txtesttool::execution_log::ExecutionLog; | ||
use zombienet::{default_zn_scenario_builder, NetworkSpawner}; | ||
|
||
// Test which sends future and ready txs from many accounts | ||
// to an unlimited pool. | ||
#[tokio::test(flavor = "multi_thread")] | ||
async fn send_future_and_ready_from_many_accounts_to_collator() { | ||
let net = NetworkSpawner::from_toml_with_env_logger( | ||
zombienet::asset_hub_based_network_spec_paths::HIGH_POOL_LIMIT_FATP, | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
// Wait for the parachain collator to start block production. | ||
net.wait_for_block_production("charlie").await.unwrap(); | ||
|
||
// Create future & ready txs executors. | ||
let ws = net.node_rpc_uri("charlie").unwrap(); | ||
let future_scenario_executor = default_zn_scenario_builder() | ||
.with_rpc_uri(ws.clone()) | ||
.with_start_id("0".to_string()) | ||
.with_last_id(99) | ||
.with_nonce_from(Some(100)) | ||
.with_txs_count(100) | ||
.build() | ||
.await; | ||
let ready_scenario_executor = default_zn_scenario_builder() | ||
.with_rpc_uri(ws) | ||
.with_start_id("0".to_string()) | ||
.with_last_id(99) | ||
.with_nonce_from(Some(0)) | ||
.with_txs_count(100) | ||
.build() | ||
.await; | ||
|
||
// Execute transactions and fetch the execution logs. | ||
let (future_logs, ready_logs) = futures::future::join( | ||
future_scenario_executor.execute().instrument(info_span!("future-txs-executor")), | ||
ready_scenario_executor.execute().instrument(info_span!("ready-txs-executor")), | ||
) | ||
.await; | ||
|
||
let finalized_future = | ||
future_logs.values().filter_map(|default_log| default_log.finalized()).count(); | ||
let finalized_ready = | ||
ready_logs.values().filter_map(|default_log| default_log.finalized()).count(); | ||
|
||
assert_eq!(finalized_future, 10_000); | ||
assert_eq!(finalized_ready, 10_000); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
// 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 <https://www.gnu.org/licenses/>. | ||
|
||
//! The zombienet spawner for integration tests for a transaction pool. Holds shared logic used | ||
//! across integration tests for transaction pool. | ||
|
||
use anyhow::anyhow; | ||
use tracing_subscriber::EnvFilter; | ||
use txtesttool::scenario::{ChainType, ScenarioBuilder}; | ||
use zombienet_sdk::{ | ||
subxt::SubstrateConfig, LocalFileSystem, Network, NetworkConfig, NetworkConfigExt, | ||
}; | ||
|
||
/// Gathers network TOML specifications file paths. | ||
pub mod asset_hub_based_network_spec_paths { | ||
pub const LOW_POOL_LIMIT_FATP: &'static str = | ||
"tests/zombienet/network-specs/asset-hub-low-pool-limit-fatp.toml"; | ||
pub const HIGH_POOL_LIMIT_FATP: &'static str = | ||
"tests/zombienet/network-specs/asset-hub-high-pool-limit-fatp.toml"; | ||
pub const HIGH_POOL_LIMIT_SSTP_3_COLLATORS: &'static str = | ||
"tests/zombienet/network-specs/asset-hub-high-pool-limit-sstp-3-collators.toml"; | ||
pub const HIGH_POOL_LIMIT_SSTP_4_COLLATORS: &'static str = | ||
"tests/zombienet/network-specs/asset-hub-high-pool-limit-sstp-4-collators.toml"; | ||
} | ||
|
||
#[derive(thiserror::Error, Debug)] | ||
pub enum Error { | ||
#[error("Network initialization failure: {0}")] | ||
NetworkInit(anyhow::Error), | ||
#[error("Node couldn't be found as part of the network: {0}")] | ||
NodeNotFound(anyhow::Error), | ||
#[error("Failed to get node online client")] | ||
FailedToGetOnlineClinet, | ||
#[error("Failed to get node blocks stream")] | ||
FailedToGetBlocksStream, | ||
} | ||
|
||
/// Result of work related to network spawning. | ||
pub type Result<T> = std::result::Result<T, Error>; | ||
|
||
/// Provides logic to spawn a network based on a Zombienet toml file. | ||
pub struct NetworkSpawner { | ||
network: Network<LocalFileSystem>, | ||
} | ||
|
||
impl NetworkSpawner { | ||
/// Initialize the network spawner based on a Zombienet toml file | ||
pub async fn from_toml_with_env_logger(toml_path: &'static str) -> Result<NetworkSpawner> { | ||
// Initialize the subscriber with a default log level of INFO if RUST_LOG is not set | ||
let env_filter = | ||
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); | ||
// Set up the subscriber with the formatter and the environment filter | ||
tracing_subscriber::fmt() | ||
.with_env_filter(env_filter) // Use the env filter | ||
.init(); | ||
|
||
let net_config = NetworkConfig::load_from_toml(toml_path).map_err(Error::NetworkInit)?; | ||
Ok(NetworkSpawner { | ||
network: net_config | ||
.spawn_native() | ||
.await | ||
.map_err(|err| Error::NetworkInit(anyhow!(err.to_string())))?, | ||
}) | ||
} | ||
|
||
/// Returns the spawned network. | ||
pub fn network(&self) -> &Network<LocalFileSystem> { | ||
&self.network | ||
} | ||
|
||
/// Returns a node client and waits for blocks production to kick-off. | ||
pub async fn wait_for_block_production(&self, node_name: &str) -> Result<()> { | ||
let node = self | ||
.network | ||
.get_node(node_name) | ||
.map_err(|_| Error::NodeNotFound(anyhow!("{node_name}")))?; | ||
let client = node | ||
.wait_client::<SubstrateConfig>() | ||
.await | ||
.map_err(|_| Error::FailedToGetOnlineClinet)?; | ||
let mut stream = client | ||
.blocks() | ||
.subscribe_best() | ||
.await | ||
.map_err(|_| Error::FailedToGetBlocksStream)?; | ||
loop { | ||
let Some(block) = stream.next().await else { | ||
continue; | ||
}; | ||
|
||
if let Some(block) = block.ok().filter(|block| block.number() == 1) { | ||
tracing::info!("[{node_name}] found first best block: {:#?}", block.hash()); | ||
break; | ||
} | ||
|
||
tracing::info!("[{node_name}] waiting for first best block"); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Get a certain node rpc uri. | ||
pub fn node_rpc_uri(&self, node_name: &str) -> Result<String> { | ||
self.network | ||
.get_node(node_name) | ||
.and_then(|node| Ok(node.ws_uri().to_string())) | ||
.map_err(|_| Error::NodeNotFound(anyhow!("{node_name}"))) | ||
} | ||
} | ||
|
||
/// Shared params usually set in same way for most of the scenarios. | ||
pub struct ScenarioBuilderSharedParams { | ||
watched_txs: bool, | ||
does_block_monitoring: bool, | ||
send_threshold: usize, | ||
chain_type: ChainType, | ||
} | ||
|
||
impl Default for ScenarioBuilderSharedParams { | ||
fn default() -> Self { | ||
Self { | ||
watched_txs: true, | ||
does_block_monitoring: false, | ||
send_threshold: 20000, | ||
chain_type: ChainType::Sub, | ||
} | ||
} | ||
} | ||
|
||
/// Creates a [`txtesttool::scenario::ScenarioBuilder`] with a set of default parameters defined | ||
/// with [`ScenarioBuilderSharedParams::default`]. | ||
pub fn default_zn_scenario_builder() -> ScenarioBuilder { | ||
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) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
[settings] | ||
timeout = 1500 | ||
|
||
[relaychain] | ||
default_image = "parity/polkadot:latest" | ||
default_command = "polkadot" | ||
chain = "rococo-local" | ||
|
||
[[relaychain.nodes]] | ||
name = "alice" | ||
rpc_port = 9944 | ||
validator = true | ||
|
||
[[relaychain.nodes]] | ||
name = "bob" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should expose rpc port for bob too? I think we can also enabled Some scenarios sending to the relay-chain would nice. As discussed in element they can also be quicker for development (no need to wait for 10 blocks). |
||
validator = true | ||
|
||
[[parachains]] | ||
id = 2000 | ||
chain = "asset-hub-rococo-local" | ||
default_command = "polkadot-parachain" | ||
default_image = "parity/polkadot-parachain:latest" | ||
cumulus_based = true | ||
default_args = [ | ||
"--force-authoring", | ||
"--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", | ||
"-laura::cumulus=debug", | ||
"-lbasic-authorship=debug", | ||
"-lpeerset=trace", | ||
"-lsub-libp2p=debug", | ||
"-lsync=trace", | ||
"-ltxpool=trace", | ||
] | ||
[parachains.genesis.runtimeGenesis.patch.balances] | ||
devAccounts = [ | ||
iulianbarbu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
100, | ||
1000000000000000000, | ||
"//Sender//{}", | ||
] | ||
|
||
[[parachains.collators]] | ||
name = "charlie" | ||
validator = false | ||
rpc_port = 9933 | ||
|
||
[[parachains.collators]] | ||
name = "dave" | ||
validator = true | ||
rpc_port = 9934 | ||
|
||
[[parachains.collators]] | ||
name = "eve" | ||
validator = true | ||
rpc_port = 9935 | ||
|
||
[[parachains.collators]] | ||
name = "ferdie" | ||
validator = true | ||
rpc_port = 9936 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
[relaychain] | ||
default_image = "parity/polkadot:latest" | ||
default_command = "polkadot" | ||
chain = "rococo-local" | ||
|
||
[[relaychain.nodes]] | ||
name = "alice" | ||
rpc_port = 9944 | ||
validator = true | ||
|
||
[[relaychain.nodes]] | ||
name = "bob" | ||
validator = true | ||
|
||
[[parachains]] | ||
id = 2000 | ||
cumulus_based = true | ||
chain = "asset-hub-rococo-local" | ||
default_image = "parity/polkadot-parachain:latest" | ||
default_command = "polkadot-parachain" | ||
default_args = [ | ||
"--force-authoring", | ||
"--pool-kbytes 2048000", | ||
"--pool-limit 500000", | ||
"--rpc-max-connections 15000", | ||
"--rpc-max-response-size 150", | ||
"--rpc-max-subscriptions-per-connection=128000", | ||
"--state-pruning=1024", | ||
"-laura::cumulus=debug", | ||
"-lbasic-authorship=info", | ||
"-lpeerset=trace", | ||
"-lsub-libp2p=debug", | ||
"-lsync=trace", | ||
"-ltxpool=debug", | ||
] | ||
[parachains.genesis.runtimeGenesis.patch.balances] | ||
devAccounts = [ | ||
100, | ||
1000000000000000000, | ||
"//Sender//{}", | ||
|
||
] | ||
|
||
# run charlie as parachain collator | ||
[[parachains.collators]] | ||
name = "charlie" | ||
validator = false | ||
rpc_port = 9933 | ||
|
||
[[parachains.collators]] | ||
name = "dave" | ||
validator = true | ||
rpc_port = 9934 | ||
|
||
[[parachains.collators]] | ||
name = "eve" | ||
validator = true | ||
rpc_port = 9935 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we shall wait for block with number 1, otherwise we'll exit the loop on genesis hash.