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
    clap::Parser,
19
    node_common::service::Sealing,
20
    sc_cli::{CliConfiguration, NodeKeyParams, SharedParams},
21
    std::path::PathBuf,
22
    url::Url,
23
};
24

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

            
32
    /// Validate blocks.
33
    CheckBlock(sc_cli::CheckBlockCmd),
34

            
35
    /// Export blocks.
36
    ExportBlocks(sc_cli::ExportBlocksCmd),
37

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

            
41
    /// Import blocks.
42
    ImportBlocks(sc_cli::ImportBlocksCmd),
43

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

            
47
    /// Remove the whole chain.
48
    PurgeChain(cumulus_client_cli::PurgeChainCmd),
49

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

            
54
    /// Export the genesis wasm of the parachain.
55
    ExportGenesisWasm(cumulus_client_cli::ExportGenesisWasmCommand),
56

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

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

            
66
#[derive(Debug, Parser)]
67
#[group(skip)]
68
pub struct RunCmd {
69
    #[clap(flatten)]
70
    pub base: cumulus_client_cli::RunCmd,
71

            
72
    /// Id of the parachain this collator collates for.
73
    #[arg(long)]
74
    pub parachain_id: Option<u32>,
75

            
76
    /// When blocks should be sealed in the dev service.
77
    ///
78
    /// Options are "instant", "manual", or timer interval in milliseconds
79
    #[arg(long, default_value = "instant")]
80
    pub sealing: Sealing,
81
}
82

            
83
impl std::ops::Deref for RunCmd {
84
    type Target = cumulus_client_cli::RunCmd;
85

            
86
128
    fn deref(&self) -> &Self::Target {
87
128
        &self.base
88
128
    }
89
}
90

            
91
#[derive(Debug, clap::Parser)]
92
#[command(
93
    propagate_version = true,
94
    args_conflicts_with_subcommands = true,
95
    subcommand_negates_reqs = true
96
)]
97
pub struct Cli {
98
    #[command(subcommand)]
99
    pub subcommand: Option<Subcommand>,
100

            
101
    #[command(flatten)]
102
    pub run: RunCmd,
103

            
104
    /// Disable automatic hardware benchmarks.
105
    ///
106
    /// By default these benchmarks are automatically ran at startup and measure
107
    /// the CPU speed, the memory bandwidth and the disk speed.
108
    ///
109
    /// The results are then printed out in the logs, and also sent as part of
110
    /// telemetry, if telemetry is enabled.
111
    #[arg(long)]
112
    pub no_hardware_benchmarks: bool,
113

            
114
    /// Optional parachain id that should be used to build chain spec.
115
    #[arg(long)]
116
    pub para_id: Option<u32>,
117

            
118
    /// Profile id associated with the node, whose assignements will be followed to provide RPC services.
119
    #[arg(long)]
120
    pub rpc_provider_profile_id: Option<u64>,
121

            
122
    /// Endpoints to connect to orchestrator nodes, avoiding to start a local orchestrator node.
123
    /// If this list is empty, a local embeded orchestrator node is started.
124
    #[arg(long)]
125
    pub orchestrator_endpoints: Vec<Url>,
126

            
127
    /// Relay chain arguments, optionally followed by "--" and container chain arguments
128
    #[arg(raw = true)]
129
    extra_args: Vec<String>,
130
}
131

            
132
impl Cli {
133
64
    pub fn relaychain_args(&self) -> &[String] {
134
64
        let (relay_chain_args, _) = self.split_extra_args_at_first_dashdash();
135
64

            
136
64
        relay_chain_args
137
64
    }
138

            
139
    pub fn container_chain_args(&self) -> &[String] {
140
        let (_, container_chain_args) = self.split_extra_args_at_first_dashdash();
141

            
142
        container_chain_args
143
    }
144

            
145
64
    fn split_extra_args_at_first_dashdash(&self) -> (&[String], &[String]) {
146
64
        let index_of_dashdash = self.extra_args.iter().position(|x| *x == "--");
147

            
148
64
        if let Some(i) = index_of_dashdash {
149
            let (container_chain_args, extra_extra) = self.extra_args.split_at(i);
150
            (&extra_extra[1..], container_chain_args)
151
        } else {
152
            // Only relay chain args
153
64
            (&self.extra_args, &[])
154
        }
155
64
    }
156
}
157

            
158
#[derive(Debug)]
159
pub struct RelayChainCli {
160
    /// The actual relay chain cli object.
161
    pub base: polkadot_cli::RunCmd,
162

            
163
    /// Optional chain id that should be passed to the relay chain.
164
    pub chain_id: Option<String>,
165

            
166
    /// The base path that should be used by the relay chain.
167
    pub base_path: PathBuf,
168
}
169

            
170
impl RelayChainCli {
171
    /// Parse the relay chain CLI parameters using the para chain `Configuration`.
172
64
    pub fn new<'a>(
173
64
        para_config: &sc_service::Configuration,
174
64
        relay_chain_args: impl Iterator<Item = &'a String>,
175
64
    ) -> Self {
176
64
        let extension = crate::chain_spec::Extensions::try_get(&*para_config.chain_spec);
177
64
        let chain_id = extension.map(|e| e.relay_chain.clone());
178
64
        let base_path = para_config.base_path.path().join("polkadot");
179
64
        Self {
180
64
            base_path,
181
64
            chain_id,
182
64
            base: clap::Parser::parse_from(relay_chain_args),
183
64
        }
184
64
    }
185
}
186

            
187
/// The `build-spec` command used to build a specification.
188
#[derive(Debug, Clone, clap::Parser)]
189
pub struct BuildSpecCmd {
190
    #[clap(flatten)]
191
    pub base: sc_cli::BuildSpecCmd,
192

            
193
    /// Id of the parachain this spec is for. Note that this overrides the `--chain` param.
194
    #[arg(long, conflicts_with = "chain")]
195
    #[arg(long)]
196
    pub parachain_id: Option<u32>,
197

            
198
    /// List of bootnodes to add to chain spec
199
    #[arg(long)]
200
    pub add_bootnode: Vec<String>,
201
}
202

            
203
impl CliConfiguration for BuildSpecCmd {
204
48
    fn shared_params(&self) -> &SharedParams {
205
48
        &self.base.shared_params
206
48
    }
207

            
208
4
    fn node_key_params(&self) -> Option<&NodeKeyParams> {
209
4
        Some(&self.base.node_key_params)
210
4
    }
211
}