pd/
cli.rs

1//! Command-line interface utilities for the `pd` daemon.
2
3use {
4    clap::{Parser, Subcommand},
5    std::{net::SocketAddr, path::PathBuf},
6    url::Url,
7};
8
9#[derive(Debug, Parser)]
10#[clap(name = "pd", about = "The Penumbra daemon.", version)]
11pub struct Opt {
12    /// Command to run.
13    #[clap(subcommand)]
14    pub cmd: RootCommand,
15}
16
17#[derive(Debug, Subcommand)]
18pub enum RootCommand {
19    /// Starts the Penumbra daemon.
20    Start {
21        /// The path used to store all `pd`-related data and configuration.
22        /// If unset, defaults to ~/.penumbra/network_data/node0/pd.
23        #[clap(long, env = "PENUMBRA_PD_HOME", display_order = 100)]
24        home: Option<PathBuf>,
25        /// Bind the ABCI server to this socket.
26        ///
27        /// The ABCI server is used by Tendermint to drive the application state.
28        #[clap(
29            short,
30            long,
31            env = "PENUMBRA_PD_ABCI_BIND",
32            default_value = "127.0.0.1:26658",
33            display_order = 400
34        )]
35        // TODO: Add support for Unix domain sockets, available in tower-abci >=0.10.0
36        abci_bind: SocketAddr,
37        /// Bind the gRPC server to this socket.
38        ///
39        /// The gRPC server supports both grpc (HTTP/2) and grpc-web (HTTP/1.1) clients.
40        ///
41        /// If `grpc_auto_https` is set, this defaults to `0.0.0.0:443` and uses HTTPS.
42        ///
43        /// If `grpc_auto_https` is not set, this defaults to `127.0.0.1:8080` without HTTPS.
44        #[clap(short, long, env = "PENUMBRA_PD_GRPC_BIND", display_order = 201)]
45        grpc_bind: Option<SocketAddr>,
46        /// If set, serve gRPC using auto-managed HTTPS with this domain name.
47        ///
48        /// NOTE: This option automatically provisions TLS certificates from
49        /// Let's Encrypt and caches them in the `home` directory.  The
50        /// production LE CA has rate limits, so be careful using this option
51        /// with `pd network unsafe-reset-all`, which will delete the certificates
52        /// and force re-issuance, possibly hitting the rate limit. See the
53        /// `--acme-staging` option.
54        #[clap(long, value_name = "DOMAIN", display_order = 200)]
55        grpc_auto_https: Option<String>,
56        /// Enable use of the LetsEncrypt ACME staging API (https://letsencrypt.org/docs/staging-environment/),
57        /// which is more forgiving of ratelimits. Set this option to `true`
58        /// if you're trying out the `--grpc-auto-https` option for the first time,
59        /// to validate your configuration, before subjecting yourself to production
60        /// ratelimits. This option has no effect if `--grpc-auto-https` is not set.
61        #[clap(long, display_order = 201)]
62        acme_staging: bool,
63        /// Bind the metrics endpoint to this socket.
64        #[clap(
65            short,
66            long,
67            env = "PENUMBRA_PD_METRICS_BIND",
68            default_value = "127.0.0.1:9000",
69            display_order = 300
70        )]
71        metrics_bind: SocketAddr,
72        /// The JSON-RPC address of the CometBFT node driving this `pd`
73        /// instance.
74        ///
75        /// This is used to proxy requests from the gRPC server to CometBFT,
76        /// so clients only need to connect to one endpoint and don't need to
77        /// worry about the peculiarities of CometBFT's JSON-RPC encoding
78        /// format.
79        #[clap(
80            short,
81            long,
82            env = "PENUMBRA_PD_COMETBFT_PROXY_URL",
83            default_value = "http://127.0.0.1:26657",
84            display_order = 401,
85            // Support old arg name for a while, as we migrate Tendermint -> CometBFT.
86            alias = "tendermint-addr",
87        )]
88        cometbft_addr: Url,
89        /// Enable expensive RPCs, currently a no-op.
90        #[clap(short, long, display_order = 500)]
91        enable_expensive_rpc: bool,
92    },
93
94    /// Generate, join, or reset a network.
95    Network {
96        /// Path to directory to store output in. Must not exist. Defaults to
97        /// ~/.penumbra/network_data".
98        #[clap(long)]
99        network_dir: Option<PathBuf>,
100        #[clap(subcommand)]
101        net_cmd: NetworkCommand,
102    },
103
104    /// Export the storage state the full node.
105    Export {
106        /// The home directory of the full node.
107        #[clap(long, env = "PENUMBRA_PD_HOME", display_order = 100)]
108        home: PathBuf,
109        /// The directory where the exported node state will be written.
110        #[clap(long, display_order = 200, alias = "export-path")]
111        export_directory: PathBuf,
112        /// An optional filepath for a compressed archive containing the exported
113        /// node state, e.g. ~/pd-backup.tar.gz.
114        #[clap(long, display_order = 200)]
115        export_archive: Option<PathBuf>,
116        /// Whether to prune the JMT tree.
117        #[clap(long, display_order = 300)]
118        prune: bool,
119    },
120
121    /// Run a migration before resuming post-upgrade.
122    Migrate {
123        /// The home directory of the full node.
124        ///
125        /// Migration is performed in-place on the home directory.
126        #[clap(long, env = "PENUMBRA_PD_HOME", display_order = 100)]
127        home: Option<PathBuf>,
128        /// If set, also migrate the CometBFT state located in this home directory.
129        /// If both `--home` and `--comet-home` are unset, will attempt to migrate
130        /// CometBFT state alongside the auto-located `pd` state.
131        // Note: this does _NOT_ use an env var because we are trying to
132        // get explicit consent to muck around in another daemon's state.
133        #[clap(long, display_order = 200)]
134        comet_home: Option<PathBuf>,
135        /// If set, force a migration to occur even if the chain is not halted.
136        /// Will not override a detected mismatch in state versions, or on signs
137        /// of corruption. This is "expert mode" and potentially destructive.
138        #[clap(long, display_order = 1000)]
139        force: bool,
140        /// If set, edit local state to permit the node to start, despite
141        /// a pre-existing halt order, e.g. via governance. This option
142        /// can be useful for relayer operators, to run a temporary archive node
143        /// across upgrade boundaries.
144        #[clap(long, display_order = 1000)]
145        ready_to_start: bool,
146    },
147}
148
149#[derive(Debug, Subcommand)]
150pub enum NetworkCommand {
151    /// Generates a directory structure containing necessary files to create a new
152    /// network config from genesis, based on input configuration.
153    Generate {
154        /// The `timeout_commit` parameter (block interval) to configure Tendermint with.
155        #[clap(long)]
156        timeout_commit: Option<tendermint::Timeout>,
157        /// Number of blocks per epoch.
158        #[clap(long)]
159        epoch_duration: Option<u64>,
160        /// Number of blocks that must elapse before unbonding stake is released.
161        #[clap(long)]
162        unbonding_delay: Option<u64>,
163        /// Maximum number of validators in the consensus set.
164        #[clap(long)]
165        active_validator_limit: Option<u64>,
166        /// Whether to preserve the chain ID (useful for public networks) or append a random suffix (useful for dev/testing).
167        #[clap(long)]
168        preserve_chain_id: bool,
169        /// Path to CSV file containing initial allocations [default: latest testnet].
170        #[clap(long, parse(from_os_str))]
171        allocations_input_file: Option<PathBuf>,
172        /// Penumbra wallet address to include in genesis allocations.
173        /// Intended to make dev experience nicer on first run:
174        /// generate a wallet, view its address, then generate a devnet
175        /// with that address included in the base allocations.
176        #[clap(long)]
177        allocation_address: Option<penumbra_sdk_keys::Address>,
178        #[clap(long, parse(from_os_str))]
179        /// Path to JSON file containing initial validator configs [default: latest testnet].
180        validators_input_file: Option<PathBuf>,
181        /// Testnet name [default: latest testnet].
182        #[clap(long)]
183        chain_id: Option<String>,
184        /// The duration, in number of blocks, that a governance proposal
185        /// can be voted on.
186        #[clap(long)]
187        proposal_voting_blocks: Option<u64>,
188        /// The fixed gas price for all transactions on the network.
189        /// Described as "simple" because the single value will be reused
190        /// for all gas price types: block space, compact block space, verification, and execution.
191        /// The numeric value is one-thousandths of the base unit of the fee token,
192        /// so `--gas-price-simple=1000` means all resources will have a cost of 1upenumbra.
193        #[clap(long)]
194        gas_price_simple: Option<u64>,
195        /// Base hostname for a validator's p2p service. If multiple validators
196        /// exist in the genesis, e.g. via `--validators-input-file`, then
197        /// numeric suffixes are automatically added, e.g. "-0", "-1", etc.
198        /// Helpful for when you know the validator DNS names ahead of time,
199        /// e.g. in Kubernetes service addresses. These option is most useful
200        /// to provide peering on a private network setup. If you plan to expose
201        /// the validator P2P services to the internet, see the `--external-addresses` option.
202        #[clap(long)]
203        peer_address_template: Option<String>,
204        /// Public addresses and ports for the Tendermint P2P services of the genesis
205        /// validator. Accepts comma-separated values, to support multiple validators.
206        /// If `--validators-input-file` is used to increase the number
207        /// of validators, and the `--external-addresses` flag is set, then the number of
208        /// external addresses must equal the number of validators. See the
209        /// `--peer-address-template` flag if you don't plan to expose the network
210        /// to public peers.
211        #[clap(long)]
212        // TODO we should support DNS names here. However, there are complications:
213        // https://github.com/tendermint/tendermint/issues/1521
214        external_addresses: Option<String>,
215    },
216
217    /// Like `network generate`, but joins the network to which the specified node belongs.
218    /// Requires a URL for the CometBFT RPC for the bootstrap node.
219    Join {
220        /// URL of the remote CometBFT RPC endpoint for bootstrapping connection.
221        #[clap(env = "PENUMBRA_PD_JOIN_URL")]
222        node: Url,
223        /// Optional URL of archived node state in .tar.gz format. The archive will be
224        /// downloaded and extracted locally, allowing the node to join a network at a block height
225        /// higher than 0. Supports loading the archive from a local file, if set with file scheme
226        /// explicitly, e.g. `file:///path/to/archive.tar.gz`.
227        #[clap(long, env = "PENUMBRA_PD_ARCHIVE_URL")]
228        archive_url: Option<Url>,
229        /// Human-readable name to identify node on network
230        // Default: 'node-#'
231        #[clap(long, env = "PENUMBRA_PD_TM_EXTERNAL_ADDR")]
232        moniker: Option<String>,
233        /// Public URL to advertise for this node's Tendermint P2P service.
234        /// Setting this option will instruct other nodes on the network to connect
235        /// to yours. Must be in the form of a socket, e.g. "1.2.3.4:26656".
236        #[clap(long, env = "PENUMBRA_PD_TM_EXTERNAL_ADDR")]
237        external_address: Option<SocketAddr>,
238        /// When generating Tendermint config, use this socket to bind the Tendermint RPC service.
239        #[clap(long, env = "PENUMBRA_PD_TM_RPC_BIND", default_value = "0.0.0.0:26657")]
240        tendermint_rpc_bind: SocketAddr,
241        /// When generating Tendermint config, use this socket to bind the Tendermint P2P service.
242        #[clap(long, env = "PENUMBRA_PD_TM_P2P_BIND", default_value = "0.0.0.0:26656")]
243        tendermint_p2p_bind: SocketAddr,
244        /// Leave the downloaded archive file on disk after extraction.
245        #[clap(long, env = "PENUMBRA_PD_LEAVE_ARCHIVE", action)]
246        leave_archive: bool,
247    },
248
249    /// Reset all `pd` network state. This is a destructive action!
250    UnsafeResetAll {},
251}