linera_service/cli/command.rs
1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::{borrow::Cow, num::NonZeroU16, path::PathBuf};
5
6use chrono::{DateTime, Utc};
7use linera_base::{
8 crypto::{AccountPublicKey, CryptoHash, ValidatorPublicKey},
9 data_types::{Amount, BlockHeight, Epoch},
10 identifiers::{Account, AccountOwner, ApplicationId, ChainId, ModuleId, StreamId},
11 time::Duration,
12 vm::VmRuntime,
13};
14use linera_client::{
15 chain_listener::ChainListenerConfig,
16 client_options::{
17 ApplicationPermissionsConfig, ChainOwnershipConfig, ResourceControlPolicyConfig,
18 },
19 util,
20};
21use linera_rpc::config::CrossChainConfig;
22
23const DEFAULT_TOKENS_PER_CHAIN: Amount = Amount::from_millis(100);
24const DEFAULT_TRANSACTIONS_PER_BLOCK: usize = 1;
25const DEFAULT_WRAP_UP_MAX_IN_FLIGHT: usize = 5;
26const DEFAULT_NUM_CHAINS: usize = 10;
27const DEFAULT_BPS: usize = 10;
28
29/// Specification for a validator to be added to the committee.
30#[derive(Clone, Debug)]
31pub struct ValidatorToAdd {
32 pub public_key: ValidatorPublicKey,
33 pub account_key: AccountPublicKey,
34 pub address: String,
35 pub votes: u64,
36}
37
38impl std::str::FromStr for ValidatorToAdd {
39 type Err = anyhow::Error;
40
41 fn from_str(s: &str) -> Result<Self, Self::Err> {
42 let parts: Vec<&str> = s.split(',').collect();
43 anyhow::ensure!(
44 parts.len() == 4,
45 "Validator spec must be in format: public_key,account_key,address,votes"
46 );
47
48 Ok(ValidatorToAdd {
49 public_key: parts[0].parse()?,
50 account_key: parts[1].parse()?,
51 address: parts[2].to_string(),
52 votes: parts[3].parse()?,
53 })
54 }
55}
56
57#[derive(Clone, clap::Args, serde::Serialize)]
58#[serde(rename_all = "kebab-case")]
59pub struct BenchmarkOptions {
60 /// How many chains to use.
61 #[arg(long, default_value_t = DEFAULT_NUM_CHAINS)]
62 pub num_chains: usize,
63
64 /// How many tokens to assign to each newly created chain.
65 /// These need to cover the transaction fees per chain for the benchmark.
66 #[arg(long, default_value_t = DEFAULT_TOKENS_PER_CHAIN)]
67 pub tokens_per_chain: Amount,
68
69 /// How many transactions to put in each block.
70 #[arg(long, default_value_t = DEFAULT_TRANSACTIONS_PER_BLOCK)]
71 pub transactions_per_block: usize,
72
73 /// The application ID of a fungible token on the wallet's default chain.
74 /// If none is specified, the benchmark uses the native token.
75 #[arg(long)]
76 pub fungible_application_id: Option<linera_base::identifiers::ApplicationId>,
77
78 /// The fixed BPS (Blocks Per Second) rate that block proposals will be sent at.
79 #[arg(long, default_value_t = DEFAULT_BPS)]
80 pub bps: usize,
81
82 /// If provided, will close the chains after the benchmark is finished. Keep in mind that
83 /// closing the chains might take a while, and will increase the validator latency while
84 /// they're being closed.
85 #[arg(long)]
86 pub close_chains: bool,
87
88 /// A comma-separated list of host:port pairs to query for health metrics.
89 /// If provided, the benchmark will check these endpoints for validator health
90 /// and terminate if any validator is unhealthy.
91 /// Example: "127.0.0.1:21100,validator-1.some-network.linera.net:21100"
92 #[arg(long)]
93 pub health_check_endpoints: Option<String>,
94
95 /// The maximum number of in-flight requests to validators when wrapping up the benchmark.
96 /// While wrapping up, this controls the concurrency level when processing inboxes and
97 /// closing chains.
98 #[arg(long, default_value_t = DEFAULT_WRAP_UP_MAX_IN_FLIGHT)]
99 pub wrap_up_max_in_flight: usize,
100
101 /// Confirm before starting the benchmark.
102 #[arg(long)]
103 pub confirm_before_start: bool,
104
105 /// How long to run the benchmark for. If not provided, the benchmark will run until
106 /// it is interrupted.
107 #[arg(long)]
108 pub runtime_in_seconds: Option<u64>,
109
110 /// The delay between chains, in milliseconds. For example, if set to 200ms, the first
111 /// chain will start, then the second will start 200 ms after the first one, the third
112 /// 200 ms after the second one, and so on.
113 /// This is used for slowly ramping up the TPS, so we don't pound the validators with the full
114 /// TPS all at once.
115 #[arg(long)]
116 pub delay_between_chains_ms: Option<u64>,
117
118 /// Path to YAML file containing chain IDs to send transfers to.
119 /// If not provided, only transfers between chains in the same wallet.
120 #[arg(long)]
121 pub config_path: Option<PathBuf>,
122
123 /// Transaction distribution mode. If false (default), distributes transactions evenly
124 /// across chains within each block. If true, sends all transactions in each block
125 /// to a single chain, rotating through chains for subsequent blocks.
126 #[arg(long)]
127 pub single_destination_per_block: bool,
128}
129
130impl Default for BenchmarkOptions {
131 fn default() -> Self {
132 Self {
133 num_chains: DEFAULT_NUM_CHAINS,
134 tokens_per_chain: DEFAULT_TOKENS_PER_CHAIN,
135 transactions_per_block: DEFAULT_TRANSACTIONS_PER_BLOCK,
136 wrap_up_max_in_flight: DEFAULT_WRAP_UP_MAX_IN_FLIGHT,
137 fungible_application_id: None,
138 bps: DEFAULT_BPS,
139 close_chains: false,
140 health_check_endpoints: None,
141 confirm_before_start: false,
142 runtime_in_seconds: None,
143 delay_between_chains_ms: None,
144 config_path: None,
145 single_destination_per_block: false,
146 }
147 }
148}
149
150#[derive(Clone, clap::Subcommand, serde::Serialize)]
151#[serde(rename_all = "kebab-case")]
152pub enum BenchmarkCommand {
153 /// Start a single benchmark process, maintaining a given TPS.
154 Single {
155 #[command(flatten)]
156 options: BenchmarkOptions,
157 },
158
159 /// Run multiple benchmark processes in parallel.
160 Multi {
161 #[command(flatten)]
162 options: BenchmarkOptions,
163
164 /// The number of benchmark processes to run in parallel.
165 #[arg(long, default_value = "1")]
166 processes: usize,
167
168 /// The faucet (which implicitly defines the network)
169 #[arg(long, env = "LINERA_FAUCET_URL")]
170 faucet: String,
171
172 /// If specified, a directory with a random name will be created in this directory, and the
173 /// client state will be stored there.
174 /// If not specified, a temporary directory will be used for each client.
175 #[arg(long)]
176 client_state_dir: Option<String>,
177
178 /// The delay between starting the benchmark processes, in seconds.
179 /// If --cross-wallet-transfers is true, this will be ignored.
180 #[arg(long, default_value = "10")]
181 delay_between_processes: u64,
182
183 /// Whether to send transfers between chains in different wallets.
184 #[arg(long)]
185 cross_wallet_transfers: bool,
186 },
187}
188
189impl BenchmarkCommand {
190 pub fn transactions_per_block(&self) -> usize {
191 match self {
192 Self::Single { options } => options.transactions_per_block,
193 Self::Multi { options, .. } => options.transactions_per_block,
194 }
195 }
196}
197
198#[cfg(feature = "kubernetes")]
199use crate::cli_wrappers::local_kubernetes_net::BuildMode;
200use crate::util::{
201 DEFAULT_PAUSE_AFTER_GQL_MUTATIONS_SECS, DEFAULT_PAUSE_AFTER_LINERA_SERVICE_SECS,
202};
203
204#[derive(Clone, clap::Subcommand)]
205pub enum ClientCommand {
206 /// Transfer funds
207 Transfer {
208 /// Sending chain ID (must be one of our chains)
209 #[arg(long = "from")]
210 sender: Account,
211
212 /// Recipient account
213 #[arg(long = "to")]
214 recipient: Account,
215
216 /// Amount to transfer
217 amount: Amount,
218 },
219
220 /// Open (i.e. activate) a new chain deriving the UID from an existing one.
221 OpenChain {
222 /// Chain ID (must be one of our chains).
223 #[arg(long = "from")]
224 chain_id: Option<ChainId>,
225
226 /// The new owner (otherwise create a key pair and remember it)
227 #[arg(long = "owner")]
228 owner: Option<AccountOwner>,
229
230 /// The initial balance of the new chain. This is subtracted from the parent chain's
231 /// balance.
232 #[arg(long = "initial-balance", default_value = "0")]
233 balance: Amount,
234
235 /// Whether to create a super owner for the new chain.
236 #[arg(long)]
237 super_owner: bool,
238 },
239
240 /// Open (i.e. activate) a new multi-owner chain deriving the UID from an existing one.
241 OpenMultiOwnerChain {
242 /// Chain ID (must be one of our chains).
243 #[arg(long = "from")]
244 chain_id: Option<ChainId>,
245
246 #[clap(flatten)]
247 ownership_config: ChainOwnershipConfig,
248
249 #[clap(flatten)]
250 application_permissions_config: ApplicationPermissionsConfig,
251
252 /// The initial balance of the new chain. This is subtracted from the parent chain's
253 /// balance.
254 #[arg(long = "initial-balance", default_value = "0")]
255 balance: Amount,
256 },
257
258 /// Display who owns the chain, and how the owners work together proposing blocks.
259 ShowOwnership {
260 /// The ID of the chain whose owners will be changed.
261 #[clap(long)]
262 chain_id: Option<ChainId>,
263 },
264
265 /// Change who owns the chain, and how the owners work together proposing blocks.
266 ///
267 /// Specify the complete set of new owners, by public key. Existing owners that are
268 /// not included will be removed.
269 ChangeOwnership {
270 /// The ID of the chain whose owners will be changed.
271 #[clap(long)]
272 chain_id: Option<ChainId>,
273
274 #[clap(flatten)]
275 ownership_config: ChainOwnershipConfig,
276 },
277
278 /// Change the preferred owner of a chain.
279 SetPreferredOwner {
280 /// The ID of the chain whose preferred owner will be changed.
281 #[clap(long)]
282 chain_id: Option<ChainId>,
283
284 /// The new preferred owner.
285 #[arg(long)]
286 owner: AccountOwner,
287 },
288
289 /// Changes the application permissions configuration.
290 ChangeApplicationPermissions {
291 /// The ID of the chain to which the new permissions will be applied.
292 #[arg(long)]
293 chain_id: Option<ChainId>,
294
295 #[clap(flatten)]
296 application_permissions_config: ApplicationPermissionsConfig,
297 },
298
299 /// Close an existing chain.
300 ///
301 /// A closed chain cannot execute operations or accept messages anymore.
302 /// It can still reject incoming messages, so they bounce back to the sender.
303 CloseChain {
304 /// Chain ID (must be one of our chains)
305 chain_id: ChainId,
306 },
307
308 /// Print out the network description.
309 ShowNetworkDescription,
310
311 /// Read the current native-token balance of the given account directly from the local
312 /// state.
313 ///
314 /// NOTE: The local balance does not reflect messages that are waiting to be picked in
315 /// the local inbox, or that have not been synchronized from validators yet. Use
316 /// `linera sync` then either `linera query-balance` or `linera process-inbox &&
317 /// linera local-balance` for a consolidated balance.
318 LocalBalance {
319 /// The account to read, written as `CHAIN-ID:OWNER` or simply `CHAIN-ID` for the
320 /// chain balance. By default, we read the chain balance of the default chain in
321 /// the wallet.
322 account: Option<Account>,
323 },
324
325 /// Simulate the execution of one block made of pending messages from the local inbox,
326 /// then read the native-token balance of the account from the local state.
327 ///
328 /// NOTE: The balance does not reflect messages that have not been synchronized from
329 /// validators yet. Call `linera sync` first to do so.
330 QueryBalance {
331 /// The account to query, written as `CHAIN-ID:OWNER` or simply `CHAIN-ID` for the
332 /// chain balance. By default, we read the chain balance of the default chain in
333 /// the wallet.
334 account: Option<Account>,
335 },
336
337 /// (DEPRECATED) Synchronize the local state of the chain with a quorum validators, then query the
338 /// local balance.
339 ///
340 /// This command is deprecated. Use `linera sync && linera query-balance` instead.
341 SyncBalance {
342 /// The account to query, written as `CHAIN-ID:OWNER` or simply `CHAIN-ID` for the
343 /// chain balance. By default, we read the chain balance of the default chain in
344 /// the wallet.
345 account: Option<Account>,
346 },
347
348 /// Synchronize the local state of the chain with a quorum validators.
349 Sync {
350 /// The chain to synchronize with validators. If omitted, synchronizes the
351 /// default chain of the wallet.
352 chain_id: Option<ChainId>,
353 },
354
355 /// Process all pending incoming messages from the inbox of the given chain by creating as many
356 /// blocks as needed to execute all (non-failing) messages. Failing messages will be
357 /// marked as rejected and may bounce to their sender depending on their configuration.
358 ProcessInbox {
359 /// The chain to process. If omitted, uses the default chain of the wallet.
360 chain_id: Option<ChainId>,
361 },
362
363 /// Show the version and genesis config hash of a new validator, and print a warning if it is
364 /// incompatible. Also print some information about the given chain while we are at it.
365 QueryValidator {
366 /// The new validator's address.
367 address: String,
368 /// The chain to query. If omitted, query the default chain of the wallet.
369 chain_id: Option<ChainId>,
370 /// The public key of the validator. If given, the signature of the chain query
371 /// info will be checked.
372 #[arg(long)]
373 public_key: Option<ValidatorPublicKey>,
374 },
375
376 /// Show the current set of validators for a chain. Also print some information about
377 /// the given chain while we are at it.
378 QueryValidators {
379 /// The chain to query. If omitted, query the default chain of the wallet.
380 chain_id: Option<ChainId>,
381 /// Skip validators with less voting weight that this.
382 #[arg(long)]
383 min_votes: Option<u64>,
384 },
385
386 /// Query validators for shard information about a specific chain.
387 QueryShardInfo {
388 /// The chain to query shard information for.
389 chain_id: ChainId,
390 },
391
392 /// Synchronizes a validator with the local state of chains.
393 SyncValidator {
394 /// The public address of the validator to synchronize.
395 address: String,
396
397 /// The chains to synchronize, or the default chain if empty.
398 #[arg(long, num_args = 0..)]
399 chains: Vec<ChainId>,
400 },
401
402 /// Synchronizes all validators with the local state of chains.
403 SyncAllValidators {
404 /// The chains to synchronize, or the default chain if empty.
405 #[arg(long, num_args = 0..)]
406 chains: Vec<ChainId>,
407 },
408
409 /// Add or modify a validator (admin only)
410 ///
411 /// Deprecated: Use change-validators instead, which allows adding, changing and removing
412 /// any number of validators in a single operation.
413 SetValidator {
414 /// The public key of the validator.
415 #[arg(long)]
416 public_key: ValidatorPublicKey,
417
418 /// The public key of the account controlled by the validator.
419 #[arg(long)]
420 account_key: AccountPublicKey,
421
422 /// Network address
423 #[arg(long)]
424 address: String,
425
426 /// Voting power
427 #[arg(long, default_value = "1")]
428 votes: u64,
429
430 /// Skip the version and genesis config checks.
431 #[arg(long)]
432 skip_online_check: bool,
433 },
434
435 /// Remove a validator (admin only)
436 ///
437 /// Deprecated: Use change-validators instead, which allows adding, changing and removing
438 /// any number of validators in a single operation.
439 RemoveValidator {
440 /// The public key of the validator.
441 #[arg(long)]
442 public_key: ValidatorPublicKey,
443 },
444
445 /// Add, modify, and/or remove multiple validators in a single epoch (admin only)
446 ///
447 /// This command allows you to make multiple validator changes (additions, modifications,
448 /// and removals) in a single new epoch, avoiding the creation of unnecessary short-lived epochs.
449 ChangeValidators {
450 /// Validators to add, specified as "public_key,account_key,address,votes".
451 /// Fails if the validator already exists in the committee.
452 /// Can be specified multiple times.
453 /// Example: --add "public_key1,account_key1,address1,1"
454 #[arg(long = "add", value_name = "VALIDATOR_SPEC")]
455 add_validators: Vec<ValidatorToAdd>,
456
457 /// Validators to modify, specified as "public_key,account_key,address,votes".
458 /// Fails if the validator does not exist in the committee.
459 /// Can be specified multiple times.
460 /// Example: --modify "public_key1,account_key1,address1,2"
461 #[arg(long = "modify", value_name = "VALIDATOR_SPEC")]
462 modify_validators: Vec<ValidatorToAdd>,
463
464 /// Validators to remove, specified by their public key.
465 /// Fails if the validator does not exist in the committee.
466 /// Can be specified multiple times.
467 /// Example: --remove public_key1 --remove public_key2
468 #[arg(long = "remove")]
469 remove_validators: Vec<ValidatorPublicKey>,
470
471 /// Skip the version and genesis config checks for added and modified validators.
472 #[arg(long)]
473 skip_online_check: bool,
474 },
475
476 /// Deprecates all committees up to and including the specified one.
477 RevokeEpochs { epoch: Epoch },
478
479 /// View or update the resource control policy
480 ResourceControlPolicy {
481 /// Set the price per unit of Wasm fuel.
482 #[arg(long)]
483 wasm_fuel_unit: Option<Amount>,
484
485 /// Set the price per unit of EVM fuel.
486 #[arg(long)]
487 evm_fuel_unit: Option<Amount>,
488
489 /// Set the price per read operation.
490 #[arg(long)]
491 read_operation: Option<Amount>,
492
493 /// Set the price per write operation.
494 #[arg(long)]
495 write_operation: Option<Amount>,
496
497 /// Set the price per byte read from runtime.
498 #[arg(long)]
499 byte_runtime: Option<Amount>,
500
501 /// Set the price per byte read.
502 #[arg(long)]
503 byte_read: Option<Amount>,
504
505 /// Set the price per byte written.
506 #[arg(long)]
507 byte_written: Option<Amount>,
508
509 /// Set the base price to read a blob.
510 #[arg(long)]
511 blob_read: Option<Amount>,
512
513 /// Set the base price to publish a blob.
514 #[arg(long)]
515 blob_published: Option<Amount>,
516
517 /// Set the price to read a blob, per byte.
518 #[arg(long)]
519 blob_byte_read: Option<Amount>,
520
521 /// The price to publish a blob, per byte.
522 #[arg(long)]
523 blob_byte_published: Option<Amount>,
524
525 /// Set the price per byte stored.
526 #[arg(long)]
527 byte_stored: Option<Amount>,
528
529 /// Set the base price of sending an operation from a block..
530 #[arg(long)]
531 operation: Option<Amount>,
532
533 /// Set the additional price for each byte in the argument of a user operation.
534 #[arg(long)]
535 operation_byte: Option<Amount>,
536
537 /// Set the base price of sending a message from a block..
538 #[arg(long)]
539 message: Option<Amount>,
540
541 /// Set the additional price for each byte in the argument of a user message.
542 #[arg(long)]
543 message_byte: Option<Amount>,
544
545 /// Set the price per query to a service as an oracle.
546 #[arg(long)]
547 service_as_oracle_query: Option<Amount>,
548
549 /// Set the price for performing an HTTP request.
550 #[arg(long)]
551 http_request: Option<Amount>,
552
553 /// Set the maximum amount of Wasm fuel per block.
554 #[arg(long)]
555 maximum_wasm_fuel_per_block: Option<u64>,
556
557 /// Set the maximum amount of EVM fuel per block.
558 #[arg(long)]
559 maximum_evm_fuel_per_block: Option<u64>,
560
561 /// Set the maximum time in milliseconds that a block can spend executing services as oracles.
562 #[arg(long)]
563 maximum_service_oracle_execution_ms: Option<u64>,
564
565 /// Set the maximum size of a block, in bytes.
566 #[arg(long)]
567 maximum_block_size: Option<u64>,
568
569 /// Set the maximum size of data blobs, compressed bytecode and other binary blobs,
570 /// in bytes.
571 #[arg(long)]
572 maximum_blob_size: Option<u64>,
573
574 /// Set the maximum number of published blobs per block.
575 #[arg(long)]
576 maximum_published_blobs: Option<u64>,
577
578 /// Set the maximum size of decompressed contract or service bytecode, in bytes.
579 #[arg(long)]
580 maximum_bytecode_size: Option<u64>,
581
582 /// Set the maximum size of a block proposal, in bytes.
583 #[arg(long)]
584 maximum_block_proposal_size: Option<u64>,
585
586 /// Set the maximum read data per block.
587 #[arg(long)]
588 maximum_bytes_read_per_block: Option<u64>,
589
590 /// Set the maximum write data per block.
591 #[arg(long)]
592 maximum_bytes_written_per_block: Option<u64>,
593
594 /// Set the maximum size of oracle responses.
595 #[arg(long)]
596 maximum_oracle_response_bytes: Option<u64>,
597
598 /// Set the maximum size in bytes of a received HTTP response.
599 #[arg(long)]
600 maximum_http_response_bytes: Option<u64>,
601
602 /// Set the maximum amount of time allowed to wait for an HTTP response.
603 #[arg(long)]
604 http_request_timeout_ms: Option<u64>,
605
606 /// Set the list of hosts that contracts and services can send HTTP requests to.
607 #[arg(long)]
608 http_request_allow_list: Option<Vec<String>>,
609 },
610
611 /// Run benchmarks to test network performance.
612 #[command(subcommand)]
613 Benchmark(BenchmarkCommand),
614
615 /// Create genesis configuration for a Linera deployment.
616 /// Create initial user chains and print information to be used for initialization of validator setup.
617 /// This will also create an initial wallet for the owner of the initial "root" chains.
618 CreateGenesisConfig {
619 /// Sets the file describing the public configurations of all validators
620 #[arg(long = "committee")]
621 committee_config_path: PathBuf,
622
623 /// The output config path to be consumed by the server
624 #[arg(long = "genesis")]
625 genesis_config_path: PathBuf,
626
627 /// Known initial balance of the chain
628 #[arg(long, default_value = "0")]
629 initial_funding: Amount,
630
631 /// The start timestamp: no blocks can be created before this time.
632 #[arg(long)]
633 start_timestamp: Option<DateTime<Utc>>,
634
635 /// Number of initial (aka "root") chains to create in addition to the admin chain.
636 num_other_initial_chains: u32,
637
638 /// Configure the resource control policy (notably fees) according to pre-defined
639 /// settings.
640 #[arg(long, default_value = "no-fees")]
641 policy_config: ResourceControlPolicyConfig,
642
643 /// Set the price per unit of Wasm fuel.
644 /// (This will overwrite value from `--policy-config`)
645 #[arg(long)]
646 wasm_fuel_unit_price: Option<Amount>,
647
648 /// Set the price per unit of EVM fuel.
649 /// (This will overwrite value from `--policy-config`)
650 #[arg(long)]
651 evm_fuel_unit_price: Option<Amount>,
652
653 /// Set the price per read operation.
654 /// (This will overwrite value from `--policy-config`)
655 #[arg(long)]
656 read_operation_price: Option<Amount>,
657
658 /// Set the price per write operation.
659 /// (This will overwrite value from `--policy-config`)
660 #[arg(long)]
661 write_operation_price: Option<Amount>,
662
663 /// Set the price per byte read from runtime.
664 /// (This will overwrite value from `--policy-config`)
665 #[arg(long)]
666 byte_runtime_price: Option<Amount>,
667
668 /// Set the price per byte read.
669 /// (This will overwrite value from `--policy-config`)
670 #[arg(long)]
671 byte_read_price: Option<Amount>,
672
673 /// Set the price per byte written.
674 /// (This will overwrite value from `--policy-config`)
675 #[arg(long)]
676 byte_written_price: Option<Amount>,
677
678 /// Set the base price to read a blob.
679 /// (This will overwrite value from `--policy-config`)
680 #[arg(long)]
681 blob_read_price: Option<Amount>,
682
683 /// Set the base price to publish a blob.
684 /// (This will overwrite value from `--policy-config`)
685 #[arg(long)]
686 blob_published_price: Option<Amount>,
687
688 /// Set the price to read a blob, per byte.
689 /// (This will overwrite value from `--policy-config`)
690 #[arg(long)]
691 blob_byte_read_price: Option<Amount>,
692
693 /// Set the price to publish a blob, per byte.
694 /// (This will overwrite value from `--policy-config`)
695 #[arg(long)]
696 blob_byte_published_price: Option<Amount>,
697
698 /// Set the price per byte stored.
699 /// (This will overwrite value from `--policy-config`)
700 #[arg(long)]
701 byte_stored_price: Option<Amount>,
702
703 /// Set the base price of sending an operation from a block..
704 /// (This will overwrite value from `--policy-config`)
705 #[arg(long)]
706 operation_price: Option<Amount>,
707
708 /// Set the additional price for each byte in the argument of a user operation.
709 /// (This will overwrite value from `--policy-config`)
710 #[arg(long)]
711 operation_byte_price: Option<Amount>,
712
713 /// Set the base price of sending a message from a block..
714 /// (This will overwrite value from `--policy-config`)
715 #[arg(long)]
716 message_price: Option<Amount>,
717
718 /// Set the additional price for each byte in the argument of a user message.
719 /// (This will overwrite value from `--policy-config`)
720 #[arg(long)]
721 message_byte_price: Option<Amount>,
722
723 /// Set the price per query to a service as an oracle.
724 #[arg(long)]
725 service_as_oracle_query_price: Option<Amount>,
726
727 /// Set the price for performing an HTTP request.
728 #[arg(long)]
729 http_request_price: Option<Amount>,
730
731 /// Set the maximum amount of Wasm fuel per block.
732 /// (This will overwrite value from `--policy-config`)
733 #[arg(long)]
734 maximum_wasm_fuel_per_block: Option<u64>,
735
736 /// Set the maximum amount of EVM fuel per block.
737 /// (This will overwrite value from `--policy-config`)
738 #[arg(long)]
739 maximum_evm_fuel_per_block: Option<u64>,
740
741 /// Set the maximum time in milliseconds that a block can spend executing services as oracles.
742 #[arg(long)]
743 maximum_service_oracle_execution_ms: Option<u64>,
744
745 /// Set the maximum size of a block.
746 /// (This will overwrite value from `--policy-config`)
747 #[arg(long)]
748 maximum_block_size: Option<u64>,
749
750 /// Set the maximum size of decompressed contract or service bytecode, in bytes.
751 /// (This will overwrite value from `--policy-config`)
752 #[arg(long)]
753 maximum_bytecode_size: Option<u64>,
754
755 /// Set the maximum size of data blobs, compressed bytecode and other binary blobs,
756 /// in bytes.
757 /// (This will overwrite value from `--policy-config`)
758 #[arg(long)]
759 maximum_blob_size: Option<u64>,
760
761 /// Set the maximum number of published blobs per block.
762 /// (This will overwrite value from `--policy-config`)
763 #[arg(long)]
764 maximum_published_blobs: Option<u64>,
765
766 /// Set the maximum size of a block proposal, in bytes.
767 /// (This will overwrite value from `--policy-config`)
768 #[arg(long)]
769 maximum_block_proposal_size: Option<u64>,
770
771 /// Set the maximum read data per block.
772 /// (This will overwrite value from `--policy-config`)
773 #[arg(long)]
774 maximum_bytes_read_per_block: Option<u64>,
775
776 /// Set the maximum write data per block.
777 /// (This will overwrite value from `--policy-config`)
778 #[arg(long)]
779 maximum_bytes_written_per_block: Option<u64>,
780
781 /// Set the maximum size of oracle responses.
782 /// (This will overwrite value from `--policy-config`)
783 #[arg(long)]
784 maximum_oracle_response_bytes: Option<u64>,
785
786 /// Set the maximum size in bytes of a received HTTP response.
787 #[arg(long)]
788 maximum_http_response_bytes: Option<u64>,
789
790 /// Set the maximum amount of time allowed to wait for an HTTP response.
791 #[arg(long)]
792 http_request_timeout_ms: Option<u64>,
793
794 /// Set the list of hosts that contracts and services can send HTTP requests to.
795 #[arg(long)]
796 http_request_allow_list: Option<Vec<String>>,
797
798 /// Force this wallet to generate keys using a PRNG and a given seed. USE FOR
799 /// TESTING ONLY.
800 #[arg(long)]
801 testing_prng_seed: Option<u64>,
802
803 /// A unique name to identify this network.
804 #[arg(long)]
805 network_name: Option<String>,
806 },
807
808 /// Watch the network for notifications.
809 Watch {
810 /// The chain ID to watch.
811 chain_id: Option<ChainId>,
812
813 /// Show all notifications from all validators.
814 #[arg(long)]
815 raw: bool,
816 },
817
818 /// Run a GraphQL service to explore and extend the chains of the wallet.
819 Service {
820 #[command(flatten)]
821 config: ChainListenerConfig,
822
823 /// The port on which to run the server
824 #[arg(long)]
825 port: NonZeroU16,
826
827 /// The port to expose metrics on.
828 #[cfg(with_metrics)]
829 #[arg(long)]
830 metrics_port: NonZeroU16,
831 },
832
833 /// Run a GraphQL service that exposes a faucet where users can claim tokens.
834 /// This gives away the chain's tokens, and is mainly intended for testing.
835 Faucet {
836 /// The chain that gives away its tokens.
837 chain_id: Option<ChainId>,
838
839 /// The port on which to run the server
840 #[arg(long, default_value = "8080")]
841 port: u16,
842
843 /// The port for prometheus to scrape.
844 #[cfg(with_metrics)]
845 #[arg(long, default_value = "9090")]
846 metrics_port: u16,
847
848 /// The number of tokens to send to each new chain.
849 #[arg(long)]
850 amount: Amount,
851
852 /// The end timestamp: The faucet will rate-limit the token supply so it runs out of money
853 /// no earlier than this.
854 #[arg(long)]
855 limit_rate_until: Option<DateTime<Utc>>,
856
857 /// Configuration for the faucet chain listener.
858 #[command(flatten)]
859 config: ChainListenerConfig,
860
861 /// Path to the persistent storage file for faucet mappings.
862 #[arg(long)]
863 storage_path: PathBuf,
864
865 /// Maximum number of operations to include in a single block (default: 100).
866 #[arg(long, default_value = "100")]
867 max_batch_size: usize,
868 },
869
870 /// Publish module.
871 PublishModule {
872 /// Path to the Wasm file for the application "contract" bytecode.
873 contract: PathBuf,
874
875 /// Path to the Wasm file for the application "service" bytecode.
876 service: PathBuf,
877
878 /// The virtual machine runtime to use.
879 #[arg(long, default_value = "wasm")]
880 vm_runtime: VmRuntime,
881
882 /// An optional chain ID to publish the module. The default chain of the wallet
883 /// is used otherwise.
884 publisher: Option<ChainId>,
885 },
886
887 /// Print events from a specific chain and stream from a specified index.
888 ListEventsFromIndex {
889 /// The chain to query. If omitted, query the default chain of the wallet.
890 chain_id: Option<ChainId>,
891
892 /// The stream being considered.
893 #[arg(long)]
894 stream_id: StreamId,
895
896 /// Index of the message to start with
897 #[arg(long, default_value = "0")]
898 start_index: u32,
899 },
900
901 /// Publish a data blob of binary data.
902 PublishDataBlob {
903 /// Path to data blob file to be published.
904 blob_path: PathBuf,
905 /// An optional chain ID to publish the blob. The default chain of the wallet
906 /// is used otherwise.
907 publisher: Option<ChainId>,
908 },
909
910 // TODO(#2490): Consider removing or renaming this.
911 /// Verify that a data blob is readable.
912 ReadDataBlob {
913 /// The hash of the content.
914 hash: CryptoHash,
915 /// An optional chain ID to verify the blob. The default chain of the wallet
916 /// is used otherwise.
917 reader: Option<ChainId>,
918 },
919
920 /// Create an application.
921 CreateApplication {
922 /// The module ID of the application to create.
923 module_id: ModuleId,
924
925 /// An optional chain ID to host the application. The default chain of the wallet
926 /// is used otherwise.
927 creator: Option<ChainId>,
928
929 /// The shared parameters as JSON string.
930 #[arg(long)]
931 json_parameters: Option<String>,
932
933 /// Path to a JSON file containing the shared parameters.
934 #[arg(long)]
935 json_parameters_path: Option<PathBuf>,
936
937 /// The instantiation argument as a JSON string.
938 #[arg(long)]
939 json_argument: Option<String>,
940
941 /// Path to a JSON file containing the instantiation argument.
942 #[arg(long)]
943 json_argument_path: Option<PathBuf>,
944
945 /// The list of required dependencies of application, if any.
946 #[arg(long, num_args(0..))]
947 required_application_ids: Option<Vec<ApplicationId>>,
948 },
949
950 /// Create an application, and publish the required module.
951 PublishAndCreate {
952 /// Path to the Wasm file for the application "contract" bytecode.
953 contract: PathBuf,
954
955 /// Path to the Wasm file for the application "service" bytecode.
956 service: PathBuf,
957
958 /// The virtual machine runtime to use.
959 #[arg(long, default_value = "wasm")]
960 vm_runtime: VmRuntime,
961
962 /// An optional chain ID to publish the module. The default chain of the wallet
963 /// is used otherwise.
964 publisher: Option<ChainId>,
965
966 /// The shared parameters as JSON string.
967 #[arg(long)]
968 json_parameters: Option<String>,
969
970 /// Path to a JSON file containing the shared parameters.
971 #[arg(long)]
972 json_parameters_path: Option<PathBuf>,
973
974 /// The instantiation argument as a JSON string.
975 #[arg(long)]
976 json_argument: Option<String>,
977
978 /// Path to a JSON file containing the instantiation argument.
979 #[arg(long)]
980 json_argument_path: Option<PathBuf>,
981
982 /// The list of required dependencies of application, if any.
983 #[arg(long, num_args(0..))]
984 required_application_ids: Option<Vec<ApplicationId>>,
985 },
986
987 /// Create an unassigned key pair.
988 Keygen,
989
990 /// Link the owner to the chain.
991 /// Expects that the caller has a private key corresponding to the `public_key`,
992 /// otherwise block proposals will fail when signing with it.
993 Assign {
994 /// The owner to assign.
995 #[arg(long)]
996 owner: AccountOwner,
997
998 /// The ID of the chain.
999 #[arg(long)]
1000 chain_id: ChainId,
1001 },
1002
1003 /// Retry a block we unsuccessfully tried to propose earlier.
1004 ///
1005 /// As long as a block is pending most other commands will fail, since it is unsafe to propose
1006 /// multiple blocks at the same height.
1007 RetryPendingBlock {
1008 /// The chain with the pending block. If not specified, the wallet's default chain is used.
1009 chain_id: Option<ChainId>,
1010 },
1011
1012 /// Show the contents of the wallet.
1013 #[command(subcommand)]
1014 Wallet(WalletCommand),
1015
1016 /// Show the information about a chain.
1017 #[command(subcommand)]
1018 Chain(ChainCommand),
1019
1020 /// Manage Linera projects.
1021 #[command(subcommand)]
1022 Project(ProjectCommand),
1023
1024 /// Manage a local Linera Network.
1025 #[command(subcommand)]
1026 Net(NetCommand),
1027
1028 /// Operation on the storage.
1029 #[command(subcommand)]
1030 Storage(DatabaseToolCommand),
1031
1032 /// Print CLI help in Markdown format, and exit.
1033 #[command(hide = true)]
1034 HelpMarkdown,
1035
1036 /// Extract a Bash and GraphQL script embedded in a markdown file and print it on
1037 /// `stdout`.
1038 #[command(hide = true)]
1039 ExtractScriptFromMarkdown {
1040 /// The source file
1041 path: PathBuf,
1042
1043 /// Insert a pause of N seconds after calls to `linera service`.
1044 #[arg(long, default_value = DEFAULT_PAUSE_AFTER_LINERA_SERVICE_SECS, value_parser = util::parse_secs)]
1045 pause_after_linera_service: Duration,
1046
1047 /// Insert a pause of N seconds after GraphQL queries.
1048 #[arg(long, default_value = DEFAULT_PAUSE_AFTER_GQL_MUTATIONS_SECS, value_parser = util::parse_secs)]
1049 pause_after_gql_mutations: Duration,
1050 },
1051}
1052
1053impl ClientCommand {
1054 /// Returns the log file name to use based on the [`ClientCommand`] that will run.
1055 pub fn log_file_name(&self) -> Cow<'static, str> {
1056 match self {
1057 ClientCommand::Transfer { .. }
1058 | ClientCommand::OpenChain { .. }
1059 | ClientCommand::OpenMultiOwnerChain { .. }
1060 | ClientCommand::ShowOwnership { .. }
1061 | ClientCommand::ChangeOwnership { .. }
1062 | ClientCommand::SetPreferredOwner { .. }
1063 | ClientCommand::ChangeApplicationPermissions { .. }
1064 | ClientCommand::CloseChain { .. }
1065 | ClientCommand::ShowNetworkDescription
1066 | ClientCommand::LocalBalance { .. }
1067 | ClientCommand::QueryBalance { .. }
1068 | ClientCommand::SyncBalance { .. }
1069 | ClientCommand::Sync { .. }
1070 | ClientCommand::ProcessInbox { .. }
1071 | ClientCommand::QueryValidator { .. }
1072 | ClientCommand::QueryValidators { .. }
1073 | ClientCommand::QueryShardInfo { .. }
1074 | ClientCommand::SyncValidator { .. }
1075 | ClientCommand::SyncAllValidators { .. }
1076 | ClientCommand::SetValidator { .. }
1077 | ClientCommand::RemoveValidator { .. }
1078 | ClientCommand::ChangeValidators { .. }
1079 | ClientCommand::ResourceControlPolicy { .. }
1080 | ClientCommand::RevokeEpochs { .. }
1081 | ClientCommand::CreateGenesisConfig { .. }
1082 | ClientCommand::PublishModule { .. }
1083 | ClientCommand::ListEventsFromIndex { .. }
1084 | ClientCommand::PublishDataBlob { .. }
1085 | ClientCommand::ReadDataBlob { .. }
1086 | ClientCommand::CreateApplication { .. }
1087 | ClientCommand::PublishAndCreate { .. }
1088 | ClientCommand::Keygen
1089 | ClientCommand::Assign { .. }
1090 | ClientCommand::Wallet { .. }
1091 | ClientCommand::Chain { .. }
1092 | ClientCommand::RetryPendingBlock { .. } => "client".into(),
1093 ClientCommand::Benchmark(BenchmarkCommand::Single { .. }) => "single-benchmark".into(),
1094 ClientCommand::Benchmark(BenchmarkCommand::Multi { .. }) => "multi-benchmark".into(),
1095 ClientCommand::Net { .. } => "net".into(),
1096 ClientCommand::Project { .. } => "project".into(),
1097 ClientCommand::Watch { .. } => "watch".into(),
1098 ClientCommand::Storage { .. } => "storage".into(),
1099 ClientCommand::Service { port, .. } => format!("service-{port}").into(),
1100 ClientCommand::Faucet { .. } => "faucet".into(),
1101 ClientCommand::HelpMarkdown | ClientCommand::ExtractScriptFromMarkdown { .. } => {
1102 "tool".into()
1103 }
1104 }
1105 }
1106}
1107
1108#[derive(Clone, clap::Parser)]
1109pub enum DatabaseToolCommand {
1110 /// Delete all the namespaces in the database
1111 DeleteAll,
1112
1113 /// Delete a single namespace from the database
1114 DeleteNamespace,
1115
1116 /// Check existence of a namespace in the database
1117 CheckExistence,
1118
1119 /// Initialize a namespace in the database
1120 Initialize {
1121 #[arg(long = "genesis")]
1122 genesis_config_path: PathBuf,
1123 },
1124
1125 /// List the namespaces in the database
1126 ListNamespaces,
1127
1128 /// List the blob IDs in the database
1129 ListBlobIds,
1130
1131 /// List the chain IDs in the database
1132 ListChainIds,
1133}
1134
1135#[allow(clippy::large_enum_variant)]
1136#[derive(Clone, clap::Parser)]
1137pub enum NetCommand {
1138 /// Start a Local Linera Network
1139 Up {
1140 /// The number of initial "root" chains created in the genesis config on top of
1141 /// the default "admin" chain. All initial chains belong to the first "admin"
1142 /// wallet. It is recommended to use at least one other initial chain for the
1143 /// faucet.
1144 #[arg(long, default_value = "2")]
1145 other_initial_chains: u32,
1146
1147 /// The initial amount of native tokens credited in the initial "root" chains,
1148 /// including the default "admin" chain.
1149 #[arg(long, default_value = "1000000")]
1150 initial_amount: u128,
1151
1152 /// The number of validators in the local test network.
1153 #[arg(long, default_value = "1")]
1154 validators: usize,
1155
1156 /// The number of proxies in the local test network.
1157 #[arg(long, default_value = "1")]
1158 proxies: usize,
1159
1160 /// The number of shards per validator in the local test network.
1161 #[arg(long, default_value = "1")]
1162 shards: usize,
1163
1164 /// Configure the resource control policy (notably fees) according to pre-defined
1165 /// settings.
1166 #[arg(long, default_value = "no-fees")]
1167 policy_config: ResourceControlPolicyConfig,
1168
1169 /// The configuration for cross-chain messages.
1170 #[clap(flatten)]
1171 cross_chain_config: CrossChainConfig,
1172
1173 /// Force this wallet to generate keys using a PRNG and a given seed. USE FOR
1174 /// TESTING ONLY.
1175 #[arg(long)]
1176 testing_prng_seed: Option<u64>,
1177
1178 /// Start the local network on a local Kubernetes deployment.
1179 #[cfg(feature = "kubernetes")]
1180 #[arg(long)]
1181 kubernetes: bool,
1182
1183 /// If this is not set, we'll build the binaries from within the Docker container
1184 /// If it's set, but with no directory path arg, we'll look for the binaries based on `current_binary_parent`
1185 /// If it's set, but with a directory path arg, we'll get the binaries from that path directory
1186 #[cfg(feature = "kubernetes")]
1187 #[arg(long, num_args=0..=1)]
1188 binaries: Option<Option<PathBuf>>,
1189
1190 /// Don't build docker image. This assumes that the image is already built.
1191 #[cfg(feature = "kubernetes")]
1192 #[arg(long, default_value = "false")]
1193 no_build: bool,
1194
1195 /// The name of the docker image to use.
1196 #[cfg(feature = "kubernetes")]
1197 #[arg(long, default_value = "linera:latest")]
1198 docker_image_name: String,
1199
1200 /// The build mode to use.
1201 #[cfg(feature = "kubernetes")]
1202 #[arg(long, default_value = "release")]
1203 build_mode: BuildMode,
1204
1205 /// Run with a specific path where the wallet and validator input files are.
1206 /// If none, then a temporary directory is created.
1207 #[arg(long)]
1208 path: Option<String>,
1209
1210 /// External protocol used, either `grpc` or `grpcs`.
1211 #[arg(long, default_value = "grpc")]
1212 external_protocol: String,
1213
1214 /// If present, a faucet is started using the chain provided by --faucet-chain, or
1215 /// the first non-admin chain if not provided.
1216 #[arg(long, default_value = "false")]
1217 with_faucet: bool,
1218
1219 /// When using --with-faucet, this specifies the chain on which the faucet will be started.
1220 /// If this is `n`, the `n`-th non-admin chain (lexicographically) in the wallet is selected.
1221 #[arg(long)]
1222 faucet_chain: Option<u32>,
1223
1224 /// The port on which to run the faucet server
1225 #[arg(long, default_value = "8080")]
1226 faucet_port: NonZeroU16,
1227
1228 /// The number of tokens to send to each new chain created by the faucet.
1229 #[arg(long, default_value = "1000")]
1230 faucet_amount: Amount,
1231
1232 /// Whether to start a block exporter for each validator.
1233 #[arg(long, default_value = "false")]
1234 with_block_exporter: bool,
1235
1236 /// The number of block exporters to start.
1237 #[arg(long, default_value = "1")]
1238 num_block_exporters: usize,
1239
1240 /// The address of the block exporter.
1241 #[arg(long, default_value = "localhost")]
1242 exporter_address: String,
1243
1244 /// The port on which to run the block exporter.
1245 #[arg(long, default_value = "8081")]
1246 exporter_port: NonZeroU16,
1247
1248 /// The name of the indexer docker image to use.
1249 #[cfg(feature = "kubernetes")]
1250 #[arg(long, default_value = "linera-indexer:latest")]
1251 indexer_image_name: String,
1252
1253 /// The name of the explorer docker image to use.
1254 #[cfg(feature = "kubernetes")]
1255 #[arg(long, default_value = "linera-explorer:latest")]
1256 explorer_image_name: String,
1257
1258 /// Use dual store (rocksdb and scylladb) instead of just scylladb. This is exclusive for
1259 /// kubernetes deployments.
1260 #[cfg(feature = "kubernetes")]
1261 #[arg(long, default_value = "false")]
1262 dual_store: bool,
1263 },
1264
1265 /// Print a bash helper script to make `linera net up` easier to use. The script is
1266 /// meant to be installed in `~/.bash_profile` or sourced when needed.
1267 Helper,
1268}
1269
1270#[derive(Clone, clap::Subcommand)]
1271pub enum WalletCommand {
1272 /// Show the contents of the wallet.
1273 Show {
1274 /// The chain to show the metadata.
1275 chain_id: Option<ChainId>,
1276 /// Only print a non-formatted list of the wallet's chain IDs.
1277 #[arg(long)]
1278 short: bool,
1279 /// Print only the chains that we have a key pair for.
1280 #[arg(long)]
1281 owned: bool,
1282 },
1283
1284 /// Change the wallet default chain.
1285 SetDefault { chain_id: ChainId },
1286
1287 /// Initialize a wallet from the genesis configuration.
1288 Init {
1289 /// The path to the genesis configuration for a Linera deployment. Either this or `--faucet`
1290 /// must be specified.
1291 ///
1292 /// Overrides `--faucet` if provided.
1293 #[arg(long = "genesis")]
1294 genesis_config_path: Option<PathBuf>,
1295
1296 /// The address of a faucet.
1297 #[arg(long, env = "LINERA_FAUCET_URL")]
1298 faucet: Option<String>,
1299
1300 /// Force this wallet to generate keys using a PRNG and a given seed. USE FOR
1301 /// TESTING ONLY.
1302 #[arg(long)]
1303 testing_prng_seed: Option<u64>,
1304 },
1305
1306 /// Request a new chain from a faucet and add it to the wallet.
1307 RequestChain {
1308 /// The address of a faucet.
1309 #[arg(long, env = "LINERA_FAUCET_URL")]
1310 faucet: String,
1311
1312 /// Whether this chain should become the default chain.
1313 #[arg(long)]
1314 set_default: bool,
1315 },
1316
1317 /// Add a new followed chain (i.e. a chain without keypair) to the wallet.
1318 FollowChain {
1319 /// The chain ID.
1320 chain_id: ChainId,
1321 /// Synchronize the new chain and download all its blocks from the validators.
1322 #[arg(long)]
1323 sync: bool,
1324 },
1325
1326 /// Forgets the specified chain's keys. The chain will still be followed by the
1327 /// wallet.
1328 ForgetKeys { chain_id: ChainId },
1329
1330 /// Forgets the specified chain, including the associated key pair.
1331 ForgetChain { chain_id: ChainId },
1332}
1333
1334#[derive(Clone, clap::Subcommand)]
1335pub enum ChainCommand {
1336 /// Show the contents of a block.
1337 ShowBlock {
1338 /// The height of the block.
1339 height: BlockHeight,
1340 /// The chain to show the block (if not specified, the default chain from the
1341 /// wallet is used).
1342 chain_id: Option<ChainId>,
1343 },
1344
1345 /// Show the chain description of a chain.
1346 ShowChainDescription {
1347 /// The chain ID to show (if not specified, the default chain from the wallet is
1348 /// used).
1349 chain_id: Option<ChainId>,
1350 },
1351}
1352
1353#[derive(Clone, clap::Parser)]
1354pub enum ProjectCommand {
1355 /// Create a new Linera project.
1356 New {
1357 /// The project name. A directory of the same name will be created in the current directory.
1358 name: String,
1359
1360 /// Use the given clone of the Linera repository instead of remote crates.
1361 #[arg(long)]
1362 linera_root: Option<PathBuf>,
1363 },
1364
1365 /// Test a Linera project.
1366 ///
1367 /// Equivalent to running `cargo test` with the appropriate test runner.
1368 Test { path: Option<PathBuf> },
1369
1370 /// Build and publish a Linera project.
1371 PublishAndCreate {
1372 /// The path of the root of the Linera project.
1373 /// Defaults to current working directory if unspecified.
1374 path: Option<PathBuf>,
1375
1376 /// Specify the name of the Linera project.
1377 /// This is used to locate the generated bytecode files. The generated bytecode files should
1378 /// be of the form `<name>_{contract,service}.wasm`.
1379 ///
1380 /// Defaults to the package name in Cargo.toml, with dashes replaced by
1381 /// underscores.
1382 name: Option<String>,
1383
1384 /// An optional chain ID to publish the module. The default chain of the wallet
1385 /// is used otherwise.
1386 publisher: Option<ChainId>,
1387
1388 /// The virtual machine runtime to use.
1389 #[arg(long, default_value = "wasm")]
1390 vm_runtime: VmRuntime,
1391
1392 /// The shared parameters as JSON string.
1393 #[arg(long)]
1394 json_parameters: Option<String>,
1395
1396 /// Path to a JSON file containing the shared parameters.
1397 #[arg(long)]
1398 json_parameters_path: Option<PathBuf>,
1399
1400 /// The instantiation argument as a JSON string.
1401 #[arg(long)]
1402 json_argument: Option<String>,
1403
1404 /// Path to a JSON file containing the instantiation argument.
1405 #[arg(long)]
1406 json_argument_path: Option<PathBuf>,
1407
1408 /// The list of required dependencies of application, if any.
1409 #[arg(long, num_args(0..))]
1410 required_application_ids: Option<Vec<ApplicationId>>,
1411 },
1412}