Revert solana-tokens to RpcClient (#13623)

* Revert solana-tokens to RpcClient

* Fixup check_payer_balances tests

* Use RpcClient::new_with_commitment in other tests

Co-authored-by: Tyera Eulberg <tyera@solana.com>
This commit is contained in:
Greg Fitzgerald 2020-11-17 14:53:49 -07:00 committed by GitHub
parent 645598e615
commit 47fbfc52de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 480 additions and 483 deletions

5
Cargo.lock generated
View File

@ -4958,8 +4958,6 @@ dependencies = [
"indicatif", "indicatif",
"pickledb", "pickledb",
"serde", "serde",
"solana-banks-client",
"solana-banks-server",
"solana-clap-utils", "solana-clap-utils",
"solana-cli-config", "solana-cli-config",
"solana-client", "solana-client",
@ -4969,10 +4967,9 @@ dependencies = [
"solana-runtime", "solana-runtime",
"solana-sdk", "solana-sdk",
"solana-stake-program", "solana-stake-program",
"solana-transaction-status",
"tempfile", "tempfile",
"thiserror", "thiserror",
"tokio 0.3.2",
"url 2.1.1",
] ]
[[package]] [[package]]

View File

@ -18,7 +18,6 @@ indexmap = "1.5.1"
indicatif = "0.15.0" indicatif = "0.15.0"
pickledb = "0.4.1" pickledb = "0.4.1"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
solana-banks-client = { path = "../banks-client", version = "1.5.0" }
solana-clap-utils = { path = "../clap-utils", version = "1.5.0" } solana-clap-utils = { path = "../clap-utils", version = "1.5.0" }
solana-cli-config = { path = "../cli-config", version = "1.5.0" } solana-cli-config = { path = "../cli-config", version = "1.5.0" }
solana-client = { path = "../client", version = "1.5.0" } solana-client = { path = "../client", version = "1.5.0" }
@ -26,14 +25,11 @@ solana-remote-wallet = { path = "../remote-wallet", version = "1.5.0" }
solana-runtime = { path = "../runtime", version = "1.5.0" } solana-runtime = { path = "../runtime", version = "1.5.0" }
solana-sdk = { path = "../sdk", version = "1.5.0" } solana-sdk = { path = "../sdk", version = "1.5.0" }
solana-stake-program = { path = "../programs/stake", version = "1.5.0" } solana-stake-program = { path = "../programs/stake", version = "1.5.0" }
solana-transaction-status = { path = "../transaction-status", version = "1.5.0" }
tempfile = "3.1.0" tempfile = "3.1.0"
thiserror = "1.0" thiserror = "1.0"
tokio = { version = "0.3", features = ["full"] }
url = "2.1"
[dev-dependencies] [dev-dependencies]
bincode = "1.3.1" bincode = "1.3.1"
solana-banks-server = { path = "../banks-server", version = "1.5.0" }
solana-core = { path = "../core", version = "1.5.0" } solana-core = { path = "../core", version = "1.5.0" }
solana-logger = { path = "../logger", version = "1.5.0" } solana-logger = { path = "../logger", version = "1.5.0" }
solana-runtime = { path = "../runtime", version = "1.5.0" }

View File

@ -7,16 +7,19 @@ use indexmap::IndexMap;
use indicatif::{ProgressBar, ProgressStyle}; use indicatif::{ProgressBar, ProgressStyle};
use pickledb::PickleDb; use pickledb::PickleDb;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use solana_banks_client::BanksClient; use solana_client::{
client_error::{ClientError, Result as ClientResult},
rpc_client::RpcClient,
rpc_config::RpcSendTransactionConfig,
};
use solana_sdk::{ use solana_sdk::{
commitment_config::CommitmentLevel, commitment_config::CommitmentConfig,
instruction::Instruction, instruction::Instruction,
message::Message, message::Message,
native_token::{lamports_to_sol, sol_to_lamports}, native_token::{lamports_to_sol, sol_to_lamports},
signature::{unique_signers, Signature, Signer}, signature::{unique_signers, Signature, Signer},
system_instruction, system_instruction,
transaction::Transaction, transaction::Transaction,
transport::{self, TransportError},
}; };
use solana_stake_program::{ use solana_stake_program::{
stake_instruction::{self, LockupArgs}, stake_instruction::{self, LockupArgs},
@ -25,9 +28,9 @@ use solana_stake_program::{
use std::{ use std::{
cmp::{self}, cmp::{self},
io, io,
thread::sleep,
time::Duration, time::Duration,
}; };
use tokio::time::sleep;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
struct Allocation { struct Allocation {
@ -78,7 +81,7 @@ pub enum Error {
#[error("PickleDb error")] #[error("PickleDb error")]
PickleDbError(#[from] pickledb::error::Error), PickleDbError(#[from] pickledb::error::Error),
#[error("Transport error")] #[error("Transport error")]
TransportError(#[from] TransportError), ClientError(#[from] ClientError),
#[error("Missing lockup authority")] #[error("Missing lockup authority")]
MissingLockupAuthority, MissingLockupAuthority,
#[error("insufficient funds in {0:?}, requires {1} SOL")] #[error("insufficient funds in {0:?}, requires {1} SOL")]
@ -128,16 +131,16 @@ fn apply_previous_transactions(
allocations.retain(|x| x.amount > 0.5); allocations.retain(|x| x.amount > 0.5);
} }
async fn transfer<S: Signer>( fn transfer<S: Signer>(
client: &mut BanksClient, client: &RpcClient,
lamports: u64, lamports: u64,
sender_keypair: &S, sender_keypair: &S,
to_pubkey: &Pubkey, to_pubkey: &Pubkey,
) -> io::Result<Transaction> { ) -> ClientResult<Transaction> {
let create_instruction = let create_instruction =
system_instruction::transfer(&sender_keypair.pubkey(), &to_pubkey, lamports); system_instruction::transfer(&sender_keypair.pubkey(), &to_pubkey, lamports);
let message = Message::new(&[create_instruction], Some(&sender_keypair.pubkey())); let message = Message::new(&[create_instruction], Some(&sender_keypair.pubkey()));
let recent_blockhash = client.get_recent_blockhash().await?; let (recent_blockhash, _fees) = client.get_recent_blockhash()?;
Ok(Transaction::new( Ok(Transaction::new(
&[sender_keypair], &[sender_keypair],
message, message,
@ -218,8 +221,8 @@ fn distribution_instructions(
instructions instructions
} }
async fn distribute_allocations( fn distribute_allocations(
client: &mut BanksClient, client: &RpcClient,
db: &mut PickleDb, db: &mut PickleDb,
allocations: &[Allocation], allocations: &[Allocation],
args: &DistributeTokensArgs, args: &DistributeTokensArgs,
@ -252,7 +255,7 @@ async fn distribute_allocations(
.iter() .iter()
.map(|message| message.header.num_required_signatures as usize) .map(|message| message.header.num_required_signatures as usize)
.sum(); .sum();
check_payer_balances(num_signatures, allocations, client, args).await?; check_payer_balances(num_signatures, allocations, client, args)?;
for ((allocation, message), (new_stake_account_keypair, lockup_date)) in for ((allocation, message), (new_stake_account_keypair, lockup_date)) in
allocations.iter().zip(messages).zip(stake_extras) allocations.iter().zip(messages).zip(stake_extras)
@ -273,13 +276,19 @@ async fn distribute_allocations(
} }
} }
let signers = unique_signers(signers); let signers = unique_signers(signers);
let result: transport::Result<(Transaction, u64)> = { let result: ClientResult<(Transaction, u64)> = {
if args.dry_run { if args.dry_run {
Ok((Transaction::new_unsigned(message), std::u64::MAX)) Ok((Transaction::new_unsigned(message), std::u64::MAX))
} else { } else {
let (_fee_calculator, blockhash, last_valid_slot) = client.get_fees().await?; let (blockhash, _fee_calculator, last_valid_slot) = client
.get_recent_blockhash_with_commitment(CommitmentConfig::default())?
.value;
let transaction = Transaction::new(&signers, message, blockhash); let transaction = Transaction::new(&signers, message, blockhash);
client.send_transaction(transaction.clone()).await?; let config = RpcSendTransactionConfig {
skip_preflight: true,
..RpcSendTransactionConfig::default()
};
client.send_transaction_with_config(&transaction, config)?;
Ok((transaction, last_valid_slot)) Ok((transaction, last_valid_slot))
} }
}; };
@ -333,8 +342,8 @@ fn new_spinner_progress_bar() -> ProgressBar {
progress_bar progress_bar
} }
pub async fn process_allocations( pub fn process_allocations(
client: &mut BanksClient, client: &RpcClient,
args: &DistributeTokensArgs, args: &DistributeTokensArgs,
) -> Result<Option<usize>, Error> { ) -> Result<Option<usize>, Error> {
let mut allocations: Vec<Allocation> = read_allocations(&args.input_csv, args.transfer_amount)?; let mut allocations: Vec<Allocation> = read_allocations(&args.input_csv, args.transfer_amount)?;
@ -349,7 +358,7 @@ pub async fn process_allocations(
let mut db = db::open_db(&args.transaction_db, args.dry_run)?; let mut db = db::open_db(&args.transaction_db, args.dry_run)?;
// Start by finalizing any transactions from the previous run. // Start by finalizing any transactions from the previous run.
let confirmations = finalize_transactions(client, &mut db, args.dry_run).await?; let confirmations = finalize_transactions(client, &mut db, args.dry_run)?;
let transaction_infos = db::read_transaction_infos(&db); let transaction_infos = db::read_transaction_infos(&db);
apply_previous_transactions(&mut allocations, &transaction_infos); apply_previous_transactions(&mut allocations, &transaction_infos);
@ -382,9 +391,9 @@ pub async fn process_allocations(
.bold() .bold()
); );
distribute_allocations(client, &mut db, &allocations, args).await?; distribute_allocations(client, &mut db, &allocations, args)?;
let opt_confirmations = finalize_transactions(client, &mut db, args.dry_run).await?; let opt_confirmations = finalize_transactions(client, &mut db, args.dry_run)?;
if !args.dry_run { if !args.dry_run {
if let Some(output_path) = &args.output_path { if let Some(output_path) = &args.output_path {
@ -395,8 +404,8 @@ pub async fn process_allocations(
Ok(opt_confirmations) Ok(opt_confirmations)
} }
async fn finalize_transactions( fn finalize_transactions(
client: &mut BanksClient, client: &RpcClient,
db: &mut PickleDb, db: &mut PickleDb,
dry_run: bool, dry_run: bool,
) -> Result<Option<usize>, Error> { ) -> Result<Option<usize>, Error> {
@ -404,7 +413,7 @@ async fn finalize_transactions(
return Ok(None); return Ok(None);
} }
let mut opt_confirmations = update_finalized_transactions(client, db).await?; let mut opt_confirmations = update_finalized_transactions(client, db)?;
let progress_bar = new_spinner_progress_bar(); let progress_bar = new_spinner_progress_bar();
@ -417,8 +426,8 @@ async fn finalize_transactions(
} }
// Sleep for about 1 slot // Sleep for about 1 slot
sleep(Duration::from_millis(500)).await; sleep(Duration::from_millis(500));
let opt_conf = update_finalized_transactions(client, db).await?; let opt_conf = update_finalized_transactions(client, db)?;
opt_confirmations = opt_conf; opt_confirmations = opt_conf;
} }
@ -427,8 +436,8 @@ async fn finalize_transactions(
// Update the finalized bit on any transactions that are now rooted // Update the finalized bit on any transactions that are now rooted
// Return the lowest number of confirmations on the unfinalized transactions or None if all are finalized. // Return the lowest number of confirmations on the unfinalized transactions or None if all are finalized.
async fn update_finalized_transactions( fn update_finalized_transactions(
client: &mut BanksClient, client: &RpcClient,
db: &mut PickleDb, db: &mut PickleDb,
) -> Result<Option<usize>, Error> { ) -> Result<Option<usize>, Error> {
let transaction_infos = db::read_transaction_infos(db); let transaction_infos = db::read_transaction_infos(db);
@ -448,9 +457,9 @@ async fn update_finalized_transactions(
.filter(|sig| *sig != Signature::default()) // Filter out dry-run signatures .filter(|sig| *sig != Signature::default()) // Filter out dry-run signatures
.collect(); .collect();
let transaction_statuses = client let transaction_statuses = client
.get_transaction_statuses(unconfirmed_signatures) .get_signature_statuses(&unconfirmed_signatures)?
.await?; .value;
let root_slot = client.get_root_slot().await?; let root_slot = client.get_slot()?;
let mut confirmations = None; let mut confirmations = None;
for ((transaction, last_valid_slot), opt_transaction_status) in unconfirmed_transactions for ((transaction, last_valid_slot), opt_transaction_status) in unconfirmed_transactions
@ -475,15 +484,15 @@ async fn update_finalized_transactions(
Ok(confirmations) Ok(confirmations)
} }
async fn check_payer_balances( fn check_payer_balances(
num_signatures: usize, num_signatures: usize,
allocations: &[Allocation], allocations: &[Allocation],
client: &mut BanksClient, client: &RpcClient,
args: &DistributeTokensArgs, args: &DistributeTokensArgs,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut undistributed_tokens: f64 = allocations.iter().map(|x| x.amount).sum(); let mut undistributed_tokens: f64 = allocations.iter().map(|x| x.amount).sum();
let (fee_calculator, _blockhash, _last_valid_slot) = client.get_fees().await?; let (_blockhash, fee_calculator) = client.get_recent_blockhash()?;
let fees = fee_calculator let fees = fee_calculator
.lamports_per_signature .lamports_per_signature
.checked_mul(num_signatures as u64) .checked_mul(num_signatures as u64)
@ -505,7 +514,7 @@ async fn check_payer_balances(
let allocation_lamports = sol_to_lamports(undistributed_tokens); let allocation_lamports = sol_to_lamports(undistributed_tokens);
if let Some((unlocked_sol_source, total_unlocked_sol)) = unlocked_sol_source { if let Some((unlocked_sol_source, total_unlocked_sol)) = unlocked_sol_source {
let staker_balance = client.get_balance(distribution_source).await?; let staker_balance = client.get_balance(&distribution_source)?;
if staker_balance < allocation_lamports { if staker_balance < allocation_lamports {
return Err(Error::InsufficientFunds( return Err(Error::InsufficientFunds(
vec![FundingSource::StakeAccount].into(), vec![FundingSource::StakeAccount].into(),
@ -513,7 +522,7 @@ async fn check_payer_balances(
)); ));
} }
if args.fee_payer.pubkey() == unlocked_sol_source { if args.fee_payer.pubkey() == unlocked_sol_source {
let balance = client.get_balance(args.fee_payer.pubkey()).await?; let balance = client.get_balance(&args.fee_payer.pubkey())?;
if balance < fees + total_unlocked_sol { if balance < fees + total_unlocked_sol {
return Err(Error::InsufficientFunds( return Err(Error::InsufficientFunds(
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into(), vec![FundingSource::SystemAccount, FundingSource::FeePayer].into(),
@ -521,14 +530,14 @@ async fn check_payer_balances(
)); ));
} }
} else { } else {
let fee_payer_balance = client.get_balance(args.fee_payer.pubkey()).await?; let fee_payer_balance = client.get_balance(&args.fee_payer.pubkey())?;
if fee_payer_balance < fees { if fee_payer_balance < fees {
return Err(Error::InsufficientFunds( return Err(Error::InsufficientFunds(
vec![FundingSource::FeePayer].into(), vec![FundingSource::FeePayer].into(),
lamports_to_sol(fees), lamports_to_sol(fees),
)); ));
} }
let unlocked_sol_balance = client.get_balance(unlocked_sol_source).await?; let unlocked_sol_balance = client.get_balance(&unlocked_sol_source)?;
if unlocked_sol_balance < total_unlocked_sol { if unlocked_sol_balance < total_unlocked_sol {
return Err(Error::InsufficientFunds( return Err(Error::InsufficientFunds(
vec![FundingSource::SystemAccount].into(), vec![FundingSource::SystemAccount].into(),
@ -537,7 +546,7 @@ async fn check_payer_balances(
} }
} }
} else if args.fee_payer.pubkey() == distribution_source { } else if args.fee_payer.pubkey() == distribution_source {
let balance = client.get_balance(args.fee_payer.pubkey()).await?; let balance = client.get_balance(&args.fee_payer.pubkey())?;
if balance < fees + allocation_lamports { if balance < fees + allocation_lamports {
return Err(Error::InsufficientFunds( return Err(Error::InsufficientFunds(
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into(), vec![FundingSource::SystemAccount, FundingSource::FeePayer].into(),
@ -545,14 +554,14 @@ async fn check_payer_balances(
)); ));
} }
} else { } else {
let fee_payer_balance = client.get_balance(args.fee_payer.pubkey()).await?; let fee_payer_balance = client.get_balance(&args.fee_payer.pubkey())?;
if fee_payer_balance < fees { if fee_payer_balance < fees {
return Err(Error::InsufficientFunds( return Err(Error::InsufficientFunds(
vec![FundingSource::FeePayer].into(), vec![FundingSource::FeePayer].into(),
lamports_to_sol(fees), lamports_to_sol(fees),
)); ));
} }
let sender_balance = client.get_balance(distribution_source).await?; let sender_balance = client.get_balance(&distribution_source)?;
if sender_balance < allocation_lamports { if sender_balance < allocation_lamports {
return Err(Error::InsufficientFunds( return Err(Error::InsufficientFunds(
vec![FundingSource::SystemAccount].into(), vec![FundingSource::SystemAccount].into(),
@ -563,10 +572,7 @@ async fn check_payer_balances(
Ok(()) Ok(())
} }
pub async fn process_balances( pub fn process_balances(client: &RpcClient, args: &BalancesArgs) -> Result<(), csv::Error> {
client: &mut BanksClient,
args: &BalancesArgs,
) -> Result<(), csv::Error> {
let allocations: Vec<Allocation> = read_allocations(&args.input_csv, None)?; let allocations: Vec<Allocation> = read_allocations(&args.input_csv, None)?;
let allocations = merge_allocations(&allocations); let allocations = merge_allocations(&allocations);
@ -582,7 +588,7 @@ pub async fn process_balances(
for allocation in &allocations { for allocation in &allocations {
let address = allocation.recipient.parse().unwrap(); let address = allocation.recipient.parse().unwrap();
let expected = lamports_to_sol(sol_to_lamports(allocation.amount)); let expected = lamports_to_sol(sol_to_lamports(allocation.amount));
let actual = lamports_to_sol(client.get_balance(address).await.unwrap()); let actual = lamports_to_sol(client.get_balance(&address).unwrap());
println!( println!(
"{:<44} {:>24.9} {:>24.9} {:>24.9}", "{:<44} {:>24.9} {:>24.9} {:>24.9}",
allocation.recipient, allocation.recipient,
@ -604,8 +610,8 @@ pub fn process_transaction_log(args: &TransactionLogArgs) -> Result<(), Error> {
use crate::db::check_output_file; use crate::db::check_output_file;
use solana_sdk::{pubkey::Pubkey, signature::Keypair}; use solana_sdk::{pubkey::Pubkey, signature::Keypair};
use tempfile::{tempdir, NamedTempFile}; use tempfile::{tempdir, NamedTempFile};
pub async fn test_process_distribute_tokens_with_client( pub fn test_process_distribute_tokens_with_client(
client: &mut BanksClient, client: &RpcClient,
sender_keypair: Keypair, sender_keypair: Keypair,
transfer_amount: Option<f64>, transfer_amount: Option<f64>,
) { ) {
@ -616,17 +622,12 @@ pub async fn test_process_distribute_tokens_with_client(
&sender_keypair, &sender_keypair,
&fee_payer.pubkey(), &fee_payer.pubkey(),
) )
.await
.unwrap(); .unwrap();
client client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent) .send_and_confirm_transaction_with_spinner(&transaction)
.await
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
client client.get_balance(&fee_payer.pubkey()).unwrap(),
.get_balance_with_commitment(fee_payer.pubkey(), CommitmentLevel::Recent)
.await
.unwrap(),
sol_to_lamports(1.0), sol_to_lamports(1.0),
); );
@ -667,7 +668,7 @@ pub async fn test_process_distribute_tokens_with_client(
stake_args: None, stake_args: None,
transfer_amount, transfer_amount,
}; };
let confirmations = process_allocations(client, &args).await.unwrap(); let confirmations = process_allocations(client, &args).unwrap();
assert_eq!(confirmations, None); assert_eq!(confirmations, None);
let transaction_infos = let transaction_infos =
@ -680,15 +681,12 @@ pub async fn test_process_distribute_tokens_with_client(
expected_amount expected_amount
); );
assert_eq!( assert_eq!(client.get_balance(&alice_pubkey).unwrap(), expected_amount,);
client.get_balance(alice_pubkey).await.unwrap(),
expected_amount,
);
check_output_file(&output_path, &db::open_db(&transaction_db, true).unwrap()); check_output_file(&output_path, &db::open_db(&transaction_db, true).unwrap());
// Now, run it again, and check there's no double-spend. // Now, run it again, and check there's no double-spend.
process_allocations(client, &args).await.unwrap(); process_allocations(client, &args).unwrap();
let transaction_infos = let transaction_infos =
db::read_transaction_infos(&db::open_db(&transaction_db, true).unwrap()); db::read_transaction_infos(&db::open_db(&transaction_db, true).unwrap());
assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos.len(), 1);
@ -699,18 +697,12 @@ pub async fn test_process_distribute_tokens_with_client(
expected_amount expected_amount
); );
assert_eq!( assert_eq!(client.get_balance(&alice_pubkey).unwrap(), expected_amount,);
client.get_balance(alice_pubkey).await.unwrap(),
expected_amount,
);
check_output_file(&output_path, &db::open_db(&transaction_db, true).unwrap()); check_output_file(&output_path, &db::open_db(&transaction_db, true).unwrap());
} }
pub async fn test_process_distribute_stake_with_client( pub fn test_process_distribute_stake_with_client(client: &RpcClient, sender_keypair: Keypair) {
client: &mut BanksClient,
sender_keypair: Keypair,
) {
let fee_payer = Keypair::new(); let fee_payer = Keypair::new();
let transaction = transfer( let transaction = transfer(
client, client,
@ -718,11 +710,9 @@ pub async fn test_process_distribute_stake_with_client(
&sender_keypair, &sender_keypair,
&fee_payer.pubkey(), &fee_payer.pubkey(),
) )
.await
.unwrap(); .unwrap();
client client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent) .send_and_confirm_transaction_with_spinner(&transaction)
.await
.unwrap(); .unwrap();
let stake_account_keypair = Keypair::new(); let stake_account_keypair = Keypair::new();
@ -744,11 +734,10 @@ pub async fn test_process_distribute_stake_with_client(
); );
let message = Message::new(&instructions, Some(&sender_keypair.pubkey())); let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
let signers = [&sender_keypair, &stake_account_keypair]; let signers = [&sender_keypair, &stake_account_keypair];
let blockhash = client.get_recent_blockhash().await.unwrap(); let (blockhash, _fees) = client.get_recent_blockhash().unwrap();
let transaction = Transaction::new(&signers, message, blockhash); let transaction = Transaction::new(&signers, message, blockhash);
client client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent) .send_and_confirm_transaction_with_spinner(&transaction)
.await
.unwrap(); .unwrap();
let alice_pubkey = solana_sdk::pubkey::new_rand(); let alice_pubkey = solana_sdk::pubkey::new_rand();
@ -791,7 +780,7 @@ pub async fn test_process_distribute_stake_with_client(
sender_keypair: Box::new(sender_keypair), sender_keypair: Box::new(sender_keypair),
transfer_amount: None, transfer_amount: None,
}; };
let confirmations = process_allocations(client, &args).await.unwrap(); let confirmations = process_allocations(client, &args).unwrap();
assert_eq!(confirmations, None); assert_eq!(confirmations, None);
let transaction_infos = let transaction_infos =
@ -805,19 +794,19 @@ pub async fn test_process_distribute_stake_with_client(
); );
assert_eq!( assert_eq!(
client.get_balance(alice_pubkey).await.unwrap(), client.get_balance(&alice_pubkey).unwrap(),
sol_to_lamports(1.0), sol_to_lamports(1.0),
); );
let new_stake_account_address = transaction_infos[0].new_stake_account_address.unwrap(); let new_stake_account_address = transaction_infos[0].new_stake_account_address.unwrap();
assert_eq!( assert_eq!(
client.get_balance(new_stake_account_address).await.unwrap(), client.get_balance(&new_stake_account_address).unwrap(),
expected_amount - sol_to_lamports(1.0), expected_amount - sol_to_lamports(1.0),
); );
check_output_file(&output_path, &db::open_db(&transaction_db, true).unwrap()); check_output_file(&output_path, &db::open_db(&transaction_db, true).unwrap());
// Now, run it again, and check there's no double-spend. // Now, run it again, and check there's no double-spend.
process_allocations(client, &args).await.unwrap(); process_allocations(client, &args).unwrap();
let transaction_infos = let transaction_infos =
db::read_transaction_infos(&db::open_db(&transaction_db, true).unwrap()); db::read_transaction_infos(&db::open_db(&transaction_db, true).unwrap());
assert_eq!(transaction_infos.len(), 1); assert_eq!(transaction_infos.len(), 1);
@ -829,11 +818,11 @@ pub async fn test_process_distribute_stake_with_client(
); );
assert_eq!( assert_eq!(
client.get_balance(alice_pubkey).await.unwrap(), client.get_balance(&alice_pubkey).unwrap(),
sol_to_lamports(1.0), sol_to_lamports(1.0),
); );
assert_eq!( assert_eq!(
client.get_balance(new_stake_account_address).await.unwrap(), client.get_balance(&new_stake_account_address).unwrap(),
expected_amount - sol_to_lamports(1.0), expected_amount - sol_to_lamports(1.0),
); );
@ -843,55 +832,67 @@ pub async fn test_process_distribute_stake_with_client(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use solana_banks_client::start_client; use solana_client::rpc_client::get_rpc_request_str;
use solana_banks_server::banks_server::start_local_server; use solana_core::test_validator::TestValidator;
use solana_runtime::{bank::Bank, bank_forks::BankForks};
use solana_sdk::{ use solana_sdk::{
fee_calculator::FeeRateGovernor, clock::DEFAULT_MS_PER_SLOT,
genesis_config::create_genesis_config,
signature::{read_keypair_file, write_keypair_file}, signature::{read_keypair_file, write_keypair_file},
}; };
use solana_stake_program::stake_instruction::StakeInstruction; use solana_stake_program::stake_instruction::StakeInstruction;
use std::sync::{Arc, RwLock}; use std::fs::remove_dir_all;
use tokio::runtime::Runtime;
#[test] #[test]
fn test_process_token_allocations() { fn test_process_token_allocations() {
let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); let TestValidator {
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config)))); server,
Runtime::new().unwrap().block_on(async { leader_data,
let transport = start_local_server(&bank_forks).await; alice,
let mut banks_client = start_client(transport).await.unwrap(); ledger_path,
test_process_distribute_tokens_with_client(&mut banks_client, sender_keypair, None) ..
.await; } = TestValidator::run();
}); let url = get_rpc_request_str(leader_data.rpc, false);
let client = RpcClient::new_with_commitment(url, CommitmentConfig::recent());
test_process_distribute_tokens_with_client(&client, alice, None);
// Explicit cleanup, otherwise "pure virtual method called" crash in Docker
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
} }
#[test] #[test]
fn test_process_transfer_amount_allocations() { fn test_process_transfer_amount_allocations() {
let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); let TestValidator {
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config)))); server,
Runtime::new().unwrap().block_on(async { leader_data,
let transport = start_local_server(&bank_forks).await; alice,
let mut banks_client = start_client(transport).await.unwrap(); ledger_path,
test_process_distribute_tokens_with_client( ..
&mut banks_client, } = TestValidator::run();
sender_keypair, let url = get_rpc_request_str(leader_data.rpc, false);
Some(1.5), let client = RpcClient::new_with_commitment(url, CommitmentConfig::recent());
) test_process_distribute_tokens_with_client(&client, alice, Some(1.5));
.await;
}); // Explicit cleanup, otherwise "pure virtual method called" crash in Docker
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
} }
#[test] #[test]
fn test_process_stake_allocations() { fn test_process_stake_allocations() {
let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0)); let TestValidator {
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config)))); server,
Runtime::new().unwrap().block_on(async { leader_data,
let transport = start_local_server(&bank_forks).await; alice,
let mut banks_client = start_client(transport).await.unwrap(); ledger_path,
test_process_distribute_stake_with_client(&mut banks_client, sender_keypair).await; ..
}); } = TestValidator::run();
let url = get_rpc_request_str(leader_data.rpc, false);
let client = RpcClient::new_with_commitment(url, CommitmentConfig::recent());
test_process_distribute_stake_with_client(&client, alice);
// Explicit cleanup, otherwise "pure virtual method called" crash in Docker
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
} }
#[test] #[test]
@ -1115,16 +1116,28 @@ mod tests {
fn test_check_payer_balances_distribute_tokens_single_payer() { fn test_check_payer_balances_distribute_tokens_single_payer() {
let fees = 10_000; let fees = 10_000;
let fees_in_sol = lamports_to_sol(fees); let fees_in_sol = lamports_to_sol(fees);
let (mut genesis_config, sender_keypair) = let TestValidator {
create_genesis_config(sol_to_lamports(9_000_000.0)); server,
genesis_config.fee_rate_governor = FeeRateGovernor::new(fees, 0); leader_data,
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config)))); alice,
Runtime::new().unwrap().block_on(async { ledger_path,
let transport = start_local_server(&bank_forks).await; ..
let mut banks_client = start_client(transport).await.unwrap(); } = TestValidator::run_with_fees(fees);
let url = get_rpc_request_str(leader_data.rpc, false);
let client = RpcClient::new_with_commitment(url, CommitmentConfig::recent());
let sender_keypair_file = tmp_file_path("keypair_file", &alice.pubkey());
write_keypair_file(&alice, &sender_keypair_file).unwrap();
let sender_keypair_file = tmp_file_path("keypair_file", &sender_keypair.pubkey()); // This is a quick hack until TestValidator can be initialized with fees from block 0
write_keypair_file(&sender_keypair, &sender_keypair_file).unwrap(); while client
.get_recent_blockhash()
.unwrap()
.1
.lamports_per_signature
== 0
{
sleep(Duration::from_millis(DEFAULT_MS_PER_SLOT));
}
let allocation_amount = 1000.0; let allocation_amount = 1000.0;
@ -1135,14 +1148,11 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
None, None,
); );
check_payer_balances(1, &allocations, &mut banks_client, &args) check_payer_balances(1, &allocations, &client, &args).unwrap();
.await
.unwrap();
// Unfunded payer // Unfunded payer
let unfunded_payer = Keypair::new(); let unfunded_payer = Keypair::new();
let unfunded_payer_keypair_file = let unfunded_payer_keypair_file = tmp_file_path("keypair_file", &unfunded_payer.pubkey());
tmp_file_path("keypair_file", &unfunded_payer.pubkey());
write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap(); write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap();
args.sender_keypair = read_keypair_file(&unfunded_payer_keypair_file) args.sender_keypair = read_keypair_file(&unfunded_payer_keypair_file)
.unwrap() .unwrap()
@ -1151,9 +1161,7 @@ mod tests {
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args) let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
.await
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
sources, sources,
@ -1174,16 +1182,14 @@ mod tests {
) )
.unwrap(); .unwrap();
let transaction = transfer( let transaction = transfer(
&mut banks_client, &client,
sol_to_lamports(allocation_amount), sol_to_lamports(allocation_amount),
&sender_keypair, &alice,
&partially_funded_payer.pubkey(), &partially_funded_payer.pubkey(),
) )
.await
.unwrap(); .unwrap();
banks_client client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent) .send_and_confirm_transaction_with_spinner(&transaction)
.await
.unwrap(); .unwrap();
args.sender_keypair = read_keypair_file(&partially_funded_payer_keypair_file) args.sender_keypair = read_keypair_file(&partially_funded_payer_keypair_file)
@ -1192,9 +1198,7 @@ mod tests {
args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file) args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file)
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args) let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
.await
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
sources, sources,
@ -1204,23 +1208,39 @@ mod tests {
} else { } else {
panic!("check_payer_balances should have errored"); panic!("check_payer_balances should have errored");
} }
});
// Explicit cleanup, otherwise "pure virtual method called" crash in Docker
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
} }
#[test] #[test]
fn test_check_payer_balances_distribute_tokens_separate_payers() { fn test_check_payer_balances_distribute_tokens_separate_payers() {
let fees = 10_000; let fees = 10_000;
let fees_in_sol = lamports_to_sol(fees); let fees_in_sol = lamports_to_sol(fees);
let (mut genesis_config, sender_keypair) = let TestValidator {
create_genesis_config(sol_to_lamports(9_000_000.0)); server,
genesis_config.fee_rate_governor = FeeRateGovernor::new(fees, 0); leader_data,
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config)))); alice,
Runtime::new().unwrap().block_on(async { ledger_path,
let transport = start_local_server(&bank_forks).await; ..
let mut banks_client = start_client(transport).await.unwrap(); } = TestValidator::run_with_fees(fees);
let url = get_rpc_request_str(leader_data.rpc, false);
let client = RpcClient::new_with_commitment(url, CommitmentConfig::recent());
let sender_keypair_file = tmp_file_path("keypair_file", &sender_keypair.pubkey()); let sender_keypair_file = tmp_file_path("keypair_file", &alice.pubkey());
write_keypair_file(&sender_keypair, &sender_keypair_file).unwrap(); write_keypair_file(&alice, &sender_keypair_file).unwrap();
// This is a quick hack until TestValidator can be initialized with fees from block 0
while client
.get_recent_blockhash()
.unwrap()
.1
.lamports_per_signature
== 0
{
sleep(Duration::from_millis(DEFAULT_MS_PER_SLOT));
}
let allocation_amount = 1000.0; let allocation_amount = 1000.0;
@ -1228,16 +1248,14 @@ mod tests {
let funded_payer_keypair_file = tmp_file_path("keypair_file", &funded_payer.pubkey()); let funded_payer_keypair_file = tmp_file_path("keypair_file", &funded_payer.pubkey());
write_keypair_file(&funded_payer, &funded_payer_keypair_file).unwrap(); write_keypair_file(&funded_payer, &funded_payer_keypair_file).unwrap();
let transaction = transfer( let transaction = transfer(
&mut banks_client, &client,
sol_to_lamports(allocation_amount), sol_to_lamports(allocation_amount),
&sender_keypair, &alice,
&funded_payer.pubkey(), &funded_payer.pubkey(),
) )
.await
.unwrap(); .unwrap();
banks_client client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent) .send_and_confirm_transaction_with_spinner(&transaction)
.await
.unwrap(); .unwrap();
// Fully funded payers // Fully funded payers
@ -1247,23 +1265,18 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
None, None,
); );
check_payer_balances(1, &allocations, &mut banks_client, &args) check_payer_balances(1, &allocations, &client, &args).unwrap();
.await
.unwrap();
// Unfunded sender // Unfunded sender
let unfunded_payer = Keypair::new(); let unfunded_payer = Keypair::new();
let unfunded_payer_keypair_file = let unfunded_payer_keypair_file = tmp_file_path("keypair_file", &unfunded_payer.pubkey());
tmp_file_path("keypair_file", &unfunded_payer.pubkey());
write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap(); write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap();
args.sender_keypair = read_keypair_file(&unfunded_payer_keypair_file) args.sender_keypair = read_keypair_file(&unfunded_payer_keypair_file)
.unwrap() .unwrap()
.into(); .into();
args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into(); args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args) let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
.await
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::SystemAccount].into()); assert_eq!(sources, vec![FundingSource::SystemAccount].into());
assert!((amount - allocation_amount).abs() < f64::EPSILON); assert!((amount - allocation_amount).abs() < f64::EPSILON);
@ -1277,23 +1290,24 @@ mod tests {
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args) let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
.await
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::FeePayer].into()); assert_eq!(sources, vec![FundingSource::FeePayer].into());
assert!((amount - fees_in_sol).abs() < f64::EPSILON); assert!((amount - fees_in_sol).abs() < f64::EPSILON);
} else { } else {
panic!("check_payer_balances should have errored"); panic!("check_payer_balances should have errored");
} }
});
// Explicit cleanup, otherwise "pure virtual method called" crash in Docker
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
} }
async fn initialize_stake_account( fn initialize_stake_account(
stake_account_amount: f64, stake_account_amount: f64,
unlocked_sol: f64, unlocked_sol: f64,
sender_keypair: &Keypair, sender_keypair: &Keypair,
banks_client: &mut BanksClient, client: &RpcClient,
) -> StakeArgs { ) -> StakeArgs {
let stake_account_keypair = Keypair::new(); let stake_account_keypair = Keypair::new();
let stake_account_address = stake_account_keypair.pubkey(); let stake_account_address = stake_account_keypair.pubkey();
@ -1314,11 +1328,10 @@ mod tests {
); );
let message = Message::new(&instructions, Some(&sender_keypair.pubkey())); let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
let signers = [sender_keypair, &stake_account_keypair]; let signers = [sender_keypair, &stake_account_keypair];
let blockhash = banks_client.get_recent_blockhash().await.unwrap(); let (blockhash, _fees) = client.get_recent_blockhash().unwrap();
let transaction = Transaction::new(&signers, message, blockhash); let transaction = Transaction::new(&signers, message, blockhash);
banks_client client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent) .send_and_confirm_transaction_with_spinner(&transaction)
.await
.unwrap(); .unwrap();
StakeArgs { StakeArgs {
@ -1334,26 +1347,33 @@ mod tests {
fn test_check_payer_balances_distribute_stakes_single_payer() { fn test_check_payer_balances_distribute_stakes_single_payer() {
let fees = 10_000; let fees = 10_000;
let fees_in_sol = lamports_to_sol(fees); let fees_in_sol = lamports_to_sol(fees);
let (mut genesis_config, sender_keypair) = let TestValidator {
create_genesis_config(sol_to_lamports(9_000_000.0)); server,
genesis_config.fee_rate_governor = FeeRateGovernor::new(fees, 0); leader_data,
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config)))); alice,
Runtime::new().unwrap().block_on(async { ledger_path,
let transport = start_local_server(&bank_forks).await; ..
let mut banks_client = start_client(transport).await.unwrap(); } = TestValidator::run_with_fees(fees);
let url = get_rpc_request_str(leader_data.rpc, false);
let client = RpcClient::new_with_commitment(url, CommitmentConfig::recent());
let sender_keypair_file = tmp_file_path("keypair_file", &sender_keypair.pubkey()); let sender_keypair_file = tmp_file_path("keypair_file", &alice.pubkey());
write_keypair_file(&sender_keypair, &sender_keypair_file).unwrap(); write_keypair_file(&alice, &sender_keypair_file).unwrap();
// This is a quick hack until TestValidator can be initialized with fees from block 0
while client
.get_recent_blockhash()
.unwrap()
.1
.lamports_per_signature
== 0
{
sleep(Duration::from_millis(DEFAULT_MS_PER_SLOT));
}
let allocation_amount = 1000.0; let allocation_amount = 1000.0;
let unlocked_sol = 1.0; let unlocked_sol = 1.0;
let stake_args = initialize_stake_account( let stake_args = initialize_stake_account(allocation_amount, unlocked_sol, &alice, &client);
allocation_amount,
unlocked_sol,
&sender_keypair,
&mut banks_client,
)
.await;
// Fully funded payer & stake account // Fully funded payer & stake account
let (allocations, mut args) = initialize_check_payer_balances_inputs( let (allocations, mut args) = initialize_check_payer_balances_inputs(
@ -1362,9 +1382,7 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
Some(stake_args), Some(stake_args),
); );
check_payer_balances(1, &allocations, &mut banks_client, &args) check_payer_balances(1, &allocations, &client, &args).unwrap();
.await
.unwrap();
// Underfunded stake-account // Underfunded stake-account
let expensive_allocation_amount = 5000.0; let expensive_allocation_amount = 5000.0;
@ -1374,22 +1392,17 @@ mod tests {
lockup_date: "".to_string(), lockup_date: "".to_string(),
}]; }];
let err_result = let err_result =
check_payer_balances(1, &expensive_allocations, &mut banks_client, &args) check_payer_balances(1, &expensive_allocations, &client, &args).unwrap_err();
.await
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::StakeAccount].into()); assert_eq!(sources, vec![FundingSource::StakeAccount].into());
assert!( assert!((amount - (expensive_allocation_amount - unlocked_sol)).abs() < f64::EPSILON);
(amount - (expensive_allocation_amount - unlocked_sol)).abs() < f64::EPSILON
);
} else { } else {
panic!("check_payer_balances should have errored"); panic!("check_payer_balances should have errored");
} }
// Unfunded payer // Unfunded payer
let unfunded_payer = Keypair::new(); let unfunded_payer = Keypair::new();
let unfunded_payer_keypair_file = let unfunded_payer_keypair_file = tmp_file_path("keypair_file", &unfunded_payer.pubkey());
tmp_file_path("keypair_file", &unfunded_payer.pubkey());
write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap(); write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap();
args.sender_keypair = read_keypair_file(&unfunded_payer_keypair_file) args.sender_keypair = read_keypair_file(&unfunded_payer_keypair_file)
.unwrap() .unwrap()
@ -1398,9 +1411,7 @@ mod tests {
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args) let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
.await
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
sources, sources,
@ -1421,16 +1432,14 @@ mod tests {
) )
.unwrap(); .unwrap();
let transaction = transfer( let transaction = transfer(
&mut banks_client, &client,
sol_to_lamports(unlocked_sol), sol_to_lamports(unlocked_sol),
&sender_keypair, &alice,
&partially_funded_payer.pubkey(), &partially_funded_payer.pubkey(),
) )
.await
.unwrap(); .unwrap();
banks_client client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent) .send_and_confirm_transaction_with_spinner(&transaction)
.await
.unwrap(); .unwrap();
args.sender_keypair = read_keypair_file(&partially_funded_payer_keypair_file) args.sender_keypair = read_keypair_file(&partially_funded_payer_keypair_file)
@ -1439,9 +1448,7 @@ mod tests {
args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file) args.fee_payer = read_keypair_file(&partially_funded_payer_keypair_file)
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args) let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
.await
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!( assert_eq!(
sources, sources,
@ -1451,48 +1458,56 @@ mod tests {
} else { } else {
panic!("check_payer_balances should have errored"); panic!("check_payer_balances should have errored");
} }
});
// Explicit cleanup, otherwise "pure virtual method called" crash in Docker
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
} }
#[test] #[test]
fn test_check_payer_balances_distribute_stakes_separate_payers() { fn test_check_payer_balances_distribute_stakes_separate_payers() {
let fees = 10_000; let fees = 10_000;
let fees_in_sol = lamports_to_sol(fees); let fees_in_sol = lamports_to_sol(fees);
let (mut genesis_config, sender_keypair) = let TestValidator {
create_genesis_config(sol_to_lamports(9_000_000.0)); server,
genesis_config.fee_rate_governor = FeeRateGovernor::new(fees, 0); leader_data,
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config)))); alice,
Runtime::new().unwrap().block_on(async { ledger_path,
let transport = start_local_server(&bank_forks).await; ..
let mut banks_client = start_client(transport).await.unwrap(); } = TestValidator::run_with_fees(fees);
let url = get_rpc_request_str(leader_data.rpc, false);
let client = RpcClient::new_with_commitment(url, CommitmentConfig::recent());
let sender_keypair_file = tmp_file_path("keypair_file", &sender_keypair.pubkey()); let sender_keypair_file = tmp_file_path("keypair_file", &alice.pubkey());
write_keypair_file(&sender_keypair, &sender_keypair_file).unwrap(); write_keypair_file(&alice, &sender_keypair_file).unwrap();
// This is a quick hack until TestValidator can be initialized with fees from block 0
while client
.get_recent_blockhash()
.unwrap()
.1
.lamports_per_signature
== 0
{
sleep(Duration::from_millis(DEFAULT_MS_PER_SLOT));
}
let allocation_amount = 1000.0; let allocation_amount = 1000.0;
let unlocked_sol = 1.0; let unlocked_sol = 1.0;
let stake_args = initialize_stake_account( let stake_args = initialize_stake_account(allocation_amount, unlocked_sol, &alice, &client);
allocation_amount,
unlocked_sol,
&sender_keypair,
&mut banks_client,
)
.await;
let funded_payer = Keypair::new(); let funded_payer = Keypair::new();
let funded_payer_keypair_file = tmp_file_path("keypair_file", &funded_payer.pubkey()); let funded_payer_keypair_file = tmp_file_path("keypair_file", &funded_payer.pubkey());
write_keypair_file(&funded_payer, &funded_payer_keypair_file).unwrap(); write_keypair_file(&funded_payer, &funded_payer_keypair_file).unwrap();
let transaction = transfer( let transaction = transfer(
&mut banks_client, &client,
sol_to_lamports(unlocked_sol), sol_to_lamports(unlocked_sol),
&sender_keypair, &alice,
&funded_payer.pubkey(), &funded_payer.pubkey(),
) )
.await
.unwrap(); .unwrap();
banks_client client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent) .send_and_confirm_transaction_with_spinner(&transaction)
.await
.unwrap(); .unwrap();
// Fully funded payers // Fully funded payers
@ -1502,23 +1517,18 @@ mod tests {
&sender_keypair_file, &sender_keypair_file,
Some(stake_args), Some(stake_args),
); );
check_payer_balances(1, &allocations, &mut banks_client, &args) check_payer_balances(1, &allocations, &client, &args).unwrap();
.await
.unwrap();
// Unfunded sender // Unfunded sender
let unfunded_payer = Keypair::new(); let unfunded_payer = Keypair::new();
let unfunded_payer_keypair_file = let unfunded_payer_keypair_file = tmp_file_path("keypair_file", &unfunded_payer.pubkey());
tmp_file_path("keypair_file", &unfunded_payer.pubkey());
write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap(); write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap();
args.sender_keypair = read_keypair_file(&unfunded_payer_keypair_file) args.sender_keypair = read_keypair_file(&unfunded_payer_keypair_file)
.unwrap() .unwrap()
.into(); .into();
args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into(); args.fee_payer = read_keypair_file(&sender_keypair_file).unwrap().into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args) let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
.await
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::SystemAccount].into()); assert_eq!(sources, vec![FundingSource::SystemAccount].into());
assert!((amount - unlocked_sol).abs() < f64::EPSILON); assert!((amount - unlocked_sol).abs() < f64::EPSILON);
@ -1532,15 +1542,16 @@ mod tests {
.unwrap() .unwrap()
.into(); .into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args) let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
.await
.unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result { if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::FeePayer].into()); assert_eq!(sources, vec![FundingSource::FeePayer].into());
assert!((amount - fees_in_sol).abs() < f64::EPSILON); assert!((amount - fees_in_sol).abs() < f64::EPSILON);
} else { } else {
panic!("check_payer_balances should have errored"); panic!("check_payer_balances should have errored");
} }
});
// Explicit cleanup, otherwise "pure virtual method called" crash in Docker
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
} }
} }

View File

@ -1,8 +1,8 @@
use chrono::prelude::*; use chrono::prelude::*;
use pickledb::{error::Error, PickleDb, PickleDbDumpPolicy}; use pickledb::{error::Error, PickleDb, PickleDbDumpPolicy};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use solana_banks_client::TransactionStatus;
use solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature, transaction::Transaction}; use solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature, transaction::Transaction};
use solana_transaction_status::TransactionStatus;
use std::{cmp::Ordering, fs, io, path::Path}; use std::{cmp::Ordering, fs, io, path::Path};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
@ -306,6 +306,7 @@ mod tests {
slot: 0, slot: 0,
confirmations: Some(1), confirmations: Some(1),
err: None, err: None,
status: Ok(()),
}; };
assert_eq!( assert_eq!(
update_finalized_transaction(&mut db, &signature, Some(transaction_status), 0, 0) update_finalized_transaction(&mut db, &signature, Some(transaction_status), 0, 0)
@ -332,6 +333,7 @@ mod tests {
slot: 0, slot: 0,
confirmations: None, confirmations: None,
err: Some(TransactionError::AccountNotFound), err: Some(TransactionError::AccountNotFound),
status: Ok(()),
}; };
assert_eq!( assert_eq!(
update_finalized_transaction(&mut db, &signature, Some(transaction_status), 0, 0) update_finalized_transaction(&mut db, &signature, Some(transaction_status), 0, 0)
@ -355,6 +357,7 @@ mod tests {
slot: 0, slot: 0,
confirmations: None, confirmations: None,
err: None, err: None,
status: Ok(()),
}; };
assert_eq!( assert_eq!(
update_finalized_transaction(&mut db, &signature, Some(transaction_status), 0, 0) update_finalized_transaction(&mut db, &signature, Some(transaction_status), 0, 0)

View File

@ -1,9 +1,7 @@
use solana_banks_client::start_tcp_client;
use solana_cli_config::{Config, CONFIG_FILE}; use solana_cli_config::{Config, CONFIG_FILE};
use solana_client::rpc_client::RpcClient;
use solana_tokens::{arg_parser::parse_args, args::Command, commands}; use solana_tokens::{arg_parser::parse_args, args::Command, commands};
use std::{env, error::Error, path::Path, process}; use std::{env, error::Error, path::Path, process};
use tokio::runtime::Runtime;
use url::Url;
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
let command_args = parse_args(env::args_os())?; let command_args = parse_args(env::args_os())?;
@ -18,19 +16,14 @@ fn main() -> Result<(), Box<dyn Error>> {
Config::default() Config::default()
}; };
let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url); let json_rpc_url = command_args.url.unwrap_or(config.json_rpc_url);
let rpc_banks_url = Config::compute_rpc_banks_url(&json_rpc_url); let client = RpcClient::new(json_rpc_url);
let url = Url::parse(&rpc_banks_url)?;
let host_port = (url.host_str().unwrap(), url.port().unwrap());
let runtime = Runtime::new().unwrap();
let mut banks_client = runtime.block_on(start_tcp_client(&host_port))?;
match command_args.command { match command_args.command {
Command::DistributeTokens(args) => { Command::DistributeTokens(args) => {
runtime.block_on(commands::process_allocations(&mut banks_client, &args))?; commands::process_allocations(&client, &args)?;
} }
Command::Balances(args) => { Command::Balances(args) => {
runtime.block_on(commands::process_balances(&mut banks_client, &args))?; commands::process_balances(&client, &args)?;
} }
Command::TransactionLog(args) => { Command::TransactionLog(args) => {
commands::process_transaction_log(&args)?; commands::process_transaction_log(&args)?;

View File

@ -1,8 +1,7 @@
use solana_banks_client::start_tcp_client; use solana_client::rpc_client::RpcClient;
use solana_core::test_validator::TestValidator; use solana_core::test_validator::TestValidator;
use solana_tokens::commands::test_process_distribute_tokens_with_client; use solana_tokens::commands::test_process_distribute_tokens_with_client;
use std::fs::remove_dir_all; use std::fs::remove_dir_all;
use tokio::runtime::Runtime;
#[test] #[test]
fn test_process_distribute_with_rpc_client() { fn test_process_distribute_with_rpc_client() {
@ -15,10 +14,8 @@ fn test_process_distribute_with_rpc_client() {
.. ..
} = TestValidator::run(); } = TestValidator::run();
Runtime::new().unwrap().block_on(async { let client = RpcClient::new_socket(leader_data.rpc);
let mut banks_client = start_tcp_client(leader_data.rpc_banks).await.unwrap(); test_process_distribute_tokens_with_client(&client, alice, None);
test_process_distribute_tokens_with_client(&mut banks_client, alice, None).await
});
// Explicit cleanup, otherwise "pure virtual method called" crash in Docker // Explicit cleanup, otherwise "pure virtual method called" crash in Docker
server.close().unwrap(); server.close().unwrap();