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