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