2021-02-16 13:48:20 -08:00
|
|
|
#![allow(clippy::integer_arithmetic)]
|
2019-10-04 01:16:07 -07:00
|
|
|
use log::*;
|
2019-09-18 13:10:50 -07:00
|
|
|
use solana_bench_tps::bench::{do_bench_tps, generate_and_fund_keypairs, generate_keypairs};
|
|
|
|
use solana_bench_tps::cli;
|
2019-10-15 12:52:44 -07:00
|
|
|
use solana_genesis::Base64Account;
|
2021-05-26 08:15:46 -07:00
|
|
|
use solana_gossip::gossip_service::{discover_cluster, get_client, get_multi_client};
|
2020-02-28 12:27:01 -08:00
|
|
|
use solana_sdk::fee_calculator::FeeRateGovernor;
|
2020-02-20 13:28:55 -08:00
|
|
|
use solana_sdk::signature::{Keypair, Signer};
|
2019-09-09 16:17:10 -07:00
|
|
|
use solana_sdk::system_program;
|
2021-07-23 08:25:03 -07:00
|
|
|
use solana_streamer::socket::SocketAddrSpace;
|
2020-01-16 18:35:12 -08:00
|
|
|
use std::{collections::HashMap, fs::File, io::prelude::*, path::Path, process::exit, sync::Arc};
|
2018-03-04 00:21:40 -08:00
|
|
|
|
2019-06-18 14:44:53 -07:00
|
|
|
/// Number of signatures for all transactions in ~1 week at ~100K TPS
|
|
|
|
pub const NUM_SIGNATURES_FOR_TXS: u64 = 100_000 * 60 * 60 * 24 * 7;
|
|
|
|
|
2018-02-28 09:07:54 -08:00
|
|
|
fn main() {
|
2020-01-08 09:19:12 -08:00
|
|
|
solana_logger::setup_with_default("solana=info");
|
2018-11-16 08:45:59 -08:00
|
|
|
solana_metrics::set_panic_hook("bench-tps");
|
2018-03-03 20:15:42 -08:00
|
|
|
|
2020-05-11 15:02:01 -07:00
|
|
|
let matches = cli::build_args(solana_version::version!()).get_matches();
|
2019-04-19 14:04:36 -07:00
|
|
|
let cli_config = cli::extract_args(&matches);
|
2018-12-12 11:27:21 -08:00
|
|
|
|
2019-04-19 14:04:36 -07:00
|
|
|
let cli::Config {
|
2019-05-03 15:00:19 -07:00
|
|
|
entrypoint_addr,
|
2019-12-16 13:05:17 -08:00
|
|
|
faucet_addr,
|
2019-04-19 14:04:36 -07:00
|
|
|
id,
|
|
|
|
num_nodes,
|
|
|
|
tx_count,
|
2019-12-18 20:50:17 -08:00
|
|
|
keypair_multiplier,
|
2019-06-11 18:47:35 -07:00
|
|
|
client_ids_and_stake_file,
|
|
|
|
write_to_client_file,
|
|
|
|
read_from_client_file,
|
2019-06-18 14:44:53 -07:00
|
|
|
target_lamports_per_signature,
|
2019-10-30 14:43:30 -07:00
|
|
|
multi_client,
|
2019-09-10 16:24:43 -07:00
|
|
|
num_lamports_per_account,
|
2020-07-01 21:10:12 -07:00
|
|
|
target_node,
|
2019-09-10 16:24:43 -07:00
|
|
|
..
|
|
|
|
} = &cli_config;
|
2018-12-12 11:27:21 -08:00
|
|
|
|
2019-12-18 20:50:17 -08:00
|
|
|
let keypair_count = *tx_count * keypair_multiplier;
|
2019-09-10 16:24:43 -07:00
|
|
|
if *write_to_client_file {
|
2019-12-18 20:50:17 -08:00
|
|
|
info!("Generating {} keypairs", keypair_count);
|
2021-06-18 06:34:46 -07:00
|
|
|
let (keypairs, _) = generate_keypairs(id, keypair_count as u64);
|
2019-06-18 14:44:53 -07:00
|
|
|
let num_accounts = keypairs.len() as u64;
|
2019-10-08 22:34:26 -07:00
|
|
|
let max_fee =
|
2020-02-28 12:27:01 -08:00
|
|
|
FeeRateGovernor::new(*target_lamports_per_signature, 0).max_lamports_per_signature;
|
2019-06-18 14:44:53 -07:00
|
|
|
let num_lamports_per_account = (num_accounts - 1 + NUM_SIGNATURES_FOR_TXS * max_fee)
|
|
|
|
/ num_accounts
|
2019-09-10 16:24:43 -07:00
|
|
|
+ num_lamports_per_account;
|
2019-06-11 18:47:35 -07:00
|
|
|
let mut accounts = HashMap::new();
|
|
|
|
keypairs.iter().for_each(|keypair| {
|
|
|
|
accounts.insert(
|
|
|
|
serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap(),
|
2019-10-15 12:52:44 -07:00
|
|
|
Base64Account {
|
2019-09-09 16:17:10 -07:00
|
|
|
balance: num_lamports_per_account,
|
|
|
|
executable: false,
|
|
|
|
owner: system_program::id().to_string(),
|
|
|
|
data: String::new(),
|
|
|
|
},
|
2019-06-11 18:47:35 -07:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2019-10-04 01:16:07 -07:00
|
|
|
info!("Writing {}", client_ids_and_stake_file);
|
2019-06-11 18:47:35 -07:00
|
|
|
let serialized = serde_yaml::to_string(&accounts).unwrap();
|
|
|
|
let path = Path::new(&client_ids_and_stake_file);
|
|
|
|
let mut file = File::create(path).unwrap();
|
|
|
|
file.write_all(&serialized.into_bytes()).unwrap();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-10-04 01:16:07 -07:00
|
|
|
info!("Connecting to the cluster");
|
2021-07-23 08:25:03 -07:00
|
|
|
let nodes = discover_cluster(entrypoint_addr, *num_nodes, SocketAddrSpace::Unspecified)
|
|
|
|
.unwrap_or_else(|err| {
|
|
|
|
eprintln!("Failed to discover {} nodes: {:?}", num_nodes, err);
|
|
|
|
exit(1);
|
|
|
|
});
|
2019-05-27 20:54:44 -07:00
|
|
|
|
2019-10-30 14:43:30 -07:00
|
|
|
let client = if *multi_client {
|
2021-07-23 08:25:03 -07:00
|
|
|
let (client, num_clients) = get_multi_client(&nodes, &SocketAddrSpace::Unspecified);
|
2019-10-30 14:43:30 -07:00
|
|
|
if nodes.len() < num_clients {
|
|
|
|
eprintln!(
|
|
|
|
"Error: Insufficient nodes discovered. Expecting {} or more",
|
|
|
|
num_nodes
|
|
|
|
);
|
|
|
|
exit(1);
|
|
|
|
}
|
2020-01-16 18:35:12 -08:00
|
|
|
Arc::new(client)
|
2020-07-01 21:10:12 -07:00
|
|
|
} else if let Some(target_node) = target_node {
|
|
|
|
info!("Searching for target_node: {:?}", target_node);
|
|
|
|
let mut target_client = None;
|
|
|
|
for node in nodes {
|
|
|
|
if node.id == *target_node {
|
2021-07-23 08:25:03 -07:00
|
|
|
target_client = Some(Arc::new(get_client(&[node], &SocketAddrSpace::Unspecified)));
|
2020-07-01 21:10:12 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
target_client.unwrap_or_else(|| {
|
|
|
|
eprintln!("Target node {} not found", target_node);
|
|
|
|
exit(1);
|
|
|
|
})
|
2019-10-30 14:43:30 -07:00
|
|
|
} else {
|
2021-07-23 08:25:03 -07:00
|
|
|
Arc::new(get_client(&nodes, &SocketAddrSpace::Unspecified))
|
2019-10-30 14:43:30 -07:00
|
|
|
};
|
2019-05-01 17:14:01 -07:00
|
|
|
|
2020-07-23 14:08:59 -07:00
|
|
|
let keypairs = if *read_from_client_file {
|
2019-06-11 18:47:35 -07:00
|
|
|
let path = Path::new(&client_ids_and_stake_file);
|
|
|
|
let file = File::open(path).unwrap();
|
|
|
|
|
2019-10-04 01:16:07 -07:00
|
|
|
info!("Reading {}", client_ids_and_stake_file);
|
2019-10-15 12:52:44 -07:00
|
|
|
let accounts: HashMap<String, Base64Account> = serde_yaml::from_reader(file).unwrap();
|
2019-06-11 18:47:35 -07:00
|
|
|
let mut keypairs = vec![];
|
|
|
|
let mut last_balance = 0;
|
|
|
|
|
2019-09-09 19:48:43 -07:00
|
|
|
accounts
|
|
|
|
.into_iter()
|
|
|
|
.for_each(|(keypair, primordial_account)| {
|
|
|
|
let bytes: Vec<u8> = serde_json::from_str(keypair.as_str()).unwrap();
|
|
|
|
keypairs.push(Keypair::from_bytes(&bytes).unwrap());
|
|
|
|
last_balance = primordial_account.balance;
|
|
|
|
});
|
2019-09-24 18:46:43 -07:00
|
|
|
|
2019-12-18 20:50:17 -08:00
|
|
|
if keypairs.len() < keypair_count {
|
2019-09-24 18:46:43 -07:00
|
|
|
eprintln!(
|
|
|
|
"Expected {} accounts in {}, only received {} (--tx_count mismatch?)",
|
2019-12-18 20:50:17 -08:00
|
|
|
keypair_count,
|
2019-09-24 18:46:43 -07:00
|
|
|
client_ids_and_stake_file,
|
|
|
|
keypairs.len(),
|
|
|
|
);
|
|
|
|
exit(1);
|
|
|
|
}
|
2019-07-23 17:46:33 -07:00
|
|
|
// Sort keypairs so that do_bench_tps() uses the same subset of accounts for each run.
|
|
|
|
// This prevents the amount of storage needed for bench-tps accounts from creeping up
|
|
|
|
// across multiple runs.
|
2020-06-16 09:32:16 -07:00
|
|
|
keypairs.sort_by_key(|x| x.pubkey().to_string());
|
2020-07-23 14:08:59 -07:00
|
|
|
keypairs
|
2019-06-11 18:47:35 -07:00
|
|
|
} else {
|
|
|
|
generate_and_fund_keypairs(
|
2020-01-16 18:35:12 -08:00
|
|
|
client.clone(),
|
2019-12-16 13:05:17 -08:00
|
|
|
Some(*faucet_addr),
|
2021-06-18 06:34:46 -07:00
|
|
|
id,
|
2019-12-18 20:50:17 -08:00
|
|
|
keypair_count,
|
2019-09-10 16:24:43 -07:00
|
|
|
*num_lamports_per_account,
|
2019-06-11 18:47:35 -07:00
|
|
|
)
|
2019-06-12 15:01:59 -07:00
|
|
|
.unwrap_or_else(|e| {
|
|
|
|
eprintln!("Error could not fund keys: {:?}", e);
|
|
|
|
exit(1);
|
|
|
|
})
|
2019-06-11 18:47:35 -07:00
|
|
|
};
|
2019-04-19 14:04:36 -07:00
|
|
|
|
2020-07-23 14:08:59 -07:00
|
|
|
do_bench_tps(client, cli_config, keypairs);
|
2018-09-06 14:20:01 -07:00
|
|
|
}
|