Add port and gossip options to solana-test-validator (#16696)
This commit is contained in:
parent
9852572eb9
commit
0924c2d070
|
@ -3358,6 +3358,7 @@ impl Node {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_gossip_port(
|
fn get_gossip_port(
|
||||||
gossip_addr: &SocketAddr,
|
gossip_addr: &SocketAddr,
|
||||||
port_range: PortRange,
|
port_range: PortRange,
|
||||||
|
@ -3378,6 +3379,60 @@ impl Node {
|
||||||
bind_in_range(bind_ip_addr, port_range).expect("Failed to bind")
|
bind_in_range(bind_ip_addr, port_range).expect("Failed to bind")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_single_bind(
|
||||||
|
pubkey: &Pubkey,
|
||||||
|
gossip_addr: &SocketAddr,
|
||||||
|
port_range: PortRange,
|
||||||
|
bind_ip_addr: IpAddr,
|
||||||
|
) -> Self {
|
||||||
|
let (gossip_port, (gossip, ip_echo)) =
|
||||||
|
Self::get_gossip_port(gossip_addr, port_range, bind_ip_addr);
|
||||||
|
let (tvu_port, tvu) = Self::bind(bind_ip_addr, port_range);
|
||||||
|
let (tvu_forwards_port, tvu_forwards) = Self::bind(bind_ip_addr, port_range);
|
||||||
|
let (tpu_port, tpu) = Self::bind(bind_ip_addr, port_range);
|
||||||
|
let (tpu_forwards_port, tpu_forwards) = Self::bind(bind_ip_addr, port_range);
|
||||||
|
let (_, retransmit_socket) = Self::bind(bind_ip_addr, port_range);
|
||||||
|
let (repair_port, repair) = Self::bind(bind_ip_addr, port_range);
|
||||||
|
let (serve_repair_port, serve_repair) = Self::bind(bind_ip_addr, port_range);
|
||||||
|
let (_, broadcast) = Self::bind(bind_ip_addr, port_range);
|
||||||
|
|
||||||
|
let rpc_port = find_available_port_in_range(bind_ip_addr, port_range).unwrap();
|
||||||
|
let rpc_pubsub_port = find_available_port_in_range(bind_ip_addr, port_range).unwrap();
|
||||||
|
|
||||||
|
let info = ContactInfo {
|
||||||
|
id: *pubkey,
|
||||||
|
gossip: SocketAddr::new(gossip_addr.ip(), gossip_port),
|
||||||
|
tvu: SocketAddr::new(gossip_addr.ip(), tvu_port),
|
||||||
|
tvu_forwards: SocketAddr::new(gossip_addr.ip(), tvu_forwards_port),
|
||||||
|
repair: SocketAddr::new(gossip_addr.ip(), repair_port),
|
||||||
|
tpu: SocketAddr::new(gossip_addr.ip(), tpu_port),
|
||||||
|
tpu_forwards: SocketAddr::new(gossip_addr.ip(), tpu_forwards_port),
|
||||||
|
unused: socketaddr_any!(),
|
||||||
|
rpc: SocketAddr::new(gossip_addr.ip(), rpc_port),
|
||||||
|
rpc_pubsub: SocketAddr::new(gossip_addr.ip(), rpc_pubsub_port),
|
||||||
|
serve_repair: SocketAddr::new(gossip_addr.ip(), serve_repair_port),
|
||||||
|
wallclock: timestamp(),
|
||||||
|
shred_version: 0,
|
||||||
|
};
|
||||||
|
trace!("new ContactInfo: {:?}", info);
|
||||||
|
|
||||||
|
Node {
|
||||||
|
info,
|
||||||
|
sockets: Sockets {
|
||||||
|
gossip,
|
||||||
|
ip_echo: Some(ip_echo),
|
||||||
|
tvu: vec![tvu],
|
||||||
|
tvu_forwards: vec![tvu_forwards],
|
||||||
|
tpu: vec![tpu],
|
||||||
|
tpu_forwards: vec![tpu_forwards],
|
||||||
|
broadcast: vec![broadcast],
|
||||||
|
repair,
|
||||||
|
retransmit_sockets: vec![retransmit_socket],
|
||||||
|
serve_repair,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_with_external_ip(
|
pub fn new_with_external_ip(
|
||||||
pubkey: &Pubkey,
|
pubkey: &Pubkey,
|
||||||
gossip_addr: &SocketAddr,
|
gossip_addr: &SocketAddr,
|
||||||
|
|
|
@ -7,6 +7,7 @@ use {
|
||||||
},
|
},
|
||||||
solana_client::rpc_client::RpcClient,
|
solana_client::rpc_client::RpcClient,
|
||||||
solana_ledger::{blockstore::create_new_ledger, create_new_tmp_ledger},
|
solana_ledger::{blockstore::create_new_ledger, create_new_tmp_ledger},
|
||||||
|
solana_net_utils::PortRange,
|
||||||
solana_runtime::{
|
solana_runtime::{
|
||||||
bank_forks::{ArchiveFormat, SnapshotConfig, SnapshotVersion},
|
bank_forks::{ArchiveFormat, SnapshotConfig, SnapshotVersion},
|
||||||
genesis_utils::create_genesis_config_with_leader_ex,
|
genesis_utils::create_genesis_config_with_leader_ex,
|
||||||
|
@ -42,6 +43,29 @@ pub struct ProgramInfo {
|
||||||
pub program_path: PathBuf,
|
pub program_path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TestValidatorNodeConfig {
|
||||||
|
gossip_addr: SocketAddr,
|
||||||
|
port_range: PortRange,
|
||||||
|
bind_ip_addr: IpAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TestValidatorNodeConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
const MIN_PORT_RANGE: u16 = 1024;
|
||||||
|
const MAX_PORT_RANGE: u16 = 65535;
|
||||||
|
|
||||||
|
let bind_ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
|
||||||
|
let port_range = (MIN_PORT_RANGE, MAX_PORT_RANGE);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
gossip_addr: socketaddr!("127.0.0.1:0"),
|
||||||
|
port_range,
|
||||||
|
bind_ip_addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct TestValidatorGenesis {
|
pub struct TestValidatorGenesis {
|
||||||
fee_rate_governor: FeeRateGovernor,
|
fee_rate_governor: FeeRateGovernor,
|
||||||
|
@ -54,6 +78,7 @@ pub struct TestValidatorGenesis {
|
||||||
accounts: HashMap<Pubkey, AccountSharedData>,
|
accounts: HashMap<Pubkey, AccountSharedData>,
|
||||||
programs: Vec<ProgramInfo>,
|
programs: Vec<ProgramInfo>,
|
||||||
epoch_schedule: Option<EpochSchedule>,
|
epoch_schedule: Option<EpochSchedule>,
|
||||||
|
node_config: TestValidatorNodeConfig,
|
||||||
pub validator_exit: Arc<RwLock<ValidatorExit>>,
|
pub validator_exit: Arc<RwLock<ValidatorExit>>,
|
||||||
pub start_progress: Arc<RwLock<ValidatorStartProgress>>,
|
pub start_progress: Arc<RwLock<ValidatorStartProgress>>,
|
||||||
pub authorized_voter_keypairs: Arc<RwLock<Vec<Arc<Keypair>>>>,
|
pub authorized_voter_keypairs: Arc<RwLock<Vec<Arc<Keypair>>>>,
|
||||||
|
@ -110,6 +135,26 @@ impl TestValidatorGenesis {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn gossip_host(&mut self, gossip_host: IpAddr) -> &mut Self {
|
||||||
|
self.node_config.gossip_addr.set_ip(gossip_host);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gossip_port(&mut self, gossip_port: u16) -> &mut Self {
|
||||||
|
self.node_config.gossip_addr.set_port(gossip_port);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn port_range(&mut self, port_range: PortRange) -> &mut Self {
|
||||||
|
self.node_config.port_range = port_range;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind_ip_addr(&mut self, bind_ip_addr: IpAddr) -> &mut Self {
|
||||||
|
self.node_config.bind_ip_addr = bind_ip_addr;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Add an account to the test environment
|
/// Add an account to the test environment
|
||||||
pub fn add_account(&mut self, address: Pubkey, account: AccountSharedData) -> &mut Self {
|
pub fn add_account(&mut self, address: Pubkey, account: AccountSharedData) -> &mut Self {
|
||||||
self.accounts.insert(address, account);
|
self.accounts.insert(address, account);
|
||||||
|
@ -398,7 +443,12 @@ impl TestValidator {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut node = Node::new_localhost_with_pubkey(&validator_identity.pubkey());
|
let mut node = Node::new_single_bind(
|
||||||
|
&validator_identity.pubkey(),
|
||||||
|
&config.node_config.gossip_addr,
|
||||||
|
config.node_config.port_range,
|
||||||
|
config.node_config.bind_ip_addr,
|
||||||
|
);
|
||||||
if let Some((rpc, rpc_pubsub)) = config.rpc_ports {
|
if let Some((rpc, rpc_pubsub)) = config.rpc_ports {
|
||||||
node.info.rpc = SocketAddr::new(node.info.gossip.ip(), rpc);
|
node.info.rpc = SocketAddr::new(node.info.gossip.ip(), rpc);
|
||||||
node.info.rpc_pubsub = SocketAddr::new(node.info.gossip.ip(), rpc_pubsub);
|
node.info.rpc_pubsub = SocketAddr::new(node.info.gossip.ip(), rpc_pubsub);
|
||||||
|
|
|
@ -179,6 +179,44 @@ fn main() {
|
||||||
If the ledger already exists then this parameter is silently ignored",
|
If the ledger already exists then this parameter is silently ignored",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("gossip_port")
|
||||||
|
.long("gossip-port")
|
||||||
|
.value_name("PORT")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Gossip port number for the validator"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("gossip_host")
|
||||||
|
.long("gossip-host")
|
||||||
|
.value_name("HOST")
|
||||||
|
.takes_value(true)
|
||||||
|
.validator(solana_net_utils::is_host)
|
||||||
|
.help(
|
||||||
|
"Gossip DNS name or IP address for the validator to advertise in gossip \
|
||||||
|
[default: 127.0.0.1]",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("dynamic_port_range")
|
||||||
|
.long("dynamic-port-range")
|
||||||
|
.value_name("MIN_PORT-MAX_PORT")
|
||||||
|
.takes_value(true)
|
||||||
|
.validator(solana_validator::port_range_validator)
|
||||||
|
.help(
|
||||||
|
"Range to use for dynamically assigned ports \
|
||||||
|
[default: 1024-65535]",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("bind_address")
|
||||||
|
.long("bind-address")
|
||||||
|
.value_name("HOST")
|
||||||
|
.takes_value(true)
|
||||||
|
.validator(solana_net_utils::is_host)
|
||||||
|
.default_value("0.0.0.0")
|
||||||
|
.help("IP address to bind the validator ports [default: 0.0.0.0]"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("clone_account")
|
Arg::with_name("clone_account")
|
||||||
.long("clone")
|
.long("clone")
|
||||||
|
@ -240,6 +278,25 @@ fn main() {
|
||||||
let rpc_port = value_t_or_exit!(matches, "rpc_port", u16);
|
let rpc_port = value_t_or_exit!(matches, "rpc_port", u16);
|
||||||
let faucet_port = value_t_or_exit!(matches, "faucet_port", u16);
|
let faucet_port = value_t_or_exit!(matches, "faucet_port", u16);
|
||||||
let slots_per_epoch = value_t!(matches, "slots_per_epoch", Slot).ok();
|
let slots_per_epoch = value_t!(matches, "slots_per_epoch", Slot).ok();
|
||||||
|
let gossip_host = matches.value_of("gossip_host").map(|gossip_host| {
|
||||||
|
solana_net_utils::parse_host(gossip_host).unwrap_or_else(|err| {
|
||||||
|
eprintln!("Failed to parse --gossip-host: {}", err);
|
||||||
|
exit(1);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
let gossip_port = value_t!(matches, "gossip_port", u16).ok();
|
||||||
|
let dynamic_port_range = matches.value_of("dynamic_port_range").map(|port_range| {
|
||||||
|
solana_net_utils::parse_port_range(port_range).unwrap_or_else(|| {
|
||||||
|
eprintln!("Failed to parse --dynamic-port-range");
|
||||||
|
exit(1);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
let bind_address = matches.value_of("bind_address").map(|bind_address| {
|
||||||
|
solana_net_utils::parse_host(bind_address).unwrap_or_else(|err| {
|
||||||
|
eprintln!("Failed to parse --bind-address: {}", err);
|
||||||
|
exit(1);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
let faucet_addr = Some(SocketAddr::new(
|
let faucet_addr = Some(SocketAddr::new(
|
||||||
IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
|
IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
|
||||||
|
@ -467,6 +524,22 @@ fn main() {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(gossip_host) = gossip_host {
|
||||||
|
genesis.gossip_host(gossip_host);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(gossip_port) = gossip_port {
|
||||||
|
genesis.gossip_port(gossip_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(dynamic_port_range) = dynamic_port_range {
|
||||||
|
genesis.port_range(dynamic_port_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(bind_address) = bind_address {
|
||||||
|
genesis.bind_ip_addr(bind_address);
|
||||||
|
}
|
||||||
|
|
||||||
match genesis.start_with_mint_address(mint_address) {
|
match genesis.start_with_mint_address(mint_address) {
|
||||||
Ok(test_validator) => {
|
Ok(test_validator) => {
|
||||||
if let Some(dashboard) = dashboard {
|
if let Some(dashboard) = dashboard {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![allow(clippy::integer_arithmetic)]
|
#![allow(clippy::integer_arithmetic)]
|
||||||
pub use solana_core::test_validator;
|
pub use solana_core::{cluster_info::MINIMUM_VALIDATOR_PORT_RANGE_WIDTH, test_validator};
|
||||||
use {
|
use {
|
||||||
console::style,
|
console::style,
|
||||||
indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle},
|
indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle},
|
||||||
|
@ -75,6 +75,22 @@ pub fn port_validator(port: String) -> Result<(), String> {
|
||||||
.map_err(|e| format!("{:?}", e))
|
.map_err(|e| format!("{:?}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn port_range_validator(port_range: String) -> Result<(), String> {
|
||||||
|
if let Some((start, end)) = solana_net_utils::parse_port_range(&port_range) {
|
||||||
|
if end - start < MINIMUM_VALIDATOR_PORT_RANGE_WIDTH {
|
||||||
|
Err(format!(
|
||||||
|
"Port range is too small. Try --dynamic-port-range {}-{}",
|
||||||
|
start,
|
||||||
|
start + MINIMUM_VALIDATOR_PORT_RANGE_WIDTH
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err("Invalid port range".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new process bar for processing that will take an unknown amount of time
|
/// Creates a new process bar for processing that will take an unknown amount of time
|
||||||
pub fn new_spinner_progress_bar() -> ProgressBar {
|
pub fn new_spinner_progress_bar() -> ProgressBar {
|
||||||
let progress_bar = ProgressBar::new(42);
|
let progress_bar = ProgressBar::new(42);
|
||||||
|
|
|
@ -21,9 +21,7 @@ use {
|
||||||
DEFAULT_MAX_LEDGER_SHREDS, DEFAULT_MIN_MAX_LEDGER_SHREDS,
|
DEFAULT_MAX_LEDGER_SHREDS, DEFAULT_MIN_MAX_LEDGER_SHREDS,
|
||||||
},
|
},
|
||||||
solana_core::{
|
solana_core::{
|
||||||
cluster_info::{
|
cluster_info::{ClusterInfo, Node, VALIDATOR_PORT_RANGE},
|
||||||
ClusterInfo, Node, MINIMUM_VALIDATOR_PORT_RANGE_WIDTH, VALIDATOR_PORT_RANGE,
|
|
||||||
},
|
|
||||||
contact_info::ContactInfo,
|
contact_info::ContactInfo,
|
||||||
gossip_service::GossipService,
|
gossip_service::GossipService,
|
||||||
poh_service,
|
poh_service,
|
||||||
|
@ -296,22 +294,6 @@ fn wait_for_restart_window(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn port_range_validator(port_range: String) -> Result<(), String> {
|
|
||||||
if let Some((start, end)) = solana_net_utils::parse_port_range(&port_range) {
|
|
||||||
if end - start < MINIMUM_VALIDATOR_PORT_RANGE_WIDTH {
|
|
||||||
Err(format!(
|
|
||||||
"Port range is too small. Try --dynamic-port-range {}-{}",
|
|
||||||
start,
|
|
||||||
start + MINIMUM_VALIDATOR_PORT_RANGE_WIDTH
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err("Invalid port range".to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hash_validator(hash: String) -> Result<(), String> {
|
fn hash_validator(hash: String) -> Result<(), String> {
|
||||||
Hash::from_str(&hash)
|
Hash::from_str(&hash)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
|
@ -1298,7 +1280,7 @@ pub fn main() {
|
||||||
.value_name("MIN_PORT-MAX_PORT")
|
.value_name("MIN_PORT-MAX_PORT")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.default_value(default_dynamic_port_range)
|
.default_value(default_dynamic_port_range)
|
||||||
.validator(port_range_validator)
|
.validator(solana_validator::port_range_validator)
|
||||||
.help("Range to use for dynamically assigned ports"),
|
.help("Range to use for dynamically assigned ports"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
|
|
Loading…
Reference in New Issue