subspace_malicious_operator/
lib.rs1mod chain_spec;
4mod malicious_bundle_producer;
5mod malicious_bundle_tamper;
6pub mod malicious_domain_instance_starter;
7
8pub use chain_spec::create_domain_spec;
9use clap::Parser;
10use sc_chain_spec::GenericChainSpec;
11use sc_cli::{
12 generate_node_name, ChainSpec, CliConfiguration, Role, RunCmd as SubstrateRunCmd, RunCmd,
13 SubstrateCli,
14};
15use sc_service::config::{
16 ExecutorConfiguration, KeystoreConfig, NetworkConfiguration, RpcConfiguration,
17};
18use sc_service::{BasePath, BlocksPruning, Configuration, DatabaseSource};
19use sp_core::crypto::{AccountId32, Ss58Codec};
20use sp_domains::DomainId;
21
22#[derive(Debug, Parser)]
24#[clap(
25 propagate_version = true,
26 args_conflicts_with_subcommands = true,
27 subcommand_negates_reqs = true
28)]
29pub struct Cli {
30 #[clap(flatten)]
32 pub run: RunCmd,
33
34 #[arg(long)]
37 pub sudo_account: Option<String>,
38
39 #[arg(raw = true)]
46 pub domain_args: Vec<String>,
47}
48
49impl Cli {
50 pub fn sudo_account(&self) -> AccountId32 {
51 self.sudo_account
52 .as_ref()
53 .map(|sudo_account| {
54 AccountId32::from_ss58check(sudo_account).expect("Invalid sudo account")
55 })
56 .unwrap_or(crate::chain_spec::consensus_dev_sudo_account())
57 }
58}
59
60impl SubstrateCli for Cli {
61 fn impl_name() -> String {
62 "Subspace".into()
63 }
64
65 fn impl_version() -> String {
66 env!("SUBSTRATE_CLI_IMPL_VERSION").into()
67 }
68
69 fn executable_name() -> String {
70 "subspace-node".to_string()
73 }
74
75 fn description() -> String {
76 env!("CARGO_PKG_DESCRIPTION").into()
77 }
78
79 fn author() -> String {
80 env!("CARGO_PKG_AUTHORS").into()
81 }
82
83 fn support_url() -> String {
84 "https://forum.subspace.network".into()
85 }
86
87 fn copyright_start_year() -> i32 {
88 2021
89 }
90
91 fn load_spec(&self, id: &str) -> Result<Box<dyn ChainSpec>, String> {
92 let chain_spec = match id {
93 "dev" => crate::chain_spec::dev_config()?,
94 path => GenericChainSpec::from_json_file(std::path::PathBuf::from(path))?,
95 };
96
97 Ok(Box::new(chain_spec))
98 }
99}
100
101#[derive(Debug, Parser)]
102pub struct DomainCli {
103 #[clap(flatten)]
105 pub run: SubstrateRunCmd,
106
107 #[clap(long)]
108 pub domain_id: u32,
109
110 #[clap(raw = true)]
112 additional_args: Vec<String>,
113}
114
115impl DomainCli {
116 pub fn new(domain_args: impl Iterator<Item = String>) -> Self {
118 DomainCli::parse_from([Self::executable_name()].into_iter().chain(domain_args))
119 }
120
121 pub fn additional_args(&self) -> impl Iterator<Item = String> {
122 [Self::executable_name()]
123 .into_iter()
124 .chain(self.additional_args.clone())
125 }
126}
127
128impl SubstrateCli for DomainCli {
129 fn impl_name() -> String {
130 "Subspace Domain".into()
131 }
132
133 fn impl_version() -> String {
134 env!("SUBSTRATE_CLI_IMPL_VERSION").into()
135 }
136
137 fn executable_name() -> String {
138 "subspace-node".to_string()
141 }
142
143 fn description() -> String {
144 "Subspace Domain".into()
145 }
146
147 fn author() -> String {
148 env!("CARGO_PKG_AUTHORS").into()
149 }
150
151 fn support_url() -> String {
152 "https://github.com/autonomys/subspace/issues/new".into()
153 }
154
155 fn copyright_start_year() -> i32 {
156 2022
157 }
158
159 fn load_spec(&self, id: &str) -> Result<Box<dyn ChainSpec>, String> {
160 let runtime_name = "evm";
162 match runtime_name {
163 "evm" => crate::chain_spec::load_domain_chain_spec(id),
164 unknown_name => Err(format!("Unknown runtime: {unknown_name}")),
165 }
166 }
167}
168
169pub(crate) const DEFAULT_NETWORK_CONFIG_PATH: &str = "network";
171
172#[expect(clippy::result_large_err, reason = "Comes from Substrate")]
175pub fn create_malicious_operator_configuration<Cli: SubstrateCli>(
176 domain_id: DomainId,
177 base_path: BasePath,
178 domain_cli: &DomainCli,
179 chain_spec: Box<dyn ChainSpec>,
180 tokio_handle: tokio::runtime::Handle,
181) -> sc_cli::Result<Configuration> {
182 let domain_cli_args = &domain_cli.run;
183 let is_dev = domain_cli_args.shared_params().is_dev();
184 let role = Role::Authority;
185 let config_dir = base_path.config_dir(chain_spec.id());
186 let net_config_dir = config_dir.join(DEFAULT_NETWORK_CONFIG_PATH);
187 let client_id = Cli::client_id();
188 let node_key = domain_cli_args
189 .node_key_params()
190 .map(|x| x.node_key(&net_config_dir, role, is_dev))
191 .unwrap_or_else(|| Ok(Default::default()))?;
192 let max_runtime_instances = 8;
193 let is_validator = role.is_authority();
194 let keystore = KeystoreConfig::InMemory;
196 let telemetry_endpoints = None;
197 let runtime_cache_size = 2;
198 let mut network = match domain_cli_args.network_params() {
199 Some(network_params) => network_params.network_config(
200 &chain_spec,
201 is_dev,
202 is_validator,
203 Some(net_config_dir),
204 &client_id,
205 generate_node_name().as_str(),
206 node_key,
207 30334,
208 ),
209 None => NetworkConfiguration::new(
210 generate_node_name().as_str(),
211 &client_id,
212 node_key,
213 Some(net_config_dir),
214 ),
215 };
216 if let Some(net_config_path) = &mut network.net_config_path {
217 *net_config_path = base_path.path().join("network");
218 }
219
220 let rpc_addrs: Option<Vec<sc_service::config::RpcEndpoint>> = domain_cli
221 .run
222 .rpc_addr(9945)?
223 .map(|addrs| addrs.into_iter().map(Into::into).collect());
224
225 Ok(Configuration {
226 impl_name: Cli::impl_name(),
227 impl_version: Cli::impl_version(),
228 tokio_handle,
229 transaction_pool: domain_cli_args.transaction_pool(is_dev)?,
230 network,
231 keystore,
232 database: DatabaseSource::ParityDb {
233 path: base_path
234 .path()
235 .join("domains")
236 .join(domain_id.to_string())
237 .join("db"),
238 },
239 data_path: config_dir,
240 trie_cache_maximum_size: domain_cli_args.trie_cache_maximum_size()?,
241 state_pruning: domain_cli_args
242 .pruning_params()
243 .map(|x| x.state_pruning())
244 .unwrap_or_else(|| Ok(Default::default()))?,
245 blocks_pruning: domain_cli_args
246 .pruning_params()
247 .map(|x| x.blocks_pruning())
248 .unwrap_or_else(|| Ok(BlocksPruning::KeepFinalized))?,
249 executor: ExecutorConfiguration {
250 wasm_method: domain_cli_args
251 .import_params()
252 .map(|x| x.wasm_method())
253 .unwrap_or_default(),
254 max_runtime_instances,
255 default_heap_pages: domain_cli_args.default_heap_pages()?,
256 runtime_cache_size,
257 },
258 wasm_runtime_overrides: domain_cli_args
259 .import_params()
260 .map(|x| x.wasm_runtime_overrides())
261 .unwrap_or_default(),
262 rpc: RpcConfiguration {
263 addr: rpc_addrs,
264 methods: domain_cli_args.rpc_methods()?,
265 max_connections: domain_cli_args.rpc_max_connections()?,
266 cors: domain_cli_args.rpc_cors(is_dev)?,
267 max_request_size: 15,
268 max_response_size: 15,
269 id_provider: None,
270 max_subs_per_conn: 1024,
271 port: 9945,
272 message_buffer_capacity: domain_cli_args.rpc_buffer_capacity_per_connection()?,
273 batch_config: domain_cli_args.rpc_batch_config()?,
274 rate_limit: domain_cli_args.rpc_rate_limit()?,
275 rate_limit_whitelisted_ips: vec![],
276 rate_limit_trust_proxy_headers: false,
277 },
278 prometheus_config: domain_cli_args.prometheus_config(9616, &chain_spec)?,
279 telemetry_endpoints,
280 offchain_worker: domain_cli_args
281 .offchain_worker_params()
282 .map(|x| x.offchain_worker(&role))
283 .unwrap_or_else(|| Ok(Default::default()))?,
284 force_authoring: domain_cli_args.force_authoring()?,
285 disable_grandpa: domain_cli_args.disable_grandpa()?,
286 dev_key_seed: domain_cli_args.dev_key_seed(is_dev)?,
287 tracing_targets: domain_cli_args.shared_params().tracing_targets(),
288 tracing_receiver: domain_cli_args.shared_params().tracing_receiver(),
289 chain_spec,
290 announce_block: domain_cli_args.announce_block()?,
291 role,
292 base_path,
293 })
294}