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