Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Allow to benchmark HRMP messages from the undying collator #6261

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
Another reorg of the options
  • Loading branch information
vstakhov committed Mar 28, 2023
commit f9119473f293092adaa373f9bf7c2d8f9fb98b52
2 changes: 2 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions parachain/test-parachains/undying/collator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ clap = { version = "4.0.9", features = ["derive"] }
futures = "0.3.19"
futures-timer = "3.0.2"
log = "0.4.17"
thiserror = "1.0.31"
strum = { version = "0.24", features = ["derive"] }

test-parachain-undying = { path = ".." }
polkadot-primitives = { path = "../../../../primitives" }
Expand Down
53 changes: 48 additions & 5 deletions parachain/test-parachains/undying/collator/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,55 @@

use clap::Parser;
use sc_cli::{RuntimeVersion, SubstrateCli};
use std::str::FromStr;
use test_parachain_undying::HrmpChannelConfiguration;

/// Utility enum for parse HRMP config from a string
#[derive(Clone, Copy, Debug, strum::Display, thiserror::Error)]
pub enum HrmpConfigParseError {
IntParseError,
MissingDestination,
MissingMessageSize,
MissingMessagesCount,
TooManyParams,
}

#[derive(Debug)]
pub struct CliHrmpChannelConfiguration(pub HrmpChannelConfiguration);
sandreim marked this conversation as resolved.
Show resolved Hide resolved

/// This implementation is used to parse HRMP channels configuration from a command
/// line. This should be two numbers separated by `:`, where a first number is the
/// target parachain id and the second number is the message size in bytes.
/// For example, a configuration of `2:100` will send 100 bytes of data to the
/// parachain id 2 on each block. The HRMP channel must be configured in the genesis
/// block to be able to use this parameter.
impl FromStr for CliHrmpChannelConfiguration {
type Err = HrmpConfigParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let split_str: Vec<&str> = s.split(':').collect();
match split_str.len() {
0 => return Err(HrmpConfigParseError::MissingDestination),
1 => return Err(HrmpConfigParseError::MissingMessageSize),
2 => return Err(HrmpConfigParseError::MissingMessagesCount),
3 => {},
_ => return Err(HrmpConfigParseError::TooManyParams),
}
let destination_para_id =
split_str[0].parse::<u32>().map_err(|_| HrmpConfigParseError::IntParseError)?;
let message_size =
split_str[1].parse::<u32>().map_err(|_| HrmpConfigParseError::IntParseError)?;
let messages_count =
split_str[2].parse::<u32>().map_err(|_| HrmpConfigParseError::IntParseError)?;

Ok(CliHrmpChannelConfiguration(HrmpChannelConfiguration {
destination_para_id,
message_size,
messages_count,
}))
}
}

/// Sub-commands supported by the collator.
#[derive(Debug, Parser)]
pub enum Subcommand {
Expand Down Expand Up @@ -50,10 +97,6 @@ pub struct ExportGenesisStateCommand {
/// we compute per block.
#[arg(long, default_value_t = 1)]
pub pvf_complexity: u32,

/// Configuration of the hrmp channels
#[clap(long)]
pub hrmp_params: Vec<HrmpChannelConfiguration>,
}

/// Command for exporting the genesis wasm file.
Expand Down Expand Up @@ -83,7 +126,7 @@ pub struct RunCmd {

/// Configuration of the hrmp channels
#[clap(long)]
pub hrmp_params: Vec<HrmpChannelConfiguration>,
pub hrmp_params: Vec<CliHrmpChannelConfiguration>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think sending messages should be optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is optional, e.g. no messages are sent when a vector is empty.

}

#[allow(missing_docs)]
Expand Down
36 changes: 24 additions & 12 deletions parachain/test-parachains/undying/collator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use std::{
time::Duration,
};
use test_parachain_undying::{
execute, hash_state, BlockData, GraveyardState, HeadData, HrmpChannelConfiguration,
execute, hash_state, BlockData, GraveyardState, HeadData, HrmpChannelConfiguration, LOG_TARGET,
};

pub mod relay_chain;
Expand Down Expand Up @@ -65,7 +65,10 @@ fn calculate_head_and_state_for_number(
*grave = i as u8;
});

log::debug!(target: LOG_TARGET, "received messages from {} parachains", inbound_messages.len());
let inbound_messages = inbound_messages.values().flatten().cloned().collect::<Vec<_>>();
log::debug!(target: LOG_TARGET, "received {} messages in total", inbound_messages.len());

let mut state = GraveyardState { index, graveyard, zombies, seal, inbound_messages };
let mut head =
HeadData { number: 0, parent_hash: Hash::default().into(), post_state: hash_state(&state) };
Expand Down Expand Up @@ -95,8 +98,6 @@ struct State {
// want that state to collate on older relay chain heads.
head_to_state: HashMap<Arc<HeadData>, GraveyardState>,
number_to_head: HashMap<u64, Arc<HeadData>>,
/// Stored inbound messages for the current state
current_inbound_messages: BTreeMap<ParaId, Vec<InboundHrmpMessage>>,
/// Block number of the best block.
best_block: u64,
/// PVF time complexity.
Expand Down Expand Up @@ -142,7 +143,6 @@ impl State {
pvf_complexity,
graveyard_size,
hrmp_channels,
current_inbound_messages: BTreeMap::new(),
}
}

Expand All @@ -156,7 +156,7 @@ impl State {
) -> (BlockData, HeadData, Vec<OutboundHrmpMessage<ParaId>>) {
self.best_block = parent_head.number;

let state = if let Some(head_data) = self.number_to_head.get(&self.best_block) {
let mut state = if let Some(head_data) = self.number_to_head.get(&self.best_block) {
self.head_to_state.get(head_data).cloned().unwrap_or_else(|| {
calculate_head_and_state_for_number(
parent_head.number,
Expand All @@ -178,6 +178,14 @@ impl State {
state
};

log::debug!(
target: LOG_TARGET,
"received messages from {} parachains",
inbound_messages.len()
);
let inbound_messages = inbound_messages.values().flatten().cloned().collect::<Vec<_>>();
log::debug!(target: LOG_TARGET, "received {} messages in total", inbound_messages.len());
state.inbound_messages = inbound_messages;
// Start with prev state and transaction to execute (place 1000 tombstones).
let block = BlockData {
state,
Expand Down Expand Up @@ -299,25 +307,29 @@ impl Collator {
.await
.unwrap_or_else(|_| BTreeMap::new());

let (block_data, head_data, messages) =
state.lock().unwrap().advance(parent, inbound_messages);
let messages_count: usize =
inbound_messages.values().map(|msg_vec| msg_vec.len()).sum();

let (block_data, head_data, outbound_messages) =
state.lock().unwrap().advance(parent, inbound_messages);
log::info!(
"created a new collation on relay-parent({}): {:?}",
"created a new collation on relay-parent({}): {:?}; {} messages received, {} messages sent",
relay_parent,
head_data,
messages_count,
outbound_messages.len()
);

// The pov is the actually the initial state and the transactions.
let pov = PoV { block_data: block_data.encode().into() };

let collation = Collation {
upward_messages: Default::default(),
horizontal_messages: messages,
horizontal_messages: outbound_messages.try_into().expect("bound for the vector must be higher than number of messages",
new_validation_code: None,
head_data: head_data.encode().into(),
proof_of_validity: MaybeCompressedPoV::Raw(pov.clone()),
processed_downward_messages: 0,
processed_downward_messages: messages_count as u32,
hrmp_watermark: relay_parent_number,
};

Expand Down Expand Up @@ -367,7 +379,7 @@ impl Collator {
let current_block = self.state.lock().unwrap().best_block;

if start_block + blocks <= current_block {
return;
return
}
}
}
Expand All @@ -382,7 +394,7 @@ impl Collator {
Delay::new(Duration::from_secs(1)).await;

if seconded <= seconded_collations.load(Ordering::Relaxed) {
return;
return
}
}
}
Expand Down
10 changes: 3 additions & 7 deletions parachain/test-parachains/undying/collator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,8 @@ fn main() -> Result<()> {
Some(cli::Subcommand::ExportGenesisState(params)) => {
// `pov_size` and `pvf_complexity` need to match the ones that we start the collator
// with.
let collator = Collator::new(
params.pov_size,
params.pvf_complexity,
params.hrmp_params,
params.parachain_id,
);
let collator =
Collator::new(params.pov_size, params.pvf_complexity, vec![], params.parachain_id);
println!("0x{:?}", HexDisplay::from(&collator.genesis_head()));

Ok::<_, Error>(())
Expand All @@ -63,7 +59,7 @@ fn main() -> Result<()> {
let collator = Collator::new(
cli.run.pov_size,
cli.run.pvf_complexity,
cli.run.hrmp_params,
cli.run.hrmp_params.into_iter().map(|cli_param| cli_param.0).collect(),
cli.run.parachain_id,
);

Expand Down
41 changes: 1 addition & 40 deletions parachain/test-parachains/undying/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ mod wasm_validation;
#[cfg(not(feature = "std"))]
#[global_allocator]
static ALLOC: dlmalloc::GlobalDlmalloc = dlmalloc::GlobalDlmalloc;
const LOG_TARGET: &str = "runtime::undying";
pub const LOG_TARGET: &str = "runtime::undying";

// Make the WASM binary available.
#[cfg(feature = "std")]
Expand Down Expand Up @@ -105,45 +105,6 @@ pub struct HrmpChannelConfiguration {
pub messages_count: u32,
}

/// Utility enum for parse HRMP config from a string
#[derive(Clone, Copy, Debug)]
pub enum HrmpConfigParseError {
IntParseError,
MissingDestination,
MissingMessageSize,
MissingMessagesCount,
TooManyParams,
}

/// This implementation is used to parse HRMP channels configuration from a command
/// line. This should be two numbers separated by `:`, where a first number is the
/// target parachain id and the second number is the message size in bytes.
/// For example, a configuration of `2:100` will send 100 bytes of data to the
/// parachain id 2 on each block. The HRMP channel must be configured in the genesis
/// block to be able to use this parameter.
impl FromStr for HrmpChannelConfiguration {
type Err = HrmpConfigParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let split_str: Vec<&str> = s.split(':').collect();
match split_str.len() {
0 => return Err(HrmpConfigParseError::MissingDestination),
1 => return Err(HrmpConfigParseError::MissingMessageSize),
2 => return Err(HrmpConfigParseError::MissingMessagesCount),
3 => {},
_ => return Err(HrmpConfigParseError::TooManyParams),
}
let destination_para_id =
split_str[0].parse::<u32>().map_err(|_| HrmpConfigParseError::IntParseError)?;
let message_size =
split_str[1].parse::<u32>().map_err(|_| HrmpConfigParseError::IntParseError)?;
let messages_count =
split_str[2].parse::<u32>().map_err(|_| HrmpConfigParseError::IntParseError)?;

Ok(HrmpChannelConfiguration { destination_para_id, message_size, messages_count })
}
}

/// Block data for this parachain.
#[derive(Default, Clone, Encode, Decode, Debug)]
pub struct BlockData {
Expand Down