Add feature to RPC dos (#12119)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3678,6 +3678,7 @@ dependencies = [
|
|||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"rayon",
|
"rayon",
|
||||||
"solana-clap-utils",
|
"solana-clap-utils",
|
||||||
|
"solana-client",
|
||||||
"solana-core",
|
"solana-core",
|
||||||
"solana-ledger",
|
"solana-ledger",
|
||||||
"solana-logger 1.4.0",
|
"solana-logger 1.4.0",
|
||||||
|
@ -21,6 +21,7 @@ solana-net-utils = { path = "../net-utils", version = "1.4.0" }
|
|||||||
solana-runtime = { path = "../runtime", version = "1.4.0" }
|
solana-runtime = { path = "../runtime", version = "1.4.0" }
|
||||||
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
solana-sdk = { path = "../sdk", version = "1.4.0" }
|
||||||
solana-version = { path = "../version", version = "1.4.0" }
|
solana-version = { path = "../version", version = "1.4.0" }
|
||||||
|
solana-client = { path = "../client", version = "1.4.0" }
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
targets = ["x86_64-unknown-linux-gnu"]
|
targets = ["x86_64-unknown-linux-gnu"]
|
||||||
|
201
dos/src/main.rs
201
dos/src/main.rs
@ -1,12 +1,14 @@
|
|||||||
use clap::{crate_description, crate_name, value_t, value_t_or_exit, App, Arg};
|
use clap::{crate_description, crate_name, value_t, value_t_or_exit, App, Arg};
|
||||||
use log::*;
|
use log::*;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_core::{
|
use solana_core::{
|
||||||
contact_info::ContactInfo, gossip_service::discover, serve_repair::RepairProtocol,
|
contact_info::ContactInfo, gossip_service::discover, serve_repair::RepairProtocol,
|
||||||
};
|
};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use std::net::{SocketAddr, UdpSocket};
|
use std::net::{SocketAddr, UdpSocket};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
use std::str::FromStr;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
fn run_dos(
|
fn run_dos(
|
||||||
@ -16,21 +18,34 @@ fn run_dos(
|
|||||||
data_type: String,
|
data_type: String,
|
||||||
data_size: usize,
|
data_size: usize,
|
||||||
mode: String,
|
mode: String,
|
||||||
|
data_input: Option<String>,
|
||||||
) {
|
) {
|
||||||
let mut target = None;
|
let mut target = None;
|
||||||
for node in nodes {
|
let mut rpc_client = None;
|
||||||
if node.gossip == entrypoint_addr {
|
if nodes.is_empty() {
|
||||||
target = match mode.as_str() {
|
if mode == "rpc" {
|
||||||
"gossip" => Some(node.gossip),
|
rpc_client = Some(RpcClient::new_socket(entrypoint_addr));
|
||||||
"tvu" => Some(node.tvu),
|
}
|
||||||
"tvu_forwards" => Some(node.tvu_forwards),
|
target = Some(entrypoint_addr);
|
||||||
"tpu" => Some(node.tpu),
|
} else {
|
||||||
"tpu_forwards" => Some(node.tpu_forwards),
|
for node in nodes {
|
||||||
"repair" => Some(node.repair),
|
if node.gossip == entrypoint_addr {
|
||||||
"serve_repair" => Some(node.serve_repair),
|
target = match mode.as_str() {
|
||||||
&_ => panic!("Unknown mode"),
|
"gossip" => Some(node.gossip),
|
||||||
};
|
"tvu" => Some(node.tvu),
|
||||||
break;
|
"tvu_forwards" => Some(node.tvu_forwards),
|
||||||
|
"tpu" => Some(node.tpu),
|
||||||
|
"tpu_forwards" => Some(node.tpu_forwards),
|
||||||
|
"repair" => Some(node.repair),
|
||||||
|
"serve_repair" => Some(node.serve_repair),
|
||||||
|
"rpc" => {
|
||||||
|
rpc_client = Some(RpcClient::new_socket(node.rpc));
|
||||||
|
None
|
||||||
|
}
|
||||||
|
&_ => panic!("Unknown mode"),
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let target = target.expect("should have target");
|
let target = target.expect("should have target");
|
||||||
@ -40,30 +55,34 @@ fn run_dos(
|
|||||||
|
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
|
|
||||||
let source = thread_rng().gen_range(0, nodes.len());
|
if !nodes.is_empty() {
|
||||||
let mut contact = nodes[source].clone();
|
let source = thread_rng().gen_range(0, nodes.len());
|
||||||
contact.id = Pubkey::new_rand();
|
let mut contact = nodes[source].clone();
|
||||||
match data_type.as_str() {
|
contact.id = Pubkey::new_rand();
|
||||||
"repair_highest" => {
|
match data_type.as_str() {
|
||||||
let slot = 100;
|
"repair_highest" => {
|
||||||
let req = RepairProtocol::WindowIndexWithNonce(contact, slot, 0, 0);
|
let slot = 100;
|
||||||
data = bincode::serialize(&req).unwrap();
|
let req = RepairProtocol::WindowIndexWithNonce(contact, slot, 0, 0);
|
||||||
}
|
data = bincode::serialize(&req).unwrap();
|
||||||
"repair_shred" => {
|
}
|
||||||
let slot = 100;
|
"repair_shred" => {
|
||||||
let req = RepairProtocol::HighestWindowIndexWithNonce(contact, slot, 0, 0);
|
let slot = 100;
|
||||||
data = bincode::serialize(&req).unwrap();
|
let req = RepairProtocol::HighestWindowIndexWithNonce(contact, slot, 0, 0);
|
||||||
}
|
data = bincode::serialize(&req).unwrap();
|
||||||
"repair_orphan" => {
|
}
|
||||||
let slot = 100;
|
"repair_orphan" => {
|
||||||
let req = RepairProtocol::OrphanWithNonce(contact, slot, 0);
|
let slot = 100;
|
||||||
data = bincode::serialize(&req).unwrap();
|
let req = RepairProtocol::OrphanWithNonce(contact, slot, 0);
|
||||||
}
|
data = bincode::serialize(&req).unwrap();
|
||||||
"random" => {
|
}
|
||||||
data.resize(data_size, 0);
|
"random" => {
|
||||||
}
|
data.resize(data_size, 0);
|
||||||
&_ => {
|
}
|
||||||
panic!("unknown data type");
|
"get_account_info" => {}
|
||||||
|
"get_program_accounts" => {}
|
||||||
|
&_ => {
|
||||||
|
panic!("unknown data type");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,14 +90,39 @@ fn run_dos(
|
|||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut error_count = 0;
|
let mut error_count = 0;
|
||||||
loop {
|
loop {
|
||||||
if data_type == "random" {
|
if mode == "rpc" {
|
||||||
thread_rng().fill(&mut data[..]);
|
match data_type.as_str() {
|
||||||
|
"get_account_info" => {
|
||||||
|
let res = rpc_client
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.get_account(&Pubkey::from_str(&data_input.as_ref().unwrap()).unwrap());
|
||||||
|
if res.is_err() {
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"get_program_accounts" => {
|
||||||
|
let res = rpc_client.as_ref().unwrap().get_program_accounts(
|
||||||
|
&Pubkey::from_str(&data_input.as_ref().unwrap()).unwrap(),
|
||||||
|
);
|
||||||
|
if res.is_err() {
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&_ => {
|
||||||
|
panic!("unsupported data type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if data_type == "random" {
|
||||||
|
thread_rng().fill(&mut data[..]);
|
||||||
|
}
|
||||||
|
let res = socket.send_to(&data, target);
|
||||||
|
if res.is_err() {
|
||||||
|
error_count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let res = socket.send_to(&data, target);
|
|
||||||
count += 1;
|
count += 1;
|
||||||
if res.is_err() {
|
|
||||||
error_count += 1;
|
|
||||||
}
|
|
||||||
if last_log.elapsed().as_secs() > 5 {
|
if last_log.elapsed().as_secs() > 5 {
|
||||||
info!("count: {} errors: {}", count, error_count);
|
info!("count: {} errors: {}", count, error_count);
|
||||||
last_log = Instant::now();
|
last_log = Instant::now();
|
||||||
@ -115,6 +159,7 @@ fn main() {
|
|||||||
"tpu_forwards",
|
"tpu_forwards",
|
||||||
"repair",
|
"repair",
|
||||||
"serve_repair",
|
"serve_repair",
|
||||||
|
"rpc",
|
||||||
])
|
])
|
||||||
.help("Interface to DoS"),
|
.help("Interface to DoS"),
|
||||||
)
|
)
|
||||||
@ -130,9 +175,28 @@ fn main() {
|
|||||||
.long("data-type")
|
.long("data-type")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.value_name("TYPE")
|
.value_name("TYPE")
|
||||||
.possible_values(&["repair_highest", "repair_shred", "repair_orphan", "random"])
|
.possible_values(&[
|
||||||
|
"repair_highest",
|
||||||
|
"repair_shred",
|
||||||
|
"repair_orphan",
|
||||||
|
"random",
|
||||||
|
"get_account_info",
|
||||||
|
"get_program_accounts",
|
||||||
|
])
|
||||||
.help("Type of data to send"),
|
.help("Type of data to send"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("data_input")
|
||||||
|
.long("data-input")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("TYPE")
|
||||||
|
.help("Data to send"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("skip_gossip")
|
||||||
|
.long("skip-gossip")
|
||||||
|
.help("Just use entrypoint address directly"),
|
||||||
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let mut entrypoint_addr = SocketAddr::from(([127, 0, 0, 1], 8001));
|
let mut entrypoint_addr = SocketAddr::from(([127, 0, 0, 1], 8001));
|
||||||
@ -143,29 +207,43 @@ fn main() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
let data_size = value_t!(matches, "data_size", usize).unwrap_or(128);
|
let data_size = value_t!(matches, "data_size", usize).unwrap_or(128);
|
||||||
|
let skip_gossip = matches.is_present("skip_gossip");
|
||||||
|
|
||||||
let mode = value_t_or_exit!(matches, "mode", String);
|
let mode = value_t_or_exit!(matches, "mode", String);
|
||||||
let data_type = value_t_or_exit!(matches, "data_type", String);
|
let data_type = value_t_or_exit!(matches, "data_type", String);
|
||||||
|
let data_input = value_t!(matches, "data_input", String).ok();
|
||||||
|
|
||||||
info!("Finding cluster entry: {:?}", entrypoint_addr);
|
let mut nodes = vec![];
|
||||||
let (nodes, _validators) = discover(
|
if !skip_gossip {
|
||||||
None,
|
info!("Finding cluster entry: {:?}", entrypoint_addr);
|
||||||
Some(&entrypoint_addr),
|
let (gossip_nodes, _validators) = discover(
|
||||||
None,
|
None,
|
||||||
Some(60),
|
Some(&entrypoint_addr),
|
||||||
None,
|
None,
|
||||||
Some(&entrypoint_addr),
|
Some(60),
|
||||||
None,
|
None,
|
||||||
0,
|
Some(&entrypoint_addr),
|
||||||
)
|
None,
|
||||||
.unwrap_or_else(|err| {
|
0,
|
||||||
eprintln!("Failed to discover {} node: {:?}", entrypoint_addr, err);
|
)
|
||||||
exit(1);
|
.unwrap_or_else(|err| {
|
||||||
});
|
eprintln!("Failed to discover {} node: {:?}", entrypoint_addr, err);
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
nodes = gossip_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
info!("done found {} nodes", nodes.len());
|
info!("done found {} nodes", nodes.len());
|
||||||
|
|
||||||
run_dos(&nodes, 0, entrypoint_addr, data_type, data_size, mode);
|
run_dos(
|
||||||
|
&nodes,
|
||||||
|
0,
|
||||||
|
entrypoint_addr,
|
||||||
|
data_type,
|
||||||
|
data_size,
|
||||||
|
mode,
|
||||||
|
data_input,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -184,6 +262,7 @@ pub mod test {
|
|||||||
"random".to_string(),
|
"random".to_string(),
|
||||||
10,
|
10,
|
||||||
"tvu".to_string(),
|
"tvu".to_string(),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
run_dos(
|
run_dos(
|
||||||
@ -193,6 +272,7 @@ pub mod test {
|
|||||||
"repair_highest".to_string(),
|
"repair_highest".to_string(),
|
||||||
10,
|
10,
|
||||||
"repair".to_string(),
|
"repair".to_string(),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
run_dos(
|
run_dos(
|
||||||
@ -202,6 +282,7 @@ pub mod test {
|
|||||||
"repair_shred".to_string(),
|
"repair_shred".to_string(),
|
||||||
10,
|
10,
|
||||||
"serve_repair".to_string(),
|
"serve_repair".to_string(),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user