add use_durable_nonce option (#27151)
* add use_durable_nonce option * log creating nonce account in bench-tps * try get account data in a loop * Get account with commitment for nonce in bench-tps * use get_multiple_accounts in bench-tps * split accounts request into chunks
This commit is contained in:
parent
46a48760db
commit
e446c5123e
|
@ -8,8 +8,10 @@ use {
|
||||||
log::*,
|
log::*,
|
||||||
rand::distributions::{Distribution, Uniform},
|
rand::distributions::{Distribution, Uniform},
|
||||||
rayon::prelude::*,
|
rayon::prelude::*,
|
||||||
|
solana_client::{nonce_utils, rpc_request::MAX_MULTIPLE_ACCOUNTS},
|
||||||
solana_metrics::{self, datapoint_info},
|
solana_metrics::{self, datapoint_info},
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
|
account::Account,
|
||||||
clock::{DEFAULT_MS_PER_SLOT, DEFAULT_S_PER_SLOT, MAX_PROCESSING_AGE},
|
clock::{DEFAULT_MS_PER_SLOT, DEFAULT_S_PER_SLOT, MAX_PROCESSING_AGE},
|
||||||
compute_budget::ComputeBudgetInstruction,
|
compute_budget::ComputeBudgetInstruction,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
|
@ -23,7 +25,7 @@ use {
|
||||||
transaction::Transaction,
|
transaction::Transaction,
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
collections::VecDeque,
|
collections::{HashSet, VecDeque},
|
||||||
process::exit,
|
process::exit,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering},
|
atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering},
|
||||||
|
@ -539,16 +541,64 @@ fn transfer_with_compute_unit_price(
|
||||||
Transaction::new(&[from_keypair], message, recent_blockhash)
|
Transaction::new(&[from_keypair], message, recent_blockhash)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_nonce_blockhash<T: 'static + BenchTpsClient + Send + Sync + ?Sized>(
|
fn get_nonce_accounts<T: 'static + BenchTpsClient + Send + Sync + ?Sized>(
|
||||||
client: Arc<T>,
|
client: &Arc<T>,
|
||||||
nonce_account_pubkey: Pubkey,
|
nonce_pubkeys: &[Pubkey],
|
||||||
) -> Hash {
|
) -> Vec<Option<Account>> {
|
||||||
let nonce_account = client
|
// get_multiple_accounts supports maximum MAX_MULTIPLE_ACCOUNTS pubkeys in request
|
||||||
.get_account(&nonce_account_pubkey)
|
assert!(nonce_pubkeys.len() <= MAX_MULTIPLE_ACCOUNTS);
|
||||||
.unwrap_or_else(|error| panic!("{:?}", error));
|
loop {
|
||||||
let nonce_data = solana_rpc_client_nonce_utils::data_from_account(&nonce_account)
|
match client.get_multiple_accounts(nonce_pubkeys) {
|
||||||
.unwrap_or_else(|error| panic!("{:?}", error));
|
Ok(nonce_accounts) => {
|
||||||
nonce_data.blockhash()
|
return nonce_accounts;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
info!("Couldn't get durable nonce account: {:?}", err);
|
||||||
|
sleep(Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_nonce_blockhashes<T: 'static + BenchTpsClient + Send + Sync + ?Sized>(
|
||||||
|
client: &Arc<T>,
|
||||||
|
nonce_pubkeys: &[Pubkey],
|
||||||
|
) -> Vec<Hash> {
|
||||||
|
let num_accounts = nonce_pubkeys.len();
|
||||||
|
let mut blockhashes = vec![Hash::default(); num_accounts];
|
||||||
|
let mut unprocessed = (0..num_accounts).collect::<HashSet<_>>();
|
||||||
|
|
||||||
|
let mut request_pubkeys = Vec::<Pubkey>::with_capacity(num_accounts);
|
||||||
|
let mut request_indexes = Vec::<usize>::with_capacity(num_accounts);
|
||||||
|
|
||||||
|
while !unprocessed.is_empty() {
|
||||||
|
for i in &unprocessed {
|
||||||
|
request_pubkeys.push(nonce_pubkeys[*i]);
|
||||||
|
request_indexes.push(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
let num_unprocessed_before = unprocessed.len();
|
||||||
|
let accounts: Vec<Option<Account>> = nonce_pubkeys
|
||||||
|
.chunks(MAX_MULTIPLE_ACCOUNTS)
|
||||||
|
.flat_map(|pubkeys| get_nonce_accounts(client, pubkeys))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
for (account, index) in accounts.iter().zip(request_indexes.iter()) {
|
||||||
|
if let Some(nonce_account) = account {
|
||||||
|
let nonce_data = nonce_utils::data_from_account(nonce_account).unwrap();
|
||||||
|
blockhashes[*index] = nonce_data.blockhash();
|
||||||
|
unprocessed.remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let num_unprocessed_after = unprocessed.len();
|
||||||
|
debug!(
|
||||||
|
"Received {} durable nonce accounts",
|
||||||
|
num_unprocessed_before - num_unprocessed_after
|
||||||
|
);
|
||||||
|
request_pubkeys.clear();
|
||||||
|
request_indexes.clear();
|
||||||
|
}
|
||||||
|
blockhashes
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_nonced_system_txs<T: 'static + BenchTpsClient + Send + Sync + ?Sized>(
|
fn generate_nonced_system_txs<T: 'static + BenchTpsClient + Send + Sync + ?Sized>(
|
||||||
|
@ -561,34 +611,43 @@ fn generate_nonced_system_txs<T: 'static + BenchTpsClient + Send + Sync + ?Sized
|
||||||
) -> Vec<TimestampedTransaction> {
|
) -> Vec<TimestampedTransaction> {
|
||||||
let length = source.len();
|
let length = source.len();
|
||||||
let mut transactions: Vec<TimestampedTransaction> = Vec::with_capacity(length);
|
let mut transactions: Vec<TimestampedTransaction> = Vec::with_capacity(length);
|
||||||
for i in 0..length {
|
if !reclaim {
|
||||||
let (from, to, nonce, nonce_blockhash) = if !reclaim {
|
let pubkeys: Vec<Pubkey> = source_nonce
|
||||||
(
|
.iter()
|
||||||
source[i],
|
.map(|keypair| keypair.pubkey())
|
||||||
dest[i],
|
.collect();
|
||||||
source_nonce[i],
|
|
||||||
get_nonce_blockhash(client.clone(), source_nonce[i].pubkey()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
dest[i],
|
|
||||||
source[i],
|
|
||||||
dest_nonce[i],
|
|
||||||
get_nonce_blockhash(client.clone(), dest_nonce[i].pubkey()),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
transactions.push((
|
let blockhashes: Vec<Hash> = get_nonce_blockhashes(&client, &pubkeys);
|
||||||
system_transaction::nonced_transfer(
|
for i in 0..length {
|
||||||
from,
|
transactions.push((
|
||||||
&to.pubkey(),
|
system_transaction::nonced_transfer(
|
||||||
1,
|
source[i],
|
||||||
&nonce.pubkey(),
|
&dest[i].pubkey(),
|
||||||
from,
|
1,
|
||||||
nonce_blockhash,
|
&source_nonce[i].pubkey(),
|
||||||
),
|
source[i],
|
||||||
None,
|
blockhashes[i],
|
||||||
));
|
),
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let pubkeys: Vec<Pubkey> = dest_nonce.iter().map(|keypair| keypair.pubkey()).collect();
|
||||||
|
let blockhashes: Vec<Hash> = get_nonce_blockhashes(&client, &pubkeys);
|
||||||
|
|
||||||
|
for i in 0..length {
|
||||||
|
transactions.push((
|
||||||
|
system_transaction::nonced_transfer(
|
||||||
|
dest[i],
|
||||||
|
&source[i].pubkey(),
|
||||||
|
1,
|
||||||
|
&dest_nonce[i].pubkey(),
|
||||||
|
dest[i],
|
||||||
|
blockhashes[i],
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
transactions
|
transactions
|
||||||
}
|
}
|
||||||
|
|
|
@ -313,6 +313,11 @@ pub fn build_args<'a, 'b>(version: &'b str) -> App<'a, 'b> {
|
||||||
.takes_value(false)
|
.takes_value(false)
|
||||||
.help("Sets random compute-unit-price in range [0..100] to transfer transactions"),
|
.help("Sets random compute-unit-price in range [0..100] to transfer transactions"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("use_durable_nonce")
|
||||||
|
.long("use-durable-nonce")
|
||||||
|
.help("Use durable transaction nonce instead of recent blockhash"),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a clap `ArgMatches` structure into a `Config`
|
/// Parses a clap `ArgMatches` structure into a `Config`
|
||||||
|
@ -447,5 +452,9 @@ pub fn extract_args(matches: &ArgMatches) -> Config {
|
||||||
args.use_randomized_compute_unit_price = true;
|
args.use_randomized_compute_unit_price = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if matches.is_present("use_durable_nonce") {
|
||||||
|
args.use_durable_nonce = true;
|
||||||
|
}
|
||||||
|
|
||||||
args
|
args
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,7 @@ pub fn generate_durable_nonce_accounts<T: 'static + BenchTpsClient + Send + Sync
|
||||||
let (mut nonce_keypairs, _extra) = generate_keypairs(seed_keypair, count as u64);
|
let (mut nonce_keypairs, _extra) = generate_keypairs(seed_keypair, count as u64);
|
||||||
nonce_keypairs.truncate(count);
|
nonce_keypairs.truncate(count);
|
||||||
|
|
||||||
|
info!("Creating {} nonce accounts...", count);
|
||||||
let to_fund: Vec<NonceCreateSigners> = authority_keypairs
|
let to_fund: Vec<NonceCreateSigners> = authority_keypairs
|
||||||
.iter()
|
.iter()
|
||||||
.zip(nonce_keypairs.iter())
|
.zip(nonce_keypairs.iter())
|
||||||
|
|
Loading…
Reference in New Issue