diff --git a/docs/cli/join-testnet.md b/docs/cli/join-testnet.md index a0ded2f5..19c088a9 100644 --- a/docs/cli/join-testnet.md +++ b/docs/cli/join-testnet.md @@ -69,13 +69,20 @@ modal node run-miner --dir ./my-node --no-tui modal node run-hybrid --dir ./my-node --no-tui ``` -Ping a bootstrapper from a **second** node directory (same-dir ping opens the -live datastore): +Ping a bootstrapper from a **second** node directory. Create it first; `ping` +requires `config.json` in that directory. Copy a complete bootstrapper multiaddr +(including its peer ID) from `modal net info testnet`. Keep the target quoted in +the shell: ```bash -modal node ping --dir ./ping-node --target /dns4/node1.testnet.modality.network/tcp/4040/ws/p2p/ +modal node create --dir ./ping-node --testnet +modal net info testnet +modal node ping --dir ./ping-node --target '' ``` +The ping client uses temporary storage, but using a separate directory keeps +it independent of the running miner. + ## Post a contract After sequencers are running (hybrid nominates sequencers from mining epoch diff --git a/docs/cli/mining-testnet.md b/docs/cli/mining-testnet.md index a33289d6..04471c9d 100644 --- a/docs/cli/mining-testnet.md +++ b/docs/cli/mining-testnet.md @@ -28,9 +28,12 @@ this node should also run a sequencer. Do not use a Foundation node template as an independent operator identity. From a **second** node directory, ping a bootstrapper using its full address -from `modal net info testnet` (including `/p2p/`): +from `modal net info testnet` (including its `/p2p/` peer ID). Create the +second directory first because `ping` needs its `config.json`: ```bash +modal node create --dir ./ping-node --testnet +modal net info testnet modal node ping --dir ./ping-node --target '' ``` diff --git a/docs/cli/node-commands.md b/docs/cli/node-commands.md index 3b62ece6..8d13d4cd 100644 --- a/docs/cli/node-commands.md +++ b/docs/cli/node-commands.md @@ -287,7 +287,7 @@ Ping a remote Modality node. | Option | Description | |--------|-------------| | `--target ` | Peer multiaddr to ping | -| `--times ` | Number of ping attempts; defaults to `1` | +| `--times ` | Positive number of ping attempts; defaults to `1` | | `--config ` | Path to `config.json` | | `--dir ` | Node directory containing `config.json` | diff --git a/rust/modality-cli-node/src/ping.rs b/rust/modality-cli-node/src/ping.rs index ee8049d1..3460b4f2 100644 --- a/rust/modality-cli-node/src/ping.rs +++ b/rust/modality-cli-node/src/ping.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use std::num::NonZeroU32; use std::path::PathBuf; use modality_node::actions; @@ -24,7 +25,7 @@ pub struct Opts { target: String, #[clap(long, default_value = "1")] - times: u32, + times: NonZeroU32, } pub async fn run(opts: &Opts) -> Result<()> { @@ -34,7 +35,7 @@ pub async fn run(opts: &Opts) -> Result<()> { let mut client = ephemeral_client::open(opts.config.clone(), opts.dir.clone()).await?; log::info!("Pinging from node: {:?}", client.node.peerid); let target = opts.target.clone(); - let times_to_ping = opts.times; + let times_to_ping = opts.times.get(); let start = Instant::now(); let random_hex = generate_random_hex_string(); @@ -79,3 +80,20 @@ fn generate_random_hex_string() -> String { .map(|b| format!("{:02x}", b)) .collect::() } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn ping_count_must_be_positive() { + assert!(Opts::try_parse_from(["ping", "--target", "peer", "--times", "0"]).is_err()); + assert_eq!( + Opts::try_parse_from(["ping", "--target", "peer", "--times", "1"]) + .unwrap() + .times + .get(), + 1 + ); + } +}