referrerpolicy=no-referrer-when-downgrade

sc_cli/params/
mod.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18mod database_params;
19mod import_params;
20mod keystore_params;
21mod message_params;
22mod mixnet_params;
23mod network_params;
24mod node_key_params;
25mod offchain_worker_params;
26mod prometheus_params;
27mod pruning_params;
28mod rpc_params;
29mod runtime_params;
30mod shared_params;
31mod telemetry_params;
32mod transaction_pool_params;
33
34use crate::arg_enums::{CryptoScheme, OutputType};
35use clap::Args;
36use sc_service::config::{IpNetwork, RpcBatchRequestConfig};
37use sp_core::crypto::{Ss58AddressFormat, Ss58AddressFormatRegistry};
38use sp_runtime::{
39	generic::BlockId,
40	traits::{Block as BlockT, NumberFor},
41};
42use std::{fmt::Debug, str::FromStr};
43
44pub use crate::params::{
45	database_params::*, import_params::*, keystore_params::*, message_params::*, mixnet_params::*,
46	network_params::*, node_key_params::*, offchain_worker_params::*, prometheus_params::*,
47	pruning_params::*, rpc_params::*, runtime_params::*, shared_params::*, telemetry_params::*,
48	transaction_pool_params::*,
49};
50
51/// Parse Ss58AddressFormat
52pub fn parse_ss58_address_format(x: &str) -> Result<Ss58AddressFormat, String> {
53	match Ss58AddressFormatRegistry::try_from(x) {
54		Ok(format_registry) => Ok(format_registry.into()),
55		Err(_) => Err(format!(
56			"Unable to parse variant. Known variants: {:?}",
57			Ss58AddressFormat::all_names()
58		)),
59	}
60}
61
62/// Wrapper type of `String` that holds an unsigned integer of arbitrary size, formatted as a
63/// decimal.
64#[derive(Debug, Clone)]
65pub struct GenericNumber(String);
66
67impl FromStr for GenericNumber {
68	type Err = String;
69
70	fn from_str(block_number: &str) -> Result<Self, Self::Err> {
71		if let Some(pos) = block_number.chars().position(|d| !d.is_digit(10)) {
72			Err(format!("Expected block number, found illegal digit at position: {}", pos))
73		} else {
74			Ok(Self(block_number.to_owned()))
75		}
76	}
77}
78
79impl GenericNumber {
80	/// Wrapper on top of `std::str::parse<N>` but with `Error` as a `String`
81	///
82	/// See `https://doc.rust-lang.org/std/primitive.str.html#method.parse` for more elaborate
83	/// documentation.
84	pub fn parse<N>(&self) -> Result<N, String>
85	where
86		N: FromStr,
87		N::Err: std::fmt::Debug,
88	{
89		FromStr::from_str(&self.0).map_err(|e| format!("Failed to parse block number: {:?}", e))
90	}
91}
92
93/// Wrapper type that is either a `Hash` or the number of a `Block`.
94#[derive(Debug, Clone)]
95pub struct BlockNumberOrHash(String);
96
97impl FromStr for BlockNumberOrHash {
98	type Err = String;
99
100	fn from_str(block_number: &str) -> Result<Self, Self::Err> {
101		if let Some(rest) = block_number.strip_prefix("0x") {
102			if let Some(pos) = rest.chars().position(|c| !c.is_ascii_hexdigit()) {
103				Err(format!(
104					"Expected block hash, found illegal hex character at position: {}",
105					2 + pos,
106				))
107			} else {
108				Ok(Self(block_number.into()))
109			}
110		} else {
111			GenericNumber::from_str(block_number).map(|v| Self(v.0))
112		}
113	}
114}
115
116impl BlockNumberOrHash {
117	/// Parse the inner value as `BlockId`.
118	pub fn parse<B: BlockT>(&self) -> Result<BlockId<B>, String>
119	where
120		<B::Hash as FromStr>::Err: std::fmt::Debug,
121		NumberFor<B>: FromStr,
122		<NumberFor<B> as FromStr>::Err: std::fmt::Debug,
123	{
124		if self.0.starts_with("0x") {
125			Ok(BlockId::Hash(
126				FromStr::from_str(&self.0[2..])
127					.map_err(|e| format!("Failed to parse block hash: {:?}", e))?,
128			))
129		} else {
130			GenericNumber(self.0.clone()).parse().map(BlockId::Number)
131		}
132	}
133}
134
135/// Optional flag for specifying crypto algorithm
136#[derive(Debug, Clone, Args)]
137pub struct CryptoSchemeFlag {
138	/// cryptography scheme
139	#[arg(long, value_name = "SCHEME", value_enum, ignore_case = true, default_value_t = CryptoScheme::Sr25519)]
140	pub scheme: CryptoScheme,
141}
142
143/// Optional flag for specifying output type
144#[derive(Debug, Clone, Args)]
145pub struct OutputTypeFlag {
146	/// output format
147	#[arg(long, value_name = "FORMAT", value_enum, ignore_case = true, default_value_t = OutputType::Text)]
148	pub output_type: OutputType,
149}
150
151/// Optional flag for specifying network scheme
152#[derive(Debug, Clone, Args)]
153pub struct NetworkSchemeFlag {
154	/// network address format
155	#[arg(
156		short = 'n',
157		long,
158		value_name = "NETWORK",
159		ignore_case = true,
160		value_parser = parse_ss58_address_format,
161	)]
162	pub network: Option<Ss58AddressFormat>,
163}
164
165#[cfg(test)]
166mod tests {
167	use super::*;
168
169	type Header = sp_runtime::generic::Header<u32, sp_runtime::traits::BlakeTwo256>;
170	type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;
171
172	#[test]
173	fn parse_block_number() {
174		let block_number_or_hash = BlockNumberOrHash::from_str("1234").unwrap();
175		let parsed = block_number_or_hash.parse::<Block>().unwrap();
176		assert_eq!(BlockId::Number(1234), parsed);
177	}
178
179	#[test]
180	fn parse_block_hash() {
181		let hash = sp_core::H256::default();
182		let hash_str = format!("{:?}", hash);
183		let block_number_or_hash = BlockNumberOrHash::from_str(&hash_str).unwrap();
184		let parsed = block_number_or_hash.parse::<Block>().unwrap();
185		assert_eq!(BlockId::Hash(hash), parsed);
186	}
187
188	#[test]
189	fn parse_block_hash_fails() {
190		assert_eq!(
191			"Expected block hash, found illegal hex character at position: 2",
192			BlockNumberOrHash::from_str("0xHello").unwrap_err(),
193		);
194	}
195
196	#[test]
197	fn parse_block_number_fails() {
198		assert_eq!(
199			"Expected block number, found illegal digit at position: 3",
200			BlockNumberOrHash::from_str("345Hello").unwrap_err(),
201		);
202	}
203}