mithril_aggregator/commands/
era_command.rs

1use std::{collections::HashMap, fs::File, io::Write, path::PathBuf};
2
3use anyhow::Context;
4use clap::{Parser, Subcommand};
5use mithril_common::{
6    StdResult,
7    crypto_helper::{EraMarkersSigner, EraMarkersVerifierSecretKey},
8    entities::{Epoch, HexEncodedEraMarkersSecretKey},
9};
10use mithril_doc::StructDoc;
11use slog::{Logger, debug};
12
13use crate::{extract_all, tools::EraTools};
14
15/// Era tools
16#[derive(Parser, Debug, Clone)]
17pub struct EraCommand {
18    /// commands
19    #[clap(subcommand)]
20    pub era_subcommand: EraSubCommand,
21}
22
23impl EraCommand {
24    pub async fn execute(&self, root_logger: Logger) -> StdResult<()> {
25        self.era_subcommand.execute(root_logger).await
26    }
27
28    pub fn extract_config(command_path: String) -> HashMap<String, StructDoc> {
29        extract_all!(
30            command_path,
31            EraSubCommand,
32            List = { ListEraSubCommand },
33            GenerateTxDatum = { GenerateTxDatumEraSubCommand },
34            GenerateKeypair = { GenerateKeypairEraSubCommand },
35        )
36    }
37}
38
39/// Era tools commands.
40#[derive(Debug, Clone, Subcommand)]
41pub enum EraSubCommand {
42    /// Era list command.
43    List(ListEraSubCommand),
44
45    /// Era tx datum generate command.
46    GenerateTxDatum(GenerateTxDatumEraSubCommand),
47
48    /// Era keypair generation command.
49    GenerateKeypair(GenerateKeypairEraSubCommand),
50}
51
52impl EraSubCommand {
53    pub async fn execute(&self, root_logger: Logger) -> StdResult<()> {
54        match self {
55            Self::List(cmd) => cmd.execute(root_logger).await,
56            Self::GenerateTxDatum(cmd) => cmd.execute(root_logger).await,
57            Self::GenerateKeypair(cmd) => cmd.execute(root_logger).await,
58        }
59    }
60}
61
62/// Era list command
63#[derive(Parser, Debug, Clone)]
64pub struct ListEraSubCommand {
65    /// Enable JSON output.
66    #[clap(long)]
67    json: bool,
68}
69
70impl ListEraSubCommand {
71    pub async fn execute(&self, root_logger: Logger) -> StdResult<()> {
72        debug!(root_logger, "LIST ERA command");
73        let era_tools = EraTools::new();
74        let eras = era_tools.get_supported_eras_list()?;
75
76        if self.json {
77            println!("{}", serde_json::to_string(&eras)?);
78        } else {
79            println!("Supported Eras:");
80            println!("{eras:#?}");
81        }
82
83        Ok(())
84    }
85
86    pub fn extract_config(_parent: String) -> HashMap<String, StructDoc> {
87        HashMap::new()
88    }
89}
90
91/// Era tx datum generate command
92#[derive(Parser, Debug, Clone)]
93pub struct GenerateTxDatumEraSubCommand {
94    /// Current Era epoch
95    #[clap(long, env = "CURRENT_ERA_EPOCH")]
96    current_era_epoch: u64,
97
98    /// Next Era epoch start, if exists
99    #[clap(long, env = "NEXT_ERA_EPOCH")]
100    next_era_epoch: Option<u64>,
101
102    /// Era Markers Secret Key
103    #[clap(long, env = "ERA_MARKERS_SECRET_KEY")]
104    era_markers_secret_key: HexEncodedEraMarkersSecretKey,
105
106    /// Target path
107    #[clap(long)]
108    target_path: PathBuf,
109}
110
111impl GenerateTxDatumEraSubCommand {
112    pub async fn execute(&self, root_logger: Logger) -> StdResult<()> {
113        debug!(root_logger, "GENERATETXDATUM ERA command");
114        let era_tools = EraTools::new();
115
116        let era_markers_secret_key =
117            EraMarkersVerifierSecretKey::from_json_hex(&self.era_markers_secret_key)
118                .with_context(|| "json hex decode of era markers secret key failure")?;
119        let era_markers_signer = EraMarkersSigner::from_secret_key(era_markers_secret_key);
120        let tx_datum = era_tools.generate_tx_datum(
121            Epoch(self.current_era_epoch),
122            self.next_era_epoch.map(Epoch),
123            &era_markers_signer,
124        )?;
125
126        let mut target_file = File::create(&self.target_path)?;
127        target_file.write_all(tx_datum.as_bytes())?;
128
129        Ok(())
130    }
131
132    pub fn extract_config(_parent: String) -> HashMap<String, StructDoc> {
133        HashMap::new()
134    }
135}
136
137/// Era keypair generation command.
138#[derive(Parser, Debug, Clone)]
139pub struct GenerateKeypairEraSubCommand {
140    /// Target path for the generated keypair
141    #[clap(long)]
142    target_path: PathBuf,
143}
144
145impl GenerateKeypairEraSubCommand {
146    pub async fn execute(&self, root_logger: Logger) -> StdResult<()> {
147        debug!(root_logger, "GENERATE KEYPAIR ERA command");
148        println!(
149            "Era generate keypair to {}",
150            self.target_path.to_string_lossy()
151        );
152
153        EraTools::create_and_save_era_keypair(&self.target_path)
154            .with_context(|| "era-tools: keypair generation error")?;
155
156        Ok(())
157    }
158
159    pub fn extract_config(_parent: String) -> HashMap<String, StructDoc> {
160        HashMap::new()
161    }
162}