Handle paying for move transactions with unique solana system transactions (#5317)
This commit is contained in:
parent
f859243191
commit
05f3437601
|
@ -70,8 +70,7 @@ pub fn do_bench_tps<T>(
|
||||||
config: Config,
|
config: Config,
|
||||||
gen_keypairs: Vec<Keypair>,
|
gen_keypairs: Vec<Keypair>,
|
||||||
keypair0_balance: u64,
|
keypair0_balance: u64,
|
||||||
program_id: &Pubkey,
|
libra_args: Option<(&Pubkey, &Pubkey, Vec<Keypair>)>,
|
||||||
libra_mint_id: &Pubkey,
|
|
||||||
) -> u64
|
) -> u64
|
||||||
where
|
where
|
||||||
T: 'static + Client + Send + Sync,
|
T: 'static + Client + Send + Sync,
|
||||||
|
@ -82,8 +81,8 @@ where
|
||||||
thread_batch_sleep_ms,
|
thread_batch_sleep_ms,
|
||||||
duration,
|
duration,
|
||||||
tx_count,
|
tx_count,
|
||||||
use_move,
|
|
||||||
sustained,
|
sustained,
|
||||||
|
..
|
||||||
} = config;
|
} = config;
|
||||||
|
|
||||||
let clients: Vec<_> = clients.into_iter().map(Arc::new).collect();
|
let clients: Vec<_> = clients.into_iter().map(Arc::new).collect();
|
||||||
|
@ -175,9 +174,7 @@ where
|
||||||
&keypairs[len..],
|
&keypairs[len..],
|
||||||
threads,
|
threads,
|
||||||
reclaim_lamports_back_to_source_account,
|
reclaim_lamports_back_to_source_account,
|
||||||
use_move,
|
&libra_args,
|
||||||
&program_id,
|
|
||||||
&libra_mint_id,
|
|
||||||
);
|
);
|
||||||
// In sustained mode overlap the transfers with generation
|
// In sustained mode overlap the transfers with generation
|
||||||
// this has higher average performance but lower peak performance
|
// this has higher average performance but lower peak performance
|
||||||
|
@ -234,6 +231,74 @@ fn metrics_submit_lamport_balance(lamport_balance: u64) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_move_txs(
|
||||||
|
source: &[Keypair],
|
||||||
|
dest: &[Keypair],
|
||||||
|
reclaim: bool,
|
||||||
|
move_keypairs: &[Keypair],
|
||||||
|
libra_pay_program_id: &Pubkey,
|
||||||
|
libra_mint_id: &Pubkey,
|
||||||
|
blockhash: &Hash,
|
||||||
|
) -> Vec<(Transaction, u64)> {
|
||||||
|
let count = move_keypairs.len() / 2;
|
||||||
|
let source_move = &move_keypairs[..count];
|
||||||
|
let dest_move = &move_keypairs[count..];
|
||||||
|
let pairs: Vec<_> = if !reclaim {
|
||||||
|
source_move
|
||||||
|
.iter()
|
||||||
|
.zip(dest_move.iter())
|
||||||
|
.zip(source.iter())
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
dest_move
|
||||||
|
.iter()
|
||||||
|
.zip(source_move.iter())
|
||||||
|
.zip(dest.iter())
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
pairs
|
||||||
|
.par_iter()
|
||||||
|
.map(|((from, to), payer)| {
|
||||||
|
(
|
||||||
|
librapay_transaction::transfer(
|
||||||
|
libra_pay_program_id,
|
||||||
|
libra_mint_id,
|
||||||
|
&payer,
|
||||||
|
&from,
|
||||||
|
&to.pubkey(),
|
||||||
|
1,
|
||||||
|
*blockhash,
|
||||||
|
),
|
||||||
|
timestamp(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_solana_txs(
|
||||||
|
source: &[Keypair],
|
||||||
|
dest: &[Keypair],
|
||||||
|
reclaim: bool,
|
||||||
|
blockhash: &Hash,
|
||||||
|
) -> Vec<(Transaction, u64)> {
|
||||||
|
let pairs: Vec<_> = if !reclaim {
|
||||||
|
source.iter().zip(dest.iter()).collect()
|
||||||
|
} else {
|
||||||
|
dest.iter().zip(source.iter()).collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
pairs
|
||||||
|
.par_iter()
|
||||||
|
.map(|(from, to)| {
|
||||||
|
(
|
||||||
|
system_transaction::create_user_account(from, &to.pubkey(), 1, *blockhash),
|
||||||
|
timestamp(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_txs(
|
fn generate_txs(
|
||||||
shared_txs: &SharedTransactions,
|
shared_txs: &SharedTransactions,
|
||||||
blockhash: &Hash,
|
blockhash: &Hash,
|
||||||
|
@ -241,43 +306,25 @@ fn generate_txs(
|
||||||
dest: &[Keypair],
|
dest: &[Keypair],
|
||||||
threads: usize,
|
threads: usize,
|
||||||
reclaim: bool,
|
reclaim: bool,
|
||||||
use_move: bool,
|
libra_args: &Option<(&Pubkey, &Pubkey, Vec<Keypair>)>,
|
||||||
libra_pay_program_id: &Pubkey,
|
|
||||||
libra_mint_id: &Pubkey,
|
|
||||||
) {
|
) {
|
||||||
let tx_count = source.len();
|
let tx_count = source.len();
|
||||||
println!("Signing transactions... {} (reclaim={})", tx_count, reclaim);
|
println!("Signing transactions... {} (reclaim={})", tx_count, reclaim);
|
||||||
let signing_start = Instant::now();
|
let signing_start = Instant::now();
|
||||||
|
|
||||||
let pairs: Vec<_> = if !reclaim {
|
let transactions = if let Some((libra_pay_program_id, libra_mint_id, libra_keys)) = libra_args {
|
||||||
source.iter().zip(dest.iter()).collect()
|
generate_move_txs(
|
||||||
} else {
|
source,
|
||||||
dest.iter().zip(source.iter()).collect()
|
dest,
|
||||||
};
|
reclaim,
|
||||||
let transactions: Vec<_> = pairs
|
&libra_keys,
|
||||||
.par_iter()
|
|
||||||
.map(|(id, keypair)| {
|
|
||||||
if use_move {
|
|
||||||
(
|
|
||||||
librapay_transaction::transfer(
|
|
||||||
libra_pay_program_id,
|
libra_pay_program_id,
|
||||||
libra_mint_id,
|
libra_mint_id,
|
||||||
&id,
|
blockhash,
|
||||||
&id,
|
|
||||||
&keypair.pubkey(),
|
|
||||||
1,
|
|
||||||
*blockhash,
|
|
||||||
),
|
|
||||||
timestamp(),
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
generate_solana_txs(source, dest, reclaim, blockhash)
|
||||||
system_transaction::create_user_account(id, &keypair.pubkey(), 1, *blockhash),
|
};
|
||||||
timestamp(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let duration = signing_start.elapsed();
|
let duration = signing_start.elapsed();
|
||||||
let ns = duration.as_secs() * 1_000_000_000 + u64::from(duration.subsec_nanos());
|
let ns = duration.as_secs() * 1_000_000_000 + u64::from(duration.subsec_nanos());
|
||||||
|
@ -614,11 +661,7 @@ fn should_switch_directions(num_lamports_per_account: u64, i: u64) -> bool {
|
||||||
i % (num_lamports_per_account / 4) == 0 && (i >= (3 * num_lamports_per_account) / 4)
|
i % (num_lamports_per_account / 4) == 0 && (i >= (3 * num_lamports_per_account) / 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_keypairs(
|
pub fn generate_keypairs(seed_keypair: &Keypair, count: u64) -> (Vec<Keypair>, u64) {
|
||||||
seed_keypair: &Keypair,
|
|
||||||
count: u64,
|
|
||||||
use_move: bool,
|
|
||||||
) -> (Vec<Keypair>, u64) {
|
|
||||||
let mut seed = [0u8; 32];
|
let mut seed = [0u8; 32];
|
||||||
seed.copy_from_slice(&seed_keypair.to_bytes()[..32]);
|
seed.copy_from_slice(&seed_keypair.to_bytes()[..32]);
|
||||||
let mut rnd = GenKeys::new(seed);
|
let mut rnd = GenKeys::new(seed);
|
||||||
|
@ -631,14 +674,8 @@ pub fn generate_keypairs(
|
||||||
delta *= MAX_SPENDS_PER_TX;
|
delta *= MAX_SPENDS_PER_TX;
|
||||||
total_keys += delta;
|
total_keys += delta;
|
||||||
}
|
}
|
||||||
if use_move {
|
|
||||||
// Move funding is a naive loop that doesn't
|
|
||||||
// need aligned number of keys.
|
|
||||||
(rnd.gen_n_keypairs(count), extra)
|
|
||||||
} else {
|
|
||||||
(rnd.gen_n_keypairs(total_keys), extra)
|
(rnd.gen_n_keypairs(total_keys), extra)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn fund_move_keys<T: Client>(
|
fn fund_move_keys<T: Client>(
|
||||||
client: &T,
|
client: &T,
|
||||||
|
@ -770,10 +807,9 @@ pub fn generate_and_fund_keypairs<T: Client>(
|
||||||
tx_count: usize,
|
tx_count: usize,
|
||||||
lamports_per_account: u64,
|
lamports_per_account: u64,
|
||||||
libra_keys: Option<(&Pubkey, &Pubkey, &Arc<Keypair>)>,
|
libra_keys: Option<(&Pubkey, &Pubkey, &Arc<Keypair>)>,
|
||||||
) -> Result<(Vec<Keypair>, u64)> {
|
) -> Result<(Vec<Keypair>, Option<Vec<Keypair>>, u64)> {
|
||||||
info!("Creating {} keypairs...", tx_count * 2);
|
info!("Creating {} keypairs...", tx_count * 2);
|
||||||
let (mut keypairs, extra) =
|
let (mut keypairs, extra) = generate_keypairs(funding_key, tx_count as u64 * 2);
|
||||||
generate_keypairs(funding_key, tx_count as u64 * 2, libra_keys.is_some());
|
|
||||||
info!("Get lamports...");
|
info!("Get lamports...");
|
||||||
|
|
||||||
// Sample the first keypair, see if it has lamports, if so then resume.
|
// Sample the first keypair, see if it has lamports, if so then resume.
|
||||||
|
@ -782,26 +818,42 @@ pub fn generate_and_fund_keypairs<T: Client>(
|
||||||
.get_balance(&keypairs[tx_count * 2 - 1].pubkey())
|
.get_balance(&keypairs[tx_count * 2 - 1].pubkey())
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
let mut move_keypairs_ret = None;
|
||||||
|
|
||||||
if lamports_per_account > last_keypair_balance {
|
if lamports_per_account > last_keypair_balance {
|
||||||
let (_blockhash, fee_calculator) = client.get_recent_blockhash().unwrap();
|
let (_blockhash, fee_calculator) = client.get_recent_blockhash().unwrap();
|
||||||
let account_desired_balance =
|
let account_desired_balance =
|
||||||
lamports_per_account - last_keypair_balance + fee_calculator.max_lamports_per_signature;
|
lamports_per_account - last_keypair_balance + fee_calculator.max_lamports_per_signature;
|
||||||
let extra_fees = extra * fee_calculator.max_lamports_per_signature;
|
let extra_fees = extra * fee_calculator.max_lamports_per_signature;
|
||||||
let total = account_desired_balance * (1 + keypairs.len() as u64) + extra_fees;
|
let mut total = account_desired_balance * (1 + keypairs.len() as u64) + extra_fees;
|
||||||
|
if libra_keys.is_some() {
|
||||||
|
total *= 2;
|
||||||
|
}
|
||||||
if client.get_balance(&funding_key.pubkey()).unwrap_or(0) < total {
|
if client.get_balance(&funding_key.pubkey()).unwrap_or(0) < total {
|
||||||
airdrop_lamports(client, &drone_addr.unwrap(), funding_key, total)?;
|
airdrop_lamports(client, &drone_addr.unwrap(), funding_key, total)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((libra_pay_program_id, libra_mint_program_id, libra_mint_key)) = libra_keys {
|
if let Some((libra_pay_program_id, libra_mint_program_id, libra_mint_key)) = libra_keys {
|
||||||
|
// Generate another set of keypairs for move accounts.
|
||||||
|
// Still fund the solana ones which will be used for fees.
|
||||||
|
let seed = [0u8; 32];
|
||||||
|
let mut rnd = GenKeys::new(seed);
|
||||||
|
let move_keypairs = rnd.gen_n_keypairs(tx_count as u64 * 2);
|
||||||
fund_move_keys(
|
fund_move_keys(
|
||||||
client,
|
client,
|
||||||
funding_key,
|
funding_key,
|
||||||
&keypairs,
|
&move_keypairs,
|
||||||
total,
|
total / 2,
|
||||||
libra_pay_program_id,
|
libra_pay_program_id,
|
||||||
libra_mint_program_id,
|
libra_mint_program_id,
|
||||||
libra_mint_key,
|
libra_mint_key,
|
||||||
);
|
);
|
||||||
} else {
|
move_keypairs_ret = Some(move_keypairs);
|
||||||
|
|
||||||
|
// Give solana keys half and move keys half the lamports.
|
||||||
|
total /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
fund_keys(
|
fund_keys(
|
||||||
client,
|
client,
|
||||||
funding_key,
|
funding_key,
|
||||||
|
@ -811,12 +863,11 @@ pub fn generate_and_fund_keypairs<T: Client>(
|
||||||
extra,
|
extra,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 'generate_keypairs' generates extra keys to be able to have size-aligned funding batches for fund_keys.
|
// 'generate_keypairs' generates extra keys to be able to have size-aligned funding batches for fund_keys.
|
||||||
keypairs.truncate(2 * tx_count);
|
keypairs.truncate(2 * tx_count);
|
||||||
|
|
||||||
Ok((keypairs, last_keypair_balance))
|
Ok((keypairs, move_keypairs_ret, last_keypair_balance))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -905,7 +956,7 @@ mod tests {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let (keypairs, _keypair_balance) = generate_and_fund_keypairs(
|
let (keypairs, move_keypairs, _keypair_balance) = generate_and_fund_keypairs(
|
||||||
&client,
|
&client,
|
||||||
Some(drone_addr),
|
Some(drone_addr),
|
||||||
&config.id,
|
&config.id,
|
||||||
|
@ -915,14 +966,14 @@ mod tests {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let total = do_bench_tps(
|
let libra_mint_pubkey = libra_genesis_keypair.pubkey();
|
||||||
vec![client],
|
let move_args = if let Some(keypairs) = move_keypairs {
|
||||||
config,
|
Some((&libra_pay_program_id, &libra_mint_pubkey, keypairs))
|
||||||
keypairs,
|
} else {
|
||||||
0,
|
None
|
||||||
&libra_pay_program_id,
|
};
|
||||||
&libra_genesis_keypair.pubkey(),
|
|
||||||
);
|
let total = do_bench_tps(vec![client], config, keypairs, 0, move_args);
|
||||||
assert!(total > 100);
|
assert!(total > 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -936,11 +987,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn test_bench_tps_local_cluster_move() {
|
fn test_bench_tps_local_cluster_move() {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.tx_count = 100;
|
config.tx_count = 100;
|
||||||
config.duration = Duration::from_secs(10);
|
config.duration = Duration::from_secs(20);
|
||||||
config.use_move = true;
|
config.use_move = true;
|
||||||
|
|
||||||
test_bench_tps_local_cluster(config);
|
test_bench_tps_local_cluster(config);
|
||||||
|
@ -957,18 +1007,11 @@ mod tests {
|
||||||
config.tx_count = 10;
|
config.tx_count = 10;
|
||||||
config.duration = Duration::from_secs(5);
|
config.duration = Duration::from_secs(5);
|
||||||
|
|
||||||
let (keypairs, _keypair_balance) =
|
let (keypairs, _move_keypairs, _keypair_balance) =
|
||||||
generate_and_fund_keypairs(&clients[0], None, &config.id, config.tx_count, 20, None)
|
generate_and_fund_keypairs(&clients[0], None, &config.id, config.tx_count, 20, None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
do_bench_tps(
|
do_bench_tps(clients, config, keypairs, 0, None);
|
||||||
clients,
|
|
||||||
config,
|
|
||||||
keypairs,
|
|
||||||
0,
|
|
||||||
&Pubkey::default(),
|
|
||||||
&Pubkey::default(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -979,7 +1022,7 @@ mod tests {
|
||||||
let tx_count = 10;
|
let tx_count = 10;
|
||||||
let lamports = 20;
|
let lamports = 20;
|
||||||
|
|
||||||
let (keypairs, _keypair_balance) =
|
let (keypairs, _move_keypairs, _keypair_balance) =
|
||||||
generate_and_fund_keypairs(&client, None, &id, tx_count, lamports, None).unwrap();
|
generate_and_fund_keypairs(&client, None, &id, tx_count, lamports, None).unwrap();
|
||||||
|
|
||||||
for kp in &keypairs {
|
for kp in &keypairs {
|
||||||
|
@ -997,7 +1040,7 @@ mod tests {
|
||||||
let tx_count = 10;
|
let tx_count = 10;
|
||||||
let lamports = 20;
|
let lamports = 20;
|
||||||
|
|
||||||
let (keypairs, _keypair_balance) =
|
let (keypairs, _move_keypairs, _keypair_balance) =
|
||||||
generate_and_fund_keypairs(&client, None, &id, tx_count, lamports, None).unwrap();
|
generate_and_fund_keypairs(&client, None, &id, tx_count, lamports, None).unwrap();
|
||||||
|
|
||||||
let max_fee = client
|
let max_fee = client
|
||||||
|
|
|
@ -6,7 +6,6 @@ use crate::bench::{
|
||||||
};
|
};
|
||||||
use solana::gossip_service::{discover_cluster, get_multi_client};
|
use solana::gossip_service::{discover_cluster, get_multi_client};
|
||||||
use solana_sdk::fee_calculator::FeeCalculator;
|
use solana_sdk::fee_calculator::FeeCalculator;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
@ -42,7 +41,7 @@ fn main() {
|
||||||
} = cli_config;
|
} = cli_config;
|
||||||
|
|
||||||
if write_to_client_file {
|
if write_to_client_file {
|
||||||
let (keypairs, _) = generate_keypairs(&id, tx_count as u64 * 2, use_move);
|
let (keypairs, _) = generate_keypairs(&id, tx_count as u64 * 2);
|
||||||
let num_accounts = keypairs.len() as u64;
|
let num_accounts = keypairs.len() as u64;
|
||||||
let max_fee = FeeCalculator::new(target_lamports_per_signature).max_lamports_per_signature;
|
let max_fee = FeeCalculator::new(target_lamports_per_signature).max_lamports_per_signature;
|
||||||
let num_lamports_per_account = (num_accounts - 1 + NUM_SIGNATURES_FOR_TXS * max_fee)
|
let num_lamports_per_account = (num_accounts - 1 + NUM_SIGNATURES_FOR_TXS * max_fee)
|
||||||
|
@ -80,7 +79,7 @@ fn main() {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (keypairs, keypair_balance) = if read_from_client_file {
|
let (keypairs, _move_keypairs, keypair_balance) = if read_from_client_file {
|
||||||
let path = Path::new(&client_ids_and_stake_file);
|
let path = Path::new(&client_ids_and_stake_file);
|
||||||
let file = File::open(path).unwrap();
|
let file = File::open(path).unwrap();
|
||||||
|
|
||||||
|
@ -97,7 +96,7 @@ fn main() {
|
||||||
// This prevents the amount of storage needed for bench-tps accounts from creeping up
|
// This prevents the amount of storage needed for bench-tps accounts from creeping up
|
||||||
// across multiple runs.
|
// across multiple runs.
|
||||||
keypairs.sort_by(|x, y| x.pubkey().to_string().cmp(&y.pubkey().to_string()));
|
keypairs.sort_by(|x, y| x.pubkey().to_string().cmp(&y.pubkey().to_string()));
|
||||||
(keypairs, last_balance)
|
(keypairs, None, last_balance)
|
||||||
} else {
|
} else {
|
||||||
generate_and_fund_keypairs(
|
generate_and_fund_keypairs(
|
||||||
&client,
|
&client,
|
||||||
|
@ -123,12 +122,5 @@ fn main() {
|
||||||
use_move,
|
use_move,
|
||||||
};
|
};
|
||||||
|
|
||||||
do_bench_tps(
|
do_bench_tps(vec![client], config, keypairs, keypair_balance, None);
|
||||||
vec![client],
|
|
||||||
config,
|
|
||||||
keypairs,
|
|
||||||
keypair_balance,
|
|
||||||
&Pubkey::new_rand(),
|
|
||||||
&Pubkey::new_rand(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue