1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
use {
18
    node_common::{
19
        cli::{BuildSpecCmd, ExportChainSpecCmd},
20
        service::node_builder::Sealing,
21
    },
22
    std::path::PathBuf,
23
    tc_service_container_chain_spawner::cli::ContainerChainRunCmd,
24
};
25

            
26
/// Sub-commands supported by the collator.
27
#[derive(Debug, clap::Subcommand)]
28
#[allow(clippy::large_enum_variant)]
29
pub enum Subcommand {
30
    /// Build a chain specification.
31
    #[deprecated(
32
        note = "build-spec command will be removed after 1/04/2026. Use export-chain-spec command instead"
33
    )]
34
    BuildSpec(BuildSpecCmdCollator),
35

            
36
    /// Export the chain specification.
37
    ExportChainSpec(ExportChainSpecCmdCollator),
38

            
39
    /// Validate blocks.
40
    CheckBlock(sc_cli::CheckBlockCmd),
41

            
42
    /// Export blocks.
43
    ExportBlocks(sc_cli::ExportBlocksCmd),
44

            
45
    /// Export the state of a given block into a chain spec.
46
    ExportState(sc_cli::ExportStateCmd),
47

            
48
    /// Import blocks.
49
    ImportBlocks(sc_cli::ImportBlocksCmd),
50

            
51
    /// Revert the chain to a previous state.
52
    Revert(sc_cli::RevertCmd),
53

            
54
    /// Remove the whole chain.
55
    PurgeChain(cumulus_client_cli::PurgeChainCmd),
56

            
57
    /// Export the genesis state of the parachain.
58
    #[command(alias = "export-genesis-state")]
59
    ExportGenesisHead(cumulus_client_cli::ExportGenesisHeadCommand),
60

            
61
    /// Export the genesis wasm of the parachain.
62
    ExportGenesisWasm(ExportGenesisWasmCommand),
63

            
64
    /// Sub-commands concerned with benchmarking.
65
    /// The pallet benchmarking moved to the `pallet` sub-command.
66
    #[command(subcommand)]
67
    Benchmark(frame_benchmarking_cli::BenchmarkCmd),
68

            
69
    /// Key management cli utilities
70
    #[command(subcommand)]
71
    Key(KeyCmd),
72

            
73
    /// Precompile the WASM runtime into native code
74
    PrecompileWasm(sc_cli::PrecompileWasmCmd),
75

            
76
    /// Solochain collator mode
77
    SoloChain(SoloChainCmd),
78
}
79

            
80
/// Run the node is solochain mode. First serie of arguments are targeted for
81
/// a container chain, while the second set (after --) are targeted towards the
82
/// relay/orchestrator chain (the same chain in solochain mode).
83
#[derive(Debug, clap::Parser)]
84
#[group(skip)]
85
pub struct SoloChainCmd {
86
    #[command(flatten)]
87
    pub run: ContainerChainRunCmd,
88

            
89
    /// Disable automatic hardware benchmarks.
90
    ///
91
    /// By default these benchmarks are automatically ran at startup and measure
92
    /// the CPU speed, the memory bandwidth and the disk speed.
93
    ///
94
    /// The results are then printed out in the logs, and also sent as part of
95
    /// telemetry, if telemetry is enabled.
96
    #[arg(long)]
97
    pub no_hardware_benchmarks: bool,
98

            
99
    /// Relay chain arguments
100
    #[arg(raw = true)]
101
    pub relay_chain_args: Vec<String>,
102
}
103

            
104
#[derive(Debug, Clone, clap::Args)]
105
pub struct ExtraFields {
106
    /// List of container chain chain spec paths to add to genesis.
107
    #[arg(long)]
108
    pub add_container_chain: Option<Vec<String>>,
109

            
110
    /// List of container chain chain spec mocks to add to genesis.
111
    #[arg(long)]
112
    pub mock_container_chain: Option<Vec<u32>>,
113

            
114
    /// List of invulnerable collators to write to pallet_invulnerables genesis.
115
    #[arg(long)]
116
    pub invulnerable: Option<Vec<String>>,
117

            
118
    #[arg(long)]
119
    pub parachain_id: Option<u32>,
120
}
121

            
122
pub type BuildSpecCmdCollator = BuildSpecCmd<ExtraFields>;
123

            
124
pub type ExportChainSpecCmdCollator = ExportChainSpecCmd<ExtraFields>;
125

            
126
/// Command for exporting the genesis wasm file.
127
#[derive(Debug, clap::Parser)]
128
pub struct ExportGenesisWasmCommand {
129
    /// Output file name or stdout if unspecified.
130
    pub output: Option<PathBuf>,
131

            
132
    /// Write output in binary. Default is to write in hex.
133
    #[arg(short, long)]
134
    pub raw: bool,
135

            
136
    /// The name of the chain for that the genesis wasm file should be exported.
137
    #[arg(long)]
138
    pub chain: Option<String>,
139
}
140

            
141
#[derive(Debug, clap::Parser)]
142
#[group(skip)]
143
pub struct RunCmd {
144
    #[clap(flatten)]
145
    pub base: cumulus_client_cli::RunCmd,
146

            
147
    /// Enable the development service to run without a backing relay chain
148
    #[arg(long)]
149
    pub dev_service: bool,
150

            
151
    /// When blocks should be sealed in the dev service.
152
    ///
153
    /// Options are "instant", "manual", or timer interval in milliseconds
154
    #[arg(long, default_value = "instant")]
155
    pub sealing: Sealing,
156

            
157
    /// Id of the parachain this collator collates for.
158
    #[arg(long)]
159
    pub parachain_id: Option<u32>,
160
}
161

            
162
impl std::ops::Deref for RunCmd {
163
    type Target = cumulus_client_cli::RunCmd;
164

            
165
406
    fn deref(&self) -> &Self::Target {
166
406
        &self.base
167
406
    }
168
}
169

            
170
#[derive(Debug, clap::Subcommand)]
171
pub enum KeyCmd {
172
    #[command(flatten)]
173
    BaseCli(sc_cli::KeySubcommand),
174
}
175

            
176
impl KeyCmd {
177
    /// run the key subcommands
178
    pub fn run<C: sc_cli::SubstrateCli>(&self, cli: &C) -> Result<(), sc_cli::Error> {
179
        match self {
180
            KeyCmd::BaseCli(cmd) => cmd.run(cli),
181
        }
182
    }
183
}
184

            
185
#[derive(Debug, clap::Parser)]
186
#[command(
187
    propagate_version = true,
188
    args_conflicts_with_subcommands = true,
189
    subcommand_negates_reqs = true
190
)]
191
pub struct Cli {
192
    #[command(subcommand)]
193
    pub subcommand: Option<Subcommand>,
194

            
195
    #[command(flatten)]
196
    pub run: RunCmd,
197

            
198
    /// Disable automatic hardware benchmarks.
199
    ///
200
    /// By default these benchmarks are automatically ran at startup and measure
201
    /// the CPU speed, the memory bandwidth and the disk speed.
202
    ///
203
    /// The results are then printed out in the logs, and also sent as part of
204
    /// telemetry, if telemetry is enabled.
205
    #[arg(long)]
206
    pub no_hardware_benchmarks: bool,
207

            
208
    /// Optional parachain id that should be used to build chain spec.
209
    #[arg(long)]
210
    pub para_id: Option<u32>,
211

            
212
    /// Extra arguments, `container-args -- relay-args` or `relay-args` if no `--`
213
    #[arg(raw = true)]
214
    extra_args: Vec<String>,
215
}
216

            
217
impl Cli {
218
200
    pub fn relaychain_args(&self) -> &[String] {
219
200
        let (relay_chain_args, _) = self.split_extra_args_at_first_dashdash();
220

            
221
200
        relay_chain_args
222
200
    }
223

            
224
    pub fn container_chain_args(&self) -> &[String] {
225
        let (_, container_chain_args) = self.split_extra_args_at_first_dashdash();
226

            
227
        container_chain_args
228
    }
229

            
230
200
    fn split_extra_args_at_first_dashdash(&self) -> (&[String], &[String]) {
231
200
        let index_of_dashdash = self.extra_args.iter().position(|x| *x == "--");
232

            
233
200
        if let Some(i) = index_of_dashdash {
234
            let (container_chain_args, extra_extra) = self.extra_args.split_at(i);
235
            (&extra_extra[1..], container_chain_args)
236
        } else {
237
            // Only relay chain args
238
200
            (&self.extra_args, &[])
239
        }
240
200
    }
241
}