Skip to content

Commit

Permalink
feat(pd): support real addrs in testnet generate
Browse files Browse the repository at this point in the history
Removed the default RFC1918 addresses from the `pd testnet generate` logic.
Added two new options:

  * --peer-address-template
  * --external-addresses

The goal is to allow a node operator to pass in public IPv4 address
information at the time of config generation, so the emitted config
files are valid without further munging, particularly with respect
to the `external_address` Tendermint advertises for its P2P service.

This change unblocks a leaner deployment pipeline, where we actually
use the results of the `pd testnet generate` output, as intended.

Also: fix(pd) support urls in testnet join

We were inadvertently dropping paths on URLs by prepending `/` to
`Url.join` args, which caused the join operation to be performed on the
base domain, ignoring any path. We didn't notice this because all our
services had been on their own subdomains.
  • Loading branch information
conorsch committed Aug 16, 2023
1 parent 2407079 commit d37e934
Show file tree
Hide file tree
Showing 7 changed files with 945 additions and 549 deletions.
79 changes: 59 additions & 20 deletions crates/bin/pd/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#![allow(clippy::clone_on_copy)]
#![recursion_limit = "512"]
use std::{
net::{Ipv4Addr, SocketAddr},
path::PathBuf,
};
use std::{net::SocketAddr, path::PathBuf};

use console_subscriber::ConsoleLayer;
use metrics_tracing_context::{MetricsLayer, TracingContextLayer};
Expand All @@ -15,8 +12,9 @@ use futures::stream::TryStreamExt;
use metrics_exporter_prometheus::PrometheusBuilder;
use pd::events::EventIndexLayer;
use pd::testnet::{
generate::testnet_generate, get_testnet_dir, join::testnet_join, parse_tm_address,
url_has_necessary_parts,
config::{get_testnet_dir, parse_tm_address, url_has_necessary_parts},
generate::TestnetConfig,
join::testnet_join,
};
use penumbra_proto::client::v1alpha1::{
oblivious_query_service_server::ObliviousQueryServiceServer,
Expand Down Expand Up @@ -152,9 +150,27 @@ enum TestnetCommand {
/// Testnet name [default: latest testnet].
#[clap(long)]
chain_id: Option<String>,
/// IP Address to start `tendermint` nodes on. Increments by three to make room for `pd` per node.
#[clap(long, default_value = "192.167.10.11")]
starting_ip: Ipv4Addr,
/// Base hostname for a validator's p2p service. If multiple validators
/// exist in the genesis, e.g. via `--validators-input-file`, then
/// numeric suffixes are automatically added, e.g. "-0", "-1", etc.
/// Helpful for when you know the validator DNS names ahead of time,
/// e.g. in Kubernetes service addresses. These option is most useful
/// to provide peering on a private network setup. If you plan to expose
/// the validator P2P services to the internet, see the `--external-addresses` option.
#[clap(long)]
peer_address_template: Option<String>,

/// Public addresses and ports for the Tendermint P2P services of the genesis
/// validator. Accepts comma-separated values, to support multiple validators.
/// If `--validators-input-file` is used to increase the number
/// of validators, and the `--external-addresses` flag is set, then the number of
/// external addresses must equal the number of validators. See the
/// `--peer-address-template` flag if you don't plan to expose the network
/// to public peers.
#[clap(long)]
// TODO we should support DNS names here. However, there are complications:
// https://github.com/tendermint/tendermint/issues/1521
external_addresses: Option<String>,
},

/// Like `testnet generate`, but joins the testnet to which the specified node belongs
Expand Down Expand Up @@ -456,11 +472,7 @@ async fn main() -> anyhow::Result<()> {
RootCommand::Testnet {
tn_cmd:
TestnetCommand::Generate {
// TODO this config is gated on a "populate persistent peers"
// setting in the Go tendermint binary. Populating the persistent
// peers will be useful in local setups until peer discovery via a seed
// works.
starting_ip,
peer_address_template,
timeout_commit,
epoch_duration,
unbonding_epochs,
Expand All @@ -469,6 +481,7 @@ async fn main() -> anyhow::Result<()> {
validators_input_file,
chain_id,
preserve_chain_id,
external_addresses,
},
testnet_dir,
} => {
Expand All @@ -493,18 +506,44 @@ async fn main() -> anyhow::Result<()> {
);
}

// Unpack external address information into a vec, since there could be multiple
// values. We don't yet know how many validators will be in the genesis, but the
// Testnet::generate constructor will assert that the number of external addresses,
// if Some, is equal to the number of validators.
let external_addresses: anyhow::Result<Vec<TendermintAddress>> =
match external_addresses {
Some(a) => a
.split(',')
.map(|x| {
x.parse()
.context(format!("Failed to parse external address: {x}"))
})
.collect(),
None => Ok(Vec::new()),
};

let external_addresses = external_addresses?;

// Build and write local configs based on input flags.
testnet_generate(
output_dir,
tracing::info!(?chain_id, "Generating network config");
let t = TestnetConfig::generate(
&chain_id,
active_validator_limit,
Some(output_dir),
peer_address_template,
Some(external_addresses),
allocations_input_file,
validators_input_file,
timeout_commit,
active_validator_limit,
epoch_duration,
unbonding_epochs,
starting_ip,
validators_input_file,
allocations_input_file,
)?;
tracing::info!(
n_validators = t.validators.len(),
chain_id = %t.genesis.chain_id,
"Writing config files for network"
);
t.write_configs()?;
}
}
Ok(())
Expand Down
Loading

0 comments on commit d37e934

Please sign in to comment.