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::{cli::BuildSpecCmd, service::node_builder::Sealing},
19
    std::path::PathBuf,
20
    tc_service_container_chain_spawner::cli::ContainerChainRunCmd,
21
};
22

            
23
/// Sub-commands supported by the collator.
24
#[derive(Debug, clap::Subcommand)]
25
#[allow(clippy::large_enum_variant)]
26
pub enum Subcommand {
27
    /// Build a chain specification.
28
    BuildSpec(BuildSpecCmdCollator),
29

            
30
    /// Validate blocks.
31
    CheckBlock(sc_cli::CheckBlockCmd),
32

            
33
    /// Export blocks.
34
    ExportBlocks(sc_cli::ExportBlocksCmd),
35

            
36
    /// Export the state of a given block into a chain spec.
37
    ExportState(sc_cli::ExportStateCmd),
38

            
39
    /// Import blocks.
40
    ImportBlocks(sc_cli::ImportBlocksCmd),
41

            
42
    /// Revert the chain to a previous state.
43
    Revert(sc_cli::RevertCmd),
44

            
45
    /// Remove the whole chain.
46
    PurgeChain(cumulus_client_cli::PurgeChainCmd),
47

            
48
    /// Export the genesis state of the parachain.
49
    #[command(alias = "export-genesis-state")]
50
    ExportGenesisHead(cumulus_client_cli::ExportGenesisHeadCommand),
51

            
52
    /// Export the genesis wasm of the parachain.
53
    ExportGenesisWasm(ExportGenesisWasmCommand),
54

            
55
    /// Sub-commands concerned with benchmarking.
56
    /// The pallet benchmarking moved to the `pallet` sub-command.
57
    #[command(subcommand)]
58
    Benchmark(frame_benchmarking_cli::BenchmarkCmd),
59

            
60
    /// Key management cli utilities
61
    #[command(subcommand)]
62
    Key(KeyCmd),
63

            
64
    /// Precompile the WASM runtime into native code
65
    PrecompileWasm(sc_cli::PrecompileWasmCmd),
66

            
67
    /// Solochain collator mode
68
    SoloChain(SoloChainCmd),
69
}
70

            
71
/// Run the node is solochain mode. First serie of arguments are targeted for
72
/// a container chain, while the second set (after --) are targeted towards the
73
/// relay/orchestrator chain (the same chain in solochain mode).
74
#[derive(Debug, clap::Parser)]
75
#[group(skip)]
76
pub struct SoloChainCmd {
77
    #[command(flatten)]
78
    pub run: ContainerChainRunCmd,
79

            
80
    /// Disable automatic hardware benchmarks.
81
    ///
82
    /// By default these benchmarks are automatically ran at startup and measure
83
    /// the CPU speed, the memory bandwidth and the disk speed.
84
    ///
85
    /// The results are then printed out in the logs, and also sent as part of
86
    /// telemetry, if telemetry is enabled.
87
    #[arg(long)]
88
    pub no_hardware_benchmarks: bool,
89

            
90
    /// Relay chain arguments
91
    #[arg(raw = true)]
92
    pub relay_chain_args: Vec<String>,
93
}
94

            
95
#[derive(Debug, Clone, clap::Args)]
96
pub struct BuildSpecCmdExtraFields {
97
    /// List of container chain chain spec paths to add to genesis.
98
    #[arg(long)]
99
    pub add_container_chain: Option<Vec<String>>,
100

            
101
    /// List of container chain chain spec mocks to add to genesis.
102
    #[arg(long)]
103
    pub mock_container_chain: Option<Vec<u32>>,
104

            
105
    /// List of invulnerable collators to write to pallet_invulnerables genesis.
106
    #[arg(long)]
107
    pub invulnerable: Option<Vec<String>>,
108

            
109
    #[arg(long)]
110
    pub parachain_id: Option<u32>,
111
}
112

            
113
pub type BuildSpecCmdCollator = BuildSpecCmd<BuildSpecCmdExtraFields>;
114

            
115
/// Command for exporting the genesis wasm file.
116
#[derive(Debug, clap::Parser)]
117
pub struct ExportGenesisWasmCommand {
118
    /// Output file name or stdout if unspecified.
119
    pub output: Option<PathBuf>,
120

            
121
    /// Write output in binary. Default is to write in hex.
122
    #[arg(short, long)]
123
    pub raw: bool,
124

            
125
    /// The name of the chain for that the genesis wasm file should be exported.
126
    #[arg(long)]
127
    pub chain: Option<String>,
128
}
129

            
130
#[derive(Debug, clap::Parser)]
131
#[group(skip)]
132
pub struct RunCmd {
133
    #[clap(flatten)]
134
    pub base: cumulus_client_cli::RunCmd,
135

            
136
    /// Enable the development service to run without a backing relay chain
137
    #[arg(long)]
138
    pub dev_service: bool,
139

            
140
    /// When blocks should be sealed in the dev service.
141
    ///
142
    /// Options are "instant", "manual", or timer interval in milliseconds
143
    #[arg(long, default_value = "instant")]
144
    pub sealing: Sealing,
145

            
146
    /// Id of the parachain this collator collates for.
147
    #[arg(long)]
148
    pub parachain_id: Option<u32>,
149
}
150

            
151
impl std::ops::Deref for RunCmd {
152
    type Target = cumulus_client_cli::RunCmd;
153

            
154
402
    fn deref(&self) -> &Self::Target {
155
402
        &self.base
156
402
    }
157
}
158

            
159
#[derive(Debug, clap::Subcommand)]
160
pub enum KeyCmd {
161
    #[command(flatten)]
162
    BaseCli(sc_cli::KeySubcommand),
163
}
164

            
165
impl KeyCmd {
166
    /// run the key subcommands
167
    pub fn run<C: sc_cli::SubstrateCli>(&self, cli: &C) -> Result<(), sc_cli::Error> {
168
        match self {
169
            KeyCmd::BaseCli(cmd) => cmd.run(cli),
170
        }
171
    }
172
}
173

            
174
#[derive(Debug, clap::Parser)]
175
#[command(
176
    propagate_version = true,
177
    args_conflicts_with_subcommands = true,
178
    subcommand_negates_reqs = true
179
)]
180
pub struct Cli {
181
    #[command(subcommand)]
182
    pub subcommand: Option<Subcommand>,
183

            
184
    #[command(flatten)]
185
    pub run: RunCmd,
186

            
187
    /// Disable automatic hardware benchmarks.
188
    ///
189
    /// By default these benchmarks are automatically ran at startup and measure
190
    /// the CPU speed, the memory bandwidth and the disk speed.
191
    ///
192
    /// The results are then printed out in the logs, and also sent as part of
193
    /// telemetry, if telemetry is enabled.
194
    #[arg(long)]
195
    pub no_hardware_benchmarks: bool,
196

            
197
    /// Optional parachain id that should be used to build chain spec.
198
    #[arg(long)]
199
    pub para_id: Option<u32>,
200

            
201
    /// Extra arguments, `container-args -- relay-args` or `relay-args` if no `--`
202
    #[arg(raw = true)]
203
    extra_args: Vec<String>,
204
}
205

            
206
impl Cli {
207
198
    pub fn relaychain_args(&self) -> &[String] {
208
198
        let (relay_chain_args, _) = self.split_extra_args_at_first_dashdash();
209

            
210
198
        relay_chain_args
211
198
    }
212

            
213
    pub fn container_chain_args(&self) -> &[String] {
214
        let (_, container_chain_args) = self.split_extra_args_at_first_dashdash();
215

            
216
        container_chain_args
217
    }
218

            
219
198
    fn split_extra_args_at_first_dashdash(&self) -> (&[String], &[String]) {
220
198
        let index_of_dashdash = self.extra_args.iter().position(|x| *x == "--");
221

            
222
198
        if let Some(i) = index_of_dashdash {
223
            let (container_chain_args, extra_extra) = self.extra_args.split_at(i);
224
            (&extra_extra[1..], container_chain_args)
225
        } else {
226
            // Only relay chain args
227
198
            (&self.extra_args, &[])
228
        }
229
198
    }
230
}