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