partner_chains_node_commands/
lib.rs1#![deny(missing_docs)]
5use authority_selection_inherents::{
6 AuthoritySelectionDataSource, AuthoritySelectionInputs, CandidateValidationApi,
7};
8use clap::Parser;
9use cli_commands::address_association_signatures::AddressAssociationSignaturesCmd;
10use cli_commands::block_producer_metadata_signatures::BlockProducerMetadataSignatureCmd;
11use cli_commands::registration_signatures::RegistrationSignaturesCmd;
12use frame_support::sp_runtime::traits::NumberFor;
13use parity_scale_codec::{Decode, Encode};
14use partner_chains_cli::DefaultCmdRunContext;
15pub use partner_chains_cli::PartnerChainRuntime;
16use partner_chains_smart_contracts_commands::SmartContractsCmd;
17use sc_cli::{CliConfiguration, SharedParams, SubstrateCli};
18use sc_service::TaskManager;
19use sidechain_domain::*;
20use sp_api::ProvideRuntimeApi;
21use sp_blockchain::HeaderBackend;
22use sp_runtime::AccountId32;
23use sp_runtime::DeserializeOwned;
24use sp_runtime::Serialize;
25use sp_runtime::traits::Block as BlockT;
26use sp_session_validator_management::CommitteeMember as CommitteeMemberT;
27use sp_session_validator_management::SessionValidatorManagementApi;
28use sp_session_validator_management_query::SessionValidatorManagementQuery;
29use sp_session_validator_management_query::commands::*;
30#[allow(deprecated)]
31use sp_sidechain::{GetGenesisUtxo, GetSidechainStatus};
32use std::future::Future;
33use std::sync::Arc;
34
35#[derive(Debug, Clone, Parser)]
36pub struct AriadneParametersCmd {
38 #[arg(long)]
39 pub mc_epoch_number: McEpochNumber,
41 #[allow(missing_docs)]
42 #[clap(flatten)]
43 pub shared_params: SharedParams,
44}
45
46impl CliConfiguration for AriadneParametersCmd {
47 fn shared_params(&self) -> &SharedParams {
48 &self.shared_params
49 }
50}
51
52#[derive(Debug, Clone, Parser)]
53pub struct SidechainParamsCmd {
55 #[allow(missing_docs)]
56 #[clap(flatten)]
57 pub shared_params: SharedParams,
58}
59
60impl CliConfiguration for SidechainParamsCmd {
61 fn shared_params(&self) -> &SharedParams {
62 &self.shared_params
63 }
64}
65
66#[derive(Debug, Clone, Parser)]
67pub struct RegistrationStatusCmd {
69 #[arg(long)]
70 #[arg(long, alias = "mainchain-pub-key")]
71 pub stake_pool_pub_key: StakePoolPublicKey,
73 #[arg(long)]
74 pub mc_epoch_number: McEpochNumber,
76 #[allow(missing_docs)]
77 #[clap(flatten)]
78 pub shared_params: SharedParams,
79}
80
81impl CliConfiguration for RegistrationStatusCmd {
82 fn shared_params(&self) -> &SharedParams {
83 &self.shared_params
84 }
85}
86
87static REGISTRATION_STATUS_AFTER_HELP: once_cell::sync::Lazy<String> = once_cell::sync::Lazy::new(
88 || {
89 fn get_node_exe_name() -> Option<String> {
90 let exe_path = std::env::current_exe().ok()?;
91 let exe_name_osstr = exe_path.file_name()?.to_os_string();
92 Some(exe_name_osstr.to_str()?.to_string())
93 }
94 format!(
95 "Example: {} registration-status --stake-pool-pub-key 0x702b81ab2e86cf73a87062af1eb0da666d451976d9d91c63a119ed94e6a33dc0 --mc-epoch-number 586",
96 get_node_exe_name().unwrap_or("node-bin".to_string())
97 )
98 },
99);
100
101#[derive(Clone, Debug, clap::Subcommand)]
102#[allow(clippy::large_enum_variant)]
103pub enum PartnerChainsSubcommand<
105 RuntimeBindings: PartnerChainRuntime + Send + Sync,
106 PartnerchainAddress: Clone + Sync + Send + FromStrStdErr + 'static,
107> {
108 SidechainParams(SidechainParamsCmd),
111
112 #[clap(
117 after_help = &*REGISTRATION_STATUS_AFTER_HELP
118 )]
119 RegistrationStatus(RegistrationStatusCmd),
120
121 AriadneParameters(AriadneParametersCmd),
126
127 RegistrationSignatures(RegistrationSignaturesCmd),
129
130 SignAddressAssociation(AddressAssociationSignaturesCmd<PartnerchainAddress>),
132
133 #[command(subcommand)]
135 SignBlockProducerMetadata(BlockProducerMetadataSignatureCmd<AccountId32>),
136
137 #[command(subcommand)]
139 SmartContracts(SmartContractsCmd),
140
141 #[command(subcommand)]
143 Wizards(partner_chains_cli::Command<RuntimeBindings>),
144}
145
146#[allow(deprecated)]
147pub fn run<
149 Cli,
150 Block,
151 CommitteeMember,
152 Client,
153 BlockProducerMetadata,
154 RuntimeBindings: PartnerChainRuntime + Send + Sync,
155 PartnerchainAddress,
156>(
157 cli: &Cli,
158 get_deps: impl FnOnce(
159 sc_service::Configuration,
160 ) -> Result<
161 (Arc<Client>, TaskManager, Arc<dyn AuthoritySelectionDataSource + Send + Sync>),
162 sc_service::error::Error,
163 >,
164 cmd: PartnerChainsSubcommand<RuntimeBindings, PartnerchainAddress>,
165) -> sc_cli::Result<()>
166where
167 Cli: SubstrateCli,
168 Client: ProvideRuntimeApi<Block> + HeaderBackend<Block> + 'static,
169 Client::Api: GetGenesisUtxo<Block>
170 + GetSidechainStatus<Block>
171 + SessionValidatorManagementApi<
172 Block,
173 CommitteeMember,
174 AuthoritySelectionInputs,
175 ScEpochNumber,
176 > + CandidateValidationApi<Block>,
177 Block: BlockT,
178 NumberFor<Block>: From<u32> + Into<u32>,
179 CommitteeMember: CommitteeMemberT + Encode + Decode + Send + Sync + 'static,
180 CommitteeMember::AuthorityId: Decode + Encode + AsRef<[u8]> + Send + Sync + 'static,
181 CommitteeMember::AuthorityKeys: Decode + Encode,
182 BlockProducerMetadata: DeserializeOwned + Encode + Send + Sync,
183 PartnerchainAddress: Serialize + Clone + Sync + Send + FromStrStdErr + Encode + 'static,
184{
185 match cmd {
186 PartnerChainsSubcommand::SidechainParams(cmd) => {
187 let runner = cli.create_runner(&cmd)?;
188 runner.async_run(|config| {
189 let (client, task_manager, _) = get_deps(config)?;
190 Ok((print_result(cli_commands::get_genesis_utxo::execute(client)), task_manager))
191 })
192 },
193 PartnerChainsSubcommand::RegistrationStatus(cmd) => {
194 let runner = cli.create_runner(&cmd)?;
195 runner.async_run(move |config| {
196 let (client, task_manager, ds) = get_deps(config)?;
197 let query = SessionValidatorManagementQuery::new(client.clone(), ds.clone());
198 Ok((
199 print_result(cli_get_registration_status(
200 query,
201 cmd.mc_epoch_number,
202 cmd.stake_pool_pub_key.clone(),
203 )),
204 task_manager,
205 ))
206 })
207 },
208 PartnerChainsSubcommand::AriadneParameters(cmd) => {
209 let runner = cli.create_runner(&cmd)?;
210 runner.async_run(move |config| {
211 let (client, task_manager, ds) = get_deps(config)?;
212 let query = SessionValidatorManagementQuery::new(client.clone(), ds.clone());
213 Ok((
214 print_result(cli_get_ariadne_parameters(query, cmd.mc_epoch_number)),
215 task_manager,
216 ))
217 })
218 },
219 PartnerChainsSubcommand::RegistrationSignatures(cmd) => Ok(println!("{}", cmd.execute())),
220 PartnerChainsSubcommand::SignAddressAssociation(cmd) => {
221 cmd.execute().map_err(|e| sc_service::Error::Application(e.into()))?;
222 Ok(())
223 },
224 PartnerChainsSubcommand::SignBlockProducerMetadata(cmd) => {
225 cmd.execute::<BlockProducerMetadata>()
226 .map_err(|e| sc_service::Error::Application(e.into()))?;
227 Ok(())
228 },
229 PartnerChainsSubcommand::SmartContracts(cmd) => {
230 setup_log4rs()?;
231 Ok(cmd.execute_blocking()?)
232 },
233 PartnerChainsSubcommand::Wizards(cmd) => {
234 setup_log4rs()?;
235 Ok(cmd
236 .run(&DefaultCmdRunContext)
237 .map_err(|e| sc_cli::Error::Application(e.into()))?)
238 },
239 }
240}
241
242fn setup_log4rs() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
245 let stderr = log4rs::append::console::ConsoleAppender::builder()
246 .target(log4rs::append::console::Target::Stderr)
247 .build();
248 let ogmios_log = log4rs::append::file::FileAppender::builder().build("ogmios_client.log")?;
249
250 let log_config = log4rs::config::Config::builder()
251 .appender(log4rs::config::Appender::builder().build("stderr", Box::new(stderr)))
252 .appender(log4rs::config::Appender::builder().build("ogmios-log", Box::new(ogmios_log)))
253 .logger(
254 log4rs::config::Logger::builder()
255 .appender("ogmios-log")
256 .additive(false)
257 .build("ogmios_client::jsonrpsee", log::LevelFilter::Debug),
258 )
259 .build(log4rs::config::Root::builder().appender("stderr").build(log::LevelFilter::Info))?;
260
261 log4rs::init_config(log_config)?;
262
263 Ok(())
264}
265
266async fn print_result<FIn>(command_future: FIn) -> Result<(), sc_cli::Error>
267where
268 FIn: Future<Output = Result<String, String>>,
269{
270 let result = command_future.await.unwrap_or_else(|e| e);
271 println!("{}", result);
272 Ok(())
273}
274
275#[cfg(test)]
276mod tests {
277
278 async fn some_err() -> Result<String, String> {
279 Err("some err".to_string())
280 }
281
282 #[tokio::test]
283 async fn print_async_doesnt_fail_if_result_is_error() {
284 let result = super::print_result(some_err()).await;
285 assert!(result.is_ok());
286 }
287}