Files
pezkuwi-sdk/pezkuwi/cli/src/command.rs
T
pezkuwichain 379cb741ed feat: Rebrand Polkadot/Substrate references to PezkuwiChain
This commit systematically rebrands various references from Parity Technologies'
Polkadot/Substrate ecosystem to PezkuwiChain within the kurdistan-sdk.

Key changes include:
- Updated external repository URLs (zombienet-sdk, parity-db, parity-scale-codec, wasm-instrument) to point to pezkuwichain forks.
- Modified internal documentation and code comments to reflect PezkuwiChain naming and structure.
- Replaced direct references to  with  or specific paths within the  for XCM, Pezkuwi, and other modules.
- Cleaned up deprecated  issue and PR references in various  and  files, particularly in  and  modules.
- Adjusted image and logo URLs in documentation to point to PezkuwiChain assets.
- Removed or rephrased comments related to external Polkadot/Substrate PRs and issues.

This is a significant step towards fully customizing the SDK for the PezkuwiChain ecosystem.
2025-12-14 00:04:10 +03:00

537 lines
19 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// Pezkuwi 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.
// Pezkuwi 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 Pezkuwi. If not, see <http://www.gnu.org/licenses/>.
use crate::cli::{Cli, Subcommand, NODE_VERSION};
use pezframe_benchmarking_cli::{
BenchmarkCmd, ExtrinsicFactory, BizinikiwiRemarkBuilder, BIZINIKIWI_REFERENCE_HARDWARE,
};
use futures::future::TryFutureExt;
use log::{info, warn};
use pezkuwi_service::{
self,
benchmarking::{benchmark_inherent_data, TransferKeepAliveBuilder},
HeaderBackend, IdentifyVariant,
};
#[cfg(feature = "pyroscope")]
use pyroscope_pprofrs::{pprof_backend, PprofConfig};
use pezsc_cli::BizinikiwiCli;
use pezsc_network_types::PeerId;
use pezsp_core::crypto::Ss58AddressFormatRegistry;
use pezsp_keyring::Sr25519Keyring;
pub use crate::error::Error;
#[cfg(feature = "pyroscope")]
use std::net::ToSocketAddrs;
use std::{collections::HashSet, time::Duration};
type Result<T> = std::result::Result<T, Error>;
fn get_exec_name() -> Option<String> {
std::env::current_exe()
.ok()
.and_then(|pb| pb.file_name().map(|s| s.to_os_string()))
.and_then(|s| s.into_string().ok())
}
fn get_invulnerable_ah_collators(
chain_spec: &Box<dyn pezkuwi_service::ChainSpec>,
) -> HashSet<PeerId> {
// A default set of invulnerable asset hub collators
const KUSAMA: [&str; 11] = [
"12D3KooWHNEENyCc4R3iDLLFaJiynUp9eDZp7TtS1G6DCp459vVK",
"12D3KooWAVqLdQEjSezy7CPEgMLMSTuyfSBdbxPGkmik5x2aL8u4",
"12D3KooWBxMiVQdYa5MaQjSWAu3YsfKdrs7vgX9cPk4cCwFVAXEu",
"12D3KooWGbRmQ9FjwkzTVTSxfUh854wxc3LUD5agjzcucDarZrNn",
"12D3KooWHwXftCGdp73t4BUxW3c9UKjYTvjc7tHsrinT5M8AUmXo",
"12D3KooWCTSAq83D99RcT64rrV5X3sGZxc9JQ8nVtd6GbZEKnDqC",
"12D3KooWF63ZxKtZMYs5247WQA8fcTiGJb2osXykc31cmjwNLwem",
"12D3KooWGowDwrXAh9cxkbPHPHuwMouFHrMcJhCVXcFS2B8vc5Ry",
"12D3KooWRhoxXsZypnp1Tady6XSRqXfxu7Bj6hGk8aj6FJ1iU6pt",
"12D3KooWJUs11H7S3Hv9BVh72w3yVmHoYTXaoBUg1KQyYk4hL2bB",
"12D3KooWAeLjabo2foz6gAQvLRfwF2d3WnpUGDjhg8V5AQUnv5AZ",
];
const PEZKUWI: [&str; 7] = [
"12D3KooWEyGg3oUwYfaLWM5AJ2pvXCUxBuXNapX1tQXLsbDmMV6z",
"12D3KooWD9dTKLW65NFFLVjqgaXNzb3zKXBfwRS5iovxV6XaoVX6",
"12D3KooWPJfGGisRMkiD5yhySZggEhyMSwELb34P2bEuAmUh9RYy",
"12D3KooWQB9RBoJEByMtXtD8aC1WR1DJQb3QMXRcsQmNxrghsQLv",
"12D3KooWFhBYG98e53DQB7W2JKBL9xWrP83ANkAjzvp4enEJAt3k",
"12D3KooWG3GrM6XKMM4gp3cvemdwUvu96ziYoJmqmetLZBXE8bSa",
"12D3KooWMRyTLrCEPcAQD6c4EnudL3vVzg9zji3whvsMYPUYevpq",
];
let invulnerables = if chain_spec.is_kusama() {
KUSAMA.to_vec()
} else if chain_spec.is_pezkuwi() {
PEZKUWI.to_vec()
} else {
vec![]
};
invulnerables
.iter()
.filter_map(|invuln_str| {
invuln_str
.parse::<PeerId>()
.map_err(|e| {
warn!("Failed to parse AssetHub invulnerable peer from the default list. This should never happen. {:?}", e)
})
.ok()
})
.collect()
}
impl BizinikiwiCli for Cli {
fn impl_name() -> String {
"Parity Pezkuwi".into()
}
fn impl_version() -> String {
let commit_hash = env!("BIZINIKIWI_CLI_COMMIT_HASH");
format!("{}-{commit_hash}", NODE_VERSION)
}
fn description() -> String {
env!("CARGO_PKG_DESCRIPTION").into()
}
fn author() -> String {
env!("CARGO_PKG_AUTHORS").into()
}
fn support_url() -> String {
"https://github.com/pezkuwichain/pezkuwi-sdk/issues/new".into()
}
fn copyright_start_year() -> i32 {
2017
}
fn executable_name() -> String {
"pezkuwi".into()
}
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn pezsc_service::ChainSpec>, String> {
let id = if id == "" {
let n = get_exec_name().unwrap_or_default();
["pezkuwi", "kusama", "zagros", "pezkuwichain", "versi"]
.iter()
.cloned()
.find(|&chain| n.starts_with(chain))
.unwrap_or("pezkuwi")
} else {
id
};
Ok(match id {
"kusama" => Box::new(pezkuwi_service::chain_spec::kusama_config()?),
name if name.starts_with("kusama-") && !name.ends_with(".json") =>
Err(format!("`{name}` is not supported anymore as the kusama native runtime no longer part of the node."))?,
"pezkuwi" => Box::new(pezkuwi_service::chain_spec::pezkuwi_config()?),
name if name.starts_with("pezkuwi-") && !name.ends_with(".json") =>
Err(format!("`{name}` is not supported anymore as the pezkuwi native runtime no longer part of the node."))?,
"paseo" => Box::new(pezkuwi_service::chain_spec::paseo_config()?),
"pezkuwichain" => Box::new(pezkuwi_service::chain_spec::pezkuwichain_config()?),
#[cfg(feature = "pezkuwichain-native")]
"dev" | "pezkuwichain-dev" => Box::new(pezkuwi_service::chain_spec::pezkuwichain_development_config()?),
#[cfg(feature = "pezkuwichain-native")]
"pezkuwichain-local" => Box::new(pezkuwi_service::chain_spec::pezkuwichain_local_testnet_config()?),
#[cfg(feature = "pezkuwichain-native")]
"pezkuwichain-staging" => Box::new(pezkuwi_service::chain_spec::pezkuwichain_staging_testnet_config()?),
#[cfg(not(feature = "pezkuwichain-native"))]
name if name.starts_with("pezkuwichain-") && !name.ends_with(".json") || name == "dev" =>
Err(format!("`{}` only supported with `pezkuwichain-native` feature enabled.", name))?,
"zagros" => Box::new(pezkuwi_service::chain_spec::zagros_config()?),
#[cfg(feature = "zagros-native")]
"zagros-dev" => Box::new(pezkuwi_service::chain_spec::zagros_development_config()?),
#[cfg(feature = "zagros-native")]
"zagros-local" => Box::new(pezkuwi_service::chain_spec::zagros_local_testnet_config()?),
#[cfg(feature = "zagros-native")]
"zagros-staging" => Box::new(pezkuwi_service::chain_spec::zagros_staging_testnet_config()?),
#[cfg(feature = "pezkuwichain-native")]
"versi-dev" => Box::new(pezkuwi_service::chain_spec::versi_development_config()?),
#[cfg(feature = "pezkuwichain-native")]
"versi-local" => Box::new(pezkuwi_service::chain_spec::versi_local_testnet_config()?),
#[cfg(feature = "pezkuwichain-native")]
"versi-staging" => Box::new(pezkuwi_service::chain_spec::versi_staging_testnet_config()?),
#[cfg(not(feature = "pezkuwichain-native"))]
name if name.starts_with("versi-") =>
Err(format!("`{}` only supported with `pezkuwichain-native` feature enabled.", name))?,
path => {
let path = std::path::PathBuf::from(path);
let chain_spec = Box::new(pezkuwi_service::GenericChainSpec::from_json_file(path.clone())?)
as Box<dyn pezkuwi_service::ChainSpec>;
// When `force_*` is given or the file name starts with the name of one of the known
// chains, we use the chain spec for the specific chain.
if self.run.force_pezkuwichain ||
chain_spec.is_pezkuwichain() ||
chain_spec.is_versi()
{
Box::new(pezkuwi_service::PezkuwichainChainSpec::from_json_file(path)?)
} else if self.run.force_kusama || chain_spec.is_kusama() {
Box::new(pezkuwi_service::GenericChainSpec::from_json_file(path)?)
} else if self.run.force_zagros || chain_spec.is_zagros() {
Box::new(pezkuwi_service::ZagrosChainSpec::from_json_file(path)?)
} else {
chain_spec
}
},
})
}
}
fn set_default_ss58_version(spec: &Box<dyn pezkuwi_service::ChainSpec>) {
let ss58_version = if spec.is_kusama() {
Ss58AddressFormatRegistry::KusamaAccount
} else if spec.is_zagros() {
Ss58AddressFormatRegistry::BizinikiwiAccount
} else {
Ss58AddressFormatRegistry::PezkuwiAccount
}
.into();
pezsp_core::crypto::set_default_ss58_version(ss58_version);
}
/// Launch a node, accepting arguments just like a regular node,
/// accepts an alternative overseer generator, to adjust behavior
/// for integration tests as needed.
/// `malus_finality_delay` restrict finality votes of this node
/// to be at most `best_block - malus_finality_delay` height.
#[cfg(feature = "malus")]
pub fn run_node(
run: Cli,
overseer_gen: impl pezkuwi_service::OverseerGen,
malus_finality_delay: Option<u32>,
) -> Result<()> {
run_node_inner(run, overseer_gen, malus_finality_delay, |_logger_builder, _config| {})
}
fn run_node_inner<F>(
cli: Cli,
overseer_gen: impl pezkuwi_service::OverseerGen,
maybe_malus_finality_delay: Option<u32>,
logger_hook: F,
) -> Result<()>
where
F: FnOnce(&mut pezsc_cli::LoggerBuilder, &pezsc_service::Configuration),
{
let runner = cli
.create_runner_with_logger_hook::<_, _, F>(&cli.run.base, logger_hook)
.map_err(Error::from)?;
let chain_spec = &runner.config().chain_spec;
// By default, enable BEEFY on all networks, unless explicitly disabled through CLI.
let enable_beefy = !cli.run.no_beefy;
set_default_ss58_version(chain_spec);
if chain_spec.is_kusama() {
info!("----------------------------");
info!("This chain is not in any way");
info!(" endorsed by the ");
info!(" KUSAMA FOUNDATION ");
info!("----------------------------");
}
let node_version =
if cli.run.disable_worker_version_check { None } else { Some(NODE_VERSION.to_string()) };
let secure_validator_mode = cli.run.base.validator && !cli.run.insecure_validator;
// Parse collator protocol hold off value and get the list of the invlunerable collators.
let collator_protocol_hold_off = cli.run.collator_protocol_hold_off.map(Duration::from_millis);
let invulnerable_ah_collators = get_invulnerable_ah_collators(&chain_spec);
runner.run_node_until_exit(move |config| async move {
let hwbench = (!cli.run.no_hardware_benchmarks)
.then(|| {
config.database.path().map(|database_path| {
let _ = std::fs::create_dir_all(&database_path);
pezsc_sysinfo::gather_hwbench(Some(database_path), &BIZINIKIWI_REFERENCE_HARDWARE)
})
})
.flatten();
let database_source = config.database.clone();
let task_manager = pezkuwi_service::build_full(
config,
pezkuwi_service::NewFullParams {
is_teyrchain_node: pezkuwi_service::IsTeyrchainNode::No,
enable_beefy,
force_authoring_backoff: cli.run.force_authoring_backoff,
telemetry_worker_handle: None,
node_version,
secure_validator_mode,
workers_path: cli.run.workers_path,
workers_names: None,
overseer_gen,
overseer_message_channel_capacity_override: cli
.run
.overseer_channel_capacity_override,
malus_finality_delay: maybe_malus_finality_delay,
hwbench,
execute_workers_max_num: cli.run.execute_workers_max_num,
prepare_workers_hard_max_num: cli.run.prepare_workers_hard_max_num,
prepare_workers_soft_max_num: cli.run.prepare_workers_soft_max_num,
keep_finalized_for: cli.run.keep_finalized_for,
invulnerable_ah_collators,
collator_protocol_hold_off,
},
)
.map(|full| full.task_manager)?;
if let Some(path) = database_source.path() {
pezsc_storage_monitor::StorageMonitorService::try_spawn(
cli.storage_monitor,
path.to_path_buf(),
&task_manager.spawn_essential_handle(),
)?;
}
Ok(task_manager)
})
}
/// Parses pezkuwi specific CLI arguments and run the service.
pub fn run() -> Result<()> {
let cli: Cli = Cli::from_args();
#[cfg(feature = "pyroscope")]
let mut pyroscope_agent_maybe = if let Some(ref agent_addr) = cli.run.pyroscope_server {
let address = agent_addr
.to_socket_addrs()
.map_err(Error::AddressResolutionFailure)?
.next()
.ok_or_else(|| Error::AddressResolutionMissing)?;
// The pyroscope agent requires a `http://` prefix, so we just do that.
let agent = pyroscope::PyroscopeAgent::builder(
"http://".to_owned() + address.to_string().as_str(),
"pezkuwi".to_owned(),
)
.backend(pprof_backend(PprofConfig::new().sample_rate(113)))
.build()?;
Some(agent.start()?)
} else {
None
};
#[cfg(not(feature = "pyroscope"))]
if cli.run.pyroscope_server.is_some() {
return Err(Error::PyroscopeNotCompiledIn);
}
match &cli.subcommand {
None => run_node_inner(
cli,
pezkuwi_service::ValidatorOverseerGen,
None,
pezkuwi_node_metrics::logger_hook(),
),
#[allow(deprecated)]
Some(Subcommand::BuildSpec(cmd)) => {
let runner = cli.create_runner(cmd)?;
Ok(runner.sync_run(|config| cmd.run(config.chain_spec, config.network))?)
},
Some(Subcommand::ExportChainSpec(cmd)) => {
// Directly load the embedded chain spec using the CLIs load_spec method.
let spec = cli.load_spec(&cmd.chain)?;
cmd.run(spec).map_err(Into::into)
},
Some(Subcommand::CheckBlock(cmd)) => {
let runner = cli.create_runner(cmd).map_err(Error::BizinikiwiCli)?;
let chain_spec = &runner.config().chain_spec;
set_default_ss58_version(chain_spec);
runner.async_run(|mut config| {
let (client, _, import_queue, task_manager) =
pezkuwi_service::new_chain_ops(&mut config)?;
Ok((cmd.run(client, import_queue).map_err(Error::BizinikiwiCli), task_manager))
})
},
Some(Subcommand::ExportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
let chain_spec = &runner.config().chain_spec;
set_default_ss58_version(chain_spec);
Ok(runner.async_run(|mut config| {
let (client, _, _, task_manager) =
pezkuwi_service::new_chain_ops(&mut config).map_err(Error::PezkuwiService)?;
Ok((cmd.run(client, config.database).map_err(Error::BizinikiwiCli), task_manager))
})?)
},
Some(Subcommand::ExportState(cmd)) => {
let runner = cli.create_runner(cmd)?;
let chain_spec = &runner.config().chain_spec;
set_default_ss58_version(chain_spec);
Ok(runner.async_run(|mut config| {
let (client, _, _, task_manager) = pezkuwi_service::new_chain_ops(&mut config)?;
Ok((cmd.run(client, config.chain_spec).map_err(Error::BizinikiwiCli), task_manager))
})?)
},
Some(Subcommand::ImportBlocks(cmd)) => {
let runner = cli.create_runner(cmd)?;
let chain_spec = &runner.config().chain_spec;
set_default_ss58_version(chain_spec);
Ok(runner.async_run(|mut config| {
let (client, _, import_queue, task_manager) =
pezkuwi_service::new_chain_ops(&mut config)?;
Ok((cmd.run(client, import_queue).map_err(Error::BizinikiwiCli), task_manager))
})?)
},
Some(Subcommand::PurgeChain(cmd)) => {
let runner = cli.create_runner(cmd)?;
Ok(runner.sync_run(|config| cmd.run(config.database))?)
},
Some(Subcommand::Revert(cmd)) => {
let runner = cli.create_runner(cmd)?;
let chain_spec = &runner.config().chain_spec;
set_default_ss58_version(chain_spec);
Ok(runner.async_run(|mut config| {
let (client, backend, _, task_manager) =
pezkuwi_service::new_chain_ops(&mut config)?;
let task_handle = task_manager.spawn_handle();
let aux_revert = Box::new(|client, backend, blocks| {
pezkuwi_service::revert_backend(client, backend, blocks, config, task_handle)
.map_err(|err| {
match err {
pezkuwi_service::Error::Blockchain(err) => err.into(),
// Generic application-specific error.
err => pezsc_cli::Error::Application(err.into()),
}
})
});
Ok((
cmd.run(client, backend, Some(aux_revert)).map_err(Error::BizinikiwiCli),
task_manager,
))
})?)
},
Some(Subcommand::Benchmark(cmd)) => {
let runner = cli.create_runner(cmd)?;
let chain_spec = &runner.config().chain_spec;
match cmd {
#[cfg(not(feature = "runtime-benchmarks"))]
BenchmarkCmd::Storage(_) =>
return Err(pezsc_cli::Error::Input(
"Compile with --features=runtime-benchmarks \
to enable storage benchmarks."
.into(),
)
.into()),
#[cfg(feature = "runtime-benchmarks")]
BenchmarkCmd::Storage(cmd) => runner.sync_run(|mut config| {
let (client, backend, _, _) = pezkuwi_service::new_chain_ops(&mut config)?;
let db = backend.expose_db();
let storage = backend.expose_storage();
let shared_trie_cache = backend.expose_shared_trie_cache();
cmd.run(config, client.clone(), db, storage, shared_trie_cache).map_err(Error::BizinikiwiCli)
}),
BenchmarkCmd::Block(cmd) => runner.sync_run(|mut config| {
let (client, _, _, _) = pezkuwi_service::new_chain_ops(&mut config)?;
cmd.run(client.clone()).map_err(Error::BizinikiwiCli)
}),
BenchmarkCmd::Overhead(cmd) => runner.sync_run(|config| {
if cmd.params.runtime.is_some() {
return Err(pezsc_cli::Error::Input(
"Pezkuwi binary does not support `--runtime` flag for `benchmark overhead`. Please provide a chain spec or use the `frame-omni-bencher`."
.into(),
)
.into())
}
cmd.run_with_default_builder_and_spec::<pezkuwi_service::Block, ()>(
Some(config.chain_spec),
)
.map_err(Error::BizinikiwiCli)
}),
BenchmarkCmd::Extrinsic(cmd) => runner.sync_run(|mut config| {
let (client, _, _, _) = pezkuwi_service::new_chain_ops(&mut config)?;
let header = client.header(client.info().genesis_hash).unwrap().unwrap();
let inherent_data = benchmark_inherent_data(header)
.map_err(|e| format!("generating inherent data: {:?}", e))?;
let remark_builder = BizinikiwiRemarkBuilder::new_from_client(client.clone())?;
let tka_builder = TransferKeepAliveBuilder::new(
client.clone(),
Sr25519Keyring::Alice.to_account_id(),
config.chain_spec.identify_chain(),
);
let ext_factory =
ExtrinsicFactory(vec![Box::new(remark_builder), Box::new(tka_builder)]);
cmd.run(client.clone(), inherent_data, Vec::new(), &ext_factory)
.map_err(Error::BizinikiwiCli)
}),
BenchmarkCmd::Pallet(cmd) => {
set_default_ss58_version(chain_spec);
if cfg!(feature = "runtime-benchmarks") {
runner.sync_run(|config| {
cmd.run_with_spec::<pezsp_runtime::traits::HashingFor<pezkuwi_service::Block>, ()>(
Some(config.chain_spec),
)
.map_err(|e| Error::BizinikiwiCli(e))
})
} else {
Err(pezsc_cli::Error::Input(
"Benchmarking wasn't enabled when building the node. \
You can enable it with `--features runtime-benchmarks`."
.into(),
)
.into())
}
},
BenchmarkCmd::Machine(cmd) => runner.sync_run(|config| {
cmd.run(&config, BIZINIKIWI_REFERENCE_HARDWARE.clone())
.map_err(Error::BizinikiwiCli)
}),
// NOTE: this allows the Pezkuwi client to leniently implement
// new benchmark commands.
#[allow(unreachable_patterns)]
_ => Err(Error::CommandNotImplemented),
}
},
Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?),
Some(Subcommand::ChainInfo(cmd)) => {
let runner = cli.create_runner(cmd)?;
Ok(runner.sync_run(|config| cmd.run::<pezkuwi_service::Block>(&config))?)
},
}?;
#[cfg(feature = "pyroscope")]
if let Some(pyroscope_agent) = pyroscope_agent_maybe.take() {
let agent = pyroscope_agent.stop()?;
agent.shutdown();
}
Ok(())
}