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",
"pickledb",
"serde",
"solana-banks-client",
"solana-banks-server",
"solana-clap-utils",
"solana-cli-config",
"solana-client",
@ -4969,10 +4967,9 @@ dependencies = [
"solana-runtime",
"solana-sdk",
"solana-stake-program",
"solana-transaction-status",
"tempfile",
"thiserror",
"tokio 0.3.2",
"url 2.1.1",
]
[[package]]

View File

@ -18,7 +18,6 @@ indexmap = "1.5.1"
indicatif = "0.15.0"
pickledb = "0.4.1"
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-cli-config = { path = "../cli-config", 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-sdk = { path = "../sdk", 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"
thiserror = "1.0"
tokio = { version = "0.3", features = ["full"] }
url = "2.1"
[dev-dependencies]
bincode = "1.3.1"
solana-banks-server = { path = "../banks-server", version = "1.5.0" }
solana-core = { path = "../core", 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 pickledb::PickleDb;
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::{
commitment_config::CommitmentLevel,
commitment_config::CommitmentConfig,
instruction::Instruction,
message::Message,
native_token::{lamports_to_sol, sol_to_lamports},
signature::{unique_signers, Signature, Signer},
system_instruction,
transaction::Transaction,
transport::{self, TransportError},
};
use solana_stake_program::{
stake_instruction::{self, LockupArgs},
@ -25,9 +28,9 @@ use solana_stake_program::{
use std::{
cmp::{self},
io,
thread::sleep,
time::Duration,
};
use tokio::time::sleep;
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
struct Allocation {
@ -78,7 +81,7 @@ pub enum Error {
#[error("PickleDb error")]
PickleDbError(#[from] pickledb::error::Error),
#[error("Transport error")]
TransportError(#[from] TransportError),
ClientError(#[from] ClientError),
#[error("Missing lockup authority")]
MissingLockupAuthority,
#[error("insufficient funds in {0:?}, requires {1} SOL")]
@ -128,16 +131,16 @@ fn apply_previous_transactions(
allocations.retain(|x| x.amount > 0.5);
}
async fn transfer<S: Signer>(
client: &mut BanksClient,
fn transfer<S: Signer>(
client: &RpcClient,
lamports: u64,
sender_keypair: &S,
to_pubkey: &Pubkey,
) -> io::Result<Transaction> {
) -> ClientResult<Transaction> {
let create_instruction =
system_instruction::transfer(&sender_keypair.pubkey(), &to_pubkey, lamports);
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(
&[sender_keypair],
message,
@ -218,8 +221,8 @@ fn distribution_instructions(
instructions
}
async fn distribute_allocations(
client: &mut BanksClient,
fn distribute_allocations(
client: &RpcClient,
db: &mut PickleDb,
allocations: &[Allocation],
args: &DistributeTokensArgs,
@ -252,7 +255,7 @@ async fn distribute_allocations(
.iter()
.map(|message| message.header.num_required_signatures as usize)
.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
allocations.iter().zip(messages).zip(stake_extras)
@ -273,13 +276,19 @@ async fn distribute_allocations(
}
}
let signers = unique_signers(signers);
let result: transport::Result<(Transaction, u64)> = {
let result: ClientResult<(Transaction, u64)> = {
if args.dry_run {
Ok((Transaction::new_unsigned(message), std::u64::MAX))
} 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);
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))
}
};
@ -333,8 +342,8 @@ fn new_spinner_progress_bar() -> ProgressBar {
progress_bar
}
pub async fn process_allocations(
client: &mut BanksClient,
pub fn process_allocations(
client: &RpcClient,
args: &DistributeTokensArgs,
) -> Result<Option<usize>, Error> {
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)?;
// 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);
apply_previous_transactions(&mut allocations, &transaction_infos);
@ -382,9 +391,9 @@ pub async fn process_allocations(
.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 let Some(output_path) = &args.output_path {
@ -395,8 +404,8 @@ pub async fn process_allocations(
Ok(opt_confirmations)
}
async fn finalize_transactions(
client: &mut BanksClient,
fn finalize_transactions(
client: &RpcClient,
db: &mut PickleDb,
dry_run: bool,
) -> Result<Option<usize>, Error> {
@ -404,7 +413,7 @@ async fn finalize_transactions(
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();
@ -417,8 +426,8 @@ async fn finalize_transactions(
}
// Sleep for about 1 slot
sleep(Duration::from_millis(500)).await;
let opt_conf = update_finalized_transactions(client, db).await?;
sleep(Duration::from_millis(500));
let opt_conf = update_finalized_transactions(client, db)?;
opt_confirmations = opt_conf;
}
@ -427,8 +436,8 @@ async fn finalize_transactions(
// 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.
async fn update_finalized_transactions(
client: &mut BanksClient,
fn update_finalized_transactions(
client: &RpcClient,
db: &mut PickleDb,
) -> Result<Option<usize>, Error> {
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
.collect();
let transaction_statuses = client
.get_transaction_statuses(unconfirmed_signatures)
.await?;
let root_slot = client.get_root_slot().await?;
.get_signature_statuses(&unconfirmed_signatures)?
.value;
let root_slot = client.get_slot()?;
let mut confirmations = None;
for ((transaction, last_valid_slot), opt_transaction_status) in unconfirmed_transactions
@ -475,15 +484,15 @@ async fn update_finalized_transactions(
Ok(confirmations)
}
async fn check_payer_balances(
fn check_payer_balances(
num_signatures: usize,
allocations: &[Allocation],
client: &mut BanksClient,
client: &RpcClient,
args: &DistributeTokensArgs,
) -> Result<(), Error> {
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
.lamports_per_signature
.checked_mul(num_signatures as u64)
@ -505,7 +514,7 @@ async fn check_payer_balances(
let allocation_lamports = sol_to_lamports(undistributed_tokens);
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 {
return Err(Error::InsufficientFunds(
vec![FundingSource::StakeAccount].into(),
@ -513,7 +522,7 @@ async fn check_payer_balances(
));
}
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 {
return Err(Error::InsufficientFunds(
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into(),
@ -521,14 +530,14 @@ async fn check_payer_balances(
));
}
} 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 {
return Err(Error::InsufficientFunds(
vec![FundingSource::FeePayer].into(),
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 {
return Err(Error::InsufficientFunds(
vec![FundingSource::SystemAccount].into(),
@ -537,7 +546,7 @@ async fn check_payer_balances(
}
}
} 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 {
return Err(Error::InsufficientFunds(
vec![FundingSource::SystemAccount, FundingSource::FeePayer].into(),
@ -545,14 +554,14 @@ async fn check_payer_balances(
));
}
} 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 {
return Err(Error::InsufficientFunds(
vec![FundingSource::FeePayer].into(),
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 {
return Err(Error::InsufficientFunds(
vec![FundingSource::SystemAccount].into(),
@ -563,10 +572,7 @@ async fn check_payer_balances(
Ok(())
}
pub async fn process_balances(
client: &mut BanksClient,
args: &BalancesArgs,
) -> Result<(), csv::Error> {
pub fn process_balances(client: &RpcClient, args: &BalancesArgs) -> Result<(), csv::Error> {
let allocations: Vec<Allocation> = read_allocations(&args.input_csv, None)?;
let allocations = merge_allocations(&allocations);
@ -582,7 +588,7 @@ pub async fn process_balances(
for allocation in &allocations {
let address = allocation.recipient.parse().unwrap();
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!(
"{:<44} {:>24.9} {:>24.9} {:>24.9}",
allocation.recipient,
@ -604,8 +610,8 @@ pub fn process_transaction_log(args: &TransactionLogArgs) -> Result<(), Error> {
use crate::db::check_output_file;
use solana_sdk::{pubkey::Pubkey, signature::Keypair};
use tempfile::{tempdir, NamedTempFile};
pub async fn test_process_distribute_tokens_with_client(
client: &mut BanksClient,
pub fn test_process_distribute_tokens_with_client(
client: &RpcClient,
sender_keypair: Keypair,
transfer_amount: Option<f64>,
) {
@ -616,17 +622,12 @@ pub async fn test_process_distribute_tokens_with_client(
&sender_keypair,
&fee_payer.pubkey(),
)
.await
.unwrap();
client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent)
.await
.send_and_confirm_transaction_with_spinner(&transaction)
.unwrap();
assert_eq!(
client
.get_balance_with_commitment(fee_payer.pubkey(), CommitmentLevel::Recent)
.await
.unwrap(),
client.get_balance(&fee_payer.pubkey()).unwrap(),
sol_to_lamports(1.0),
);
@ -667,7 +668,7 @@ pub async fn test_process_distribute_tokens_with_client(
stake_args: None,
transfer_amount,
};
let confirmations = process_allocations(client, &args).await.unwrap();
let confirmations = process_allocations(client, &args).unwrap();
assert_eq!(confirmations, None);
let transaction_infos =
@ -680,15 +681,12 @@ pub async fn test_process_distribute_tokens_with_client(
expected_amount
);
assert_eq!(
client.get_balance(alice_pubkey).await.unwrap(),
expected_amount,
);
assert_eq!(client.get_balance(&alice_pubkey).unwrap(), expected_amount,);
check_output_file(&output_path, &db::open_db(&transaction_db, true).unwrap());
// 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 =
db::read_transaction_infos(&db::open_db(&transaction_db, true).unwrap());
assert_eq!(transaction_infos.len(), 1);
@ -699,18 +697,12 @@ pub async fn test_process_distribute_tokens_with_client(
expected_amount
);
assert_eq!(
client.get_balance(alice_pubkey).await.unwrap(),
expected_amount,
);
assert_eq!(client.get_balance(&alice_pubkey).unwrap(), expected_amount,);
check_output_file(&output_path, &db::open_db(&transaction_db, true).unwrap());
}
pub async fn test_process_distribute_stake_with_client(
client: &mut BanksClient,
sender_keypair: Keypair,
) {
pub fn test_process_distribute_stake_with_client(client: &RpcClient, sender_keypair: Keypair) {
let fee_payer = Keypair::new();
let transaction = transfer(
client,
@ -718,11 +710,9 @@ pub async fn test_process_distribute_stake_with_client(
&sender_keypair,
&fee_payer.pubkey(),
)
.await
.unwrap();
client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent)
.await
.send_and_confirm_transaction_with_spinner(&transaction)
.unwrap();
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 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);
client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent)
.await
.send_and_confirm_transaction_with_spinner(&transaction)
.unwrap();
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),
transfer_amount: None,
};
let confirmations = process_allocations(client, &args).await.unwrap();
let confirmations = process_allocations(client, &args).unwrap();
assert_eq!(confirmations, None);
let transaction_infos =
@ -805,19 +794,19 @@ pub async fn test_process_distribute_stake_with_client(
);
assert_eq!(
client.get_balance(alice_pubkey).await.unwrap(),
client.get_balance(&alice_pubkey).unwrap(),
sol_to_lamports(1.0),
);
let new_stake_account_address = transaction_infos[0].new_stake_account_address.unwrap();
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),
);
check_output_file(&output_path, &db::open_db(&transaction_db, true).unwrap());
// 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 =
db::read_transaction_infos(&db::open_db(&transaction_db, true).unwrap());
assert_eq!(transaction_infos.len(), 1);
@ -829,11 +818,11 @@ pub async fn test_process_distribute_stake_with_client(
);
assert_eq!(
client.get_balance(alice_pubkey).await.unwrap(),
client.get_balance(&alice_pubkey).unwrap(),
sol_to_lamports(1.0),
);
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),
);
@ -843,55 +832,67 @@ pub async fn test_process_distribute_stake_with_client(
#[cfg(test)]
mod tests {
use super::*;
use solana_banks_client::start_client;
use solana_banks_server::banks_server::start_local_server;
use solana_runtime::{bank::Bank, bank_forks::BankForks};
use solana_client::rpc_client::get_rpc_request_str;
use solana_core::test_validator::TestValidator;
use solana_sdk::{
fee_calculator::FeeRateGovernor,
genesis_config::create_genesis_config,
clock::DEFAULT_MS_PER_SLOT,
signature::{read_keypair_file, write_keypair_file},
};
use solana_stake_program::stake_instruction::StakeInstruction;
use std::sync::{Arc, RwLock};
use tokio::runtime::Runtime;
use std::fs::remove_dir_all;
#[test]
fn test_process_token_allocations() {
let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0));
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config))));
Runtime::new().unwrap().block_on(async {
let transport = start_local_server(&bank_forks).await;
let mut banks_client = start_client(transport).await.unwrap();
test_process_distribute_tokens_with_client(&mut banks_client, sender_keypair, None)
.await;
});
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = 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]
fn test_process_transfer_amount_allocations() {
let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0));
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config))));
Runtime::new().unwrap().block_on(async {
let transport = start_local_server(&bank_forks).await;
let mut banks_client = start_client(transport).await.unwrap();
test_process_distribute_tokens_with_client(
&mut banks_client,
sender_keypair,
Some(1.5),
)
.await;
});
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = 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, Some(1.5));
// Explicit cleanup, otherwise "pure virtual method called" crash in Docker
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}
#[test]
fn test_process_stake_allocations() {
let (genesis_config, sender_keypair) = create_genesis_config(sol_to_lamports(9_000_000.0));
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config))));
Runtime::new().unwrap().block_on(async {
let transport = start_local_server(&bank_forks).await;
let mut banks_client = start_client(transport).await.unwrap();
test_process_distribute_stake_with_client(&mut banks_client, sender_keypair).await;
});
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = 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]
@ -1115,16 +1116,28 @@ mod tests {
fn test_check_payer_balances_distribute_tokens_single_payer() {
let fees = 10_000;
let fees_in_sol = lamports_to_sol(fees);
let (mut genesis_config, sender_keypair) =
create_genesis_config(sol_to_lamports(9_000_000.0));
genesis_config.fee_rate_governor = FeeRateGovernor::new(fees, 0);
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config))));
Runtime::new().unwrap().block_on(async {
let transport = start_local_server(&bank_forks).await;
let mut banks_client = start_client(transport).await.unwrap();
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = 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());
write_keypair_file(&sender_keypair, &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;
@ -1135,14 +1148,11 @@ mod tests {
&sender_keypair_file,
None,
);
check_payer_balances(1, &allocations, &mut banks_client, &args)
.await
.unwrap();
check_payer_balances(1, &allocations, &client, &args).unwrap();
// Unfunded payer
let unfunded_payer = Keypair::new();
let unfunded_payer_keypair_file =
tmp_file_path("keypair_file", &unfunded_payer.pubkey());
let unfunded_payer_keypair_file = tmp_file_path("keypair_file", &unfunded_payer.pubkey());
write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap();
args.sender_keypair = read_keypair_file(&unfunded_payer_keypair_file)
.unwrap()
@ -1151,9 +1161,7 @@ mod tests {
.unwrap()
.into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args)
.await
.unwrap_err();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(
sources,
@ -1174,16 +1182,14 @@ mod tests {
)
.unwrap();
let transaction = transfer(
&mut banks_client,
&client,
sol_to_lamports(allocation_amount),
&sender_keypair,
&alice,
&partially_funded_payer.pubkey(),
)
.await
.unwrap();
banks_client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent)
.await
client
.send_and_confirm_transaction_with_spinner(&transaction)
.unwrap();
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)
.unwrap()
.into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args)
.await
.unwrap_err();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(
sources,
@ -1204,23 +1208,39 @@ mod tests {
} else {
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]
fn test_check_payer_balances_distribute_tokens_separate_payers() {
let fees = 10_000;
let fees_in_sol = lamports_to_sol(fees);
let (mut genesis_config, sender_keypair) =
create_genesis_config(sol_to_lamports(9_000_000.0));
genesis_config.fee_rate_governor = FeeRateGovernor::new(fees, 0);
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config))));
Runtime::new().unwrap().block_on(async {
let transport = start_local_server(&bank_forks).await;
let mut banks_client = start_client(transport).await.unwrap();
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = 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());
write_keypair_file(&sender_keypair, &sender_keypair_file).unwrap();
let sender_keypair_file = tmp_file_path("keypair_file", &alice.pubkey());
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;
@ -1228,16 +1248,14 @@ mod tests {
let funded_payer_keypair_file = tmp_file_path("keypair_file", &funded_payer.pubkey());
write_keypair_file(&funded_payer, &funded_payer_keypair_file).unwrap();
let transaction = transfer(
&mut banks_client,
&client,
sol_to_lamports(allocation_amount),
&sender_keypair,
&alice,
&funded_payer.pubkey(),
)
.await
.unwrap();
banks_client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent)
.await
client
.send_and_confirm_transaction_with_spinner(&transaction)
.unwrap();
// Fully funded payers
@ -1247,23 +1265,18 @@ mod tests {
&sender_keypair_file,
None,
);
check_payer_balances(1, &allocations, &mut banks_client, &args)
.await
.unwrap();
check_payer_balances(1, &allocations, &client, &args).unwrap();
// Unfunded sender
let unfunded_payer = Keypair::new();
let unfunded_payer_keypair_file =
tmp_file_path("keypair_file", &unfunded_payer.pubkey());
let unfunded_payer_keypair_file = tmp_file_path("keypair_file", &unfunded_payer.pubkey());
write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap();
args.sender_keypair = read_keypair_file(&unfunded_payer_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)
.await
.unwrap_err();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
assert!((amount - allocation_amount).abs() < f64::EPSILON);
@ -1277,23 +1290,24 @@ mod tests {
.unwrap()
.into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args)
.await
.unwrap_err();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::FeePayer].into());
assert!((amount - fees_in_sol).abs() < f64::EPSILON);
} else {
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,
unlocked_sol: f64,
sender_keypair: &Keypair,
banks_client: &mut BanksClient,
client: &RpcClient,
) -> StakeArgs {
let stake_account_keypair = Keypair::new();
let stake_account_address = stake_account_keypair.pubkey();
@ -1314,11 +1328,10 @@ mod tests {
);
let message = Message::new(&instructions, Some(&sender_keypair.pubkey()));
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);
banks_client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent)
.await
client
.send_and_confirm_transaction_with_spinner(&transaction)
.unwrap();
StakeArgs {
@ -1334,26 +1347,33 @@ mod tests {
fn test_check_payer_balances_distribute_stakes_single_payer() {
let fees = 10_000;
let fees_in_sol = lamports_to_sol(fees);
let (mut genesis_config, sender_keypair) =
create_genesis_config(sol_to_lamports(9_000_000.0));
genesis_config.fee_rate_governor = FeeRateGovernor::new(fees, 0);
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config))));
Runtime::new().unwrap().block_on(async {
let transport = start_local_server(&bank_forks).await;
let mut banks_client = start_client(transport).await.unwrap();
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = 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());
write_keypair_file(&sender_keypair, &sender_keypair_file).unwrap();
let sender_keypair_file = tmp_file_path("keypair_file", &alice.pubkey());
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 unlocked_sol = 1.0;
let stake_args = initialize_stake_account(
allocation_amount,
unlocked_sol,
&sender_keypair,
&mut banks_client,
)
.await;
let stake_args = initialize_stake_account(allocation_amount, unlocked_sol, &alice, &client);
// Fully funded payer & stake account
let (allocations, mut args) = initialize_check_payer_balances_inputs(
@ -1362,9 +1382,7 @@ mod tests {
&sender_keypair_file,
Some(stake_args),
);
check_payer_balances(1, &allocations, &mut banks_client, &args)
.await
.unwrap();
check_payer_balances(1, &allocations, &client, &args).unwrap();
// Underfunded stake-account
let expensive_allocation_amount = 5000.0;
@ -1374,22 +1392,17 @@ mod tests {
lockup_date: "".to_string(),
}];
let err_result =
check_payer_balances(1, &expensive_allocations, &mut banks_client, &args)
.await
.unwrap_err();
check_payer_balances(1, &expensive_allocations, &client, &args).unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::StakeAccount].into());
assert!(
(amount - (expensive_allocation_amount - unlocked_sol)).abs() < f64::EPSILON
);
assert!((amount - (expensive_allocation_amount - unlocked_sol)).abs() < f64::EPSILON);
} else {
panic!("check_payer_balances should have errored");
}
// Unfunded payer
let unfunded_payer = Keypair::new();
let unfunded_payer_keypair_file =
tmp_file_path("keypair_file", &unfunded_payer.pubkey());
let unfunded_payer_keypair_file = tmp_file_path("keypair_file", &unfunded_payer.pubkey());
write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap();
args.sender_keypair = read_keypair_file(&unfunded_payer_keypair_file)
.unwrap()
@ -1398,9 +1411,7 @@ mod tests {
.unwrap()
.into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args)
.await
.unwrap_err();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(
sources,
@ -1421,16 +1432,14 @@ mod tests {
)
.unwrap();
let transaction = transfer(
&mut banks_client,
&client,
sol_to_lamports(unlocked_sol),
&sender_keypair,
&alice,
&partially_funded_payer.pubkey(),
)
.await
.unwrap();
banks_client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent)
.await
client
.send_and_confirm_transaction_with_spinner(&transaction)
.unwrap();
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)
.unwrap()
.into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args)
.await
.unwrap_err();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(
sources,
@ -1451,48 +1458,56 @@ mod tests {
} else {
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]
fn test_check_payer_balances_distribute_stakes_separate_payers() {
let fees = 10_000;
let fees_in_sol = lamports_to_sol(fees);
let (mut genesis_config, sender_keypair) =
create_genesis_config(sol_to_lamports(9_000_000.0));
genesis_config.fee_rate_governor = FeeRateGovernor::new(fees, 0);
let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new(&genesis_config))));
Runtime::new().unwrap().block_on(async {
let transport = start_local_server(&bank_forks).await;
let mut banks_client = start_client(transport).await.unwrap();
let TestValidator {
server,
leader_data,
alice,
ledger_path,
..
} = 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());
write_keypair_file(&sender_keypair, &sender_keypair_file).unwrap();
let sender_keypair_file = tmp_file_path("keypair_file", &alice.pubkey());
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 unlocked_sol = 1.0;
let stake_args = initialize_stake_account(
allocation_amount,
unlocked_sol,
&sender_keypair,
&mut banks_client,
)
.await;
let stake_args = initialize_stake_account(allocation_amount, unlocked_sol, &alice, &client);
let funded_payer = Keypair::new();
let funded_payer_keypair_file = tmp_file_path("keypair_file", &funded_payer.pubkey());
write_keypair_file(&funded_payer, &funded_payer_keypair_file).unwrap();
let transaction = transfer(
&mut banks_client,
&client,
sol_to_lamports(unlocked_sol),
&sender_keypair,
&alice,
&funded_payer.pubkey(),
)
.await
.unwrap();
banks_client
.process_transaction_with_commitment(transaction, CommitmentLevel::Recent)
.await
client
.send_and_confirm_transaction_with_spinner(&transaction)
.unwrap();
// Fully funded payers
@ -1502,23 +1517,18 @@ mod tests {
&sender_keypair_file,
Some(stake_args),
);
check_payer_balances(1, &allocations, &mut banks_client, &args)
.await
.unwrap();
check_payer_balances(1, &allocations, &client, &args).unwrap();
// Unfunded sender
let unfunded_payer = Keypair::new();
let unfunded_payer_keypair_file =
tmp_file_path("keypair_file", &unfunded_payer.pubkey());
let unfunded_payer_keypair_file = tmp_file_path("keypair_file", &unfunded_payer.pubkey());
write_keypair_file(&unfunded_payer, &unfunded_payer_keypair_file).unwrap();
args.sender_keypair = read_keypair_file(&unfunded_payer_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)
.await
.unwrap_err();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::SystemAccount].into());
assert!((amount - unlocked_sol).abs() < f64::EPSILON);
@ -1532,15 +1542,16 @@ mod tests {
.unwrap()
.into();
let err_result = check_payer_balances(1, &allocations, &mut banks_client, &args)
.await
.unwrap_err();
let err_result = check_payer_balances(1, &allocations, &client, &args).unwrap_err();
if let Error::InsufficientFunds(sources, amount) = err_result {
assert_eq!(sources, vec![FundingSource::FeePayer].into());
assert!((amount - fees_in_sol).abs() < f64::EPSILON);
} else {
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 pickledb::{error::Error, PickleDb, PickleDbDumpPolicy};
use serde::{Deserialize, Serialize};
use solana_banks_client::TransactionStatus;
use solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature, transaction::Transaction};
use solana_transaction_status::TransactionStatus;
use std::{cmp::Ordering, fs, io, path::Path};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
@ -306,6 +306,7 @@ mod tests {
slot: 0,
confirmations: Some(1),
err: None,
status: Ok(()),
};
assert_eq!(
update_finalized_transaction(&mut db, &signature, Some(transaction_status), 0, 0)
@ -332,6 +333,7 @@ mod tests {
slot: 0,
confirmations: None,
err: Some(TransactionError::AccountNotFound),
status: Ok(()),
};
assert_eq!(
update_finalized_transaction(&mut db, &signature, Some(transaction_status), 0, 0)
@ -355,6 +357,7 @@ mod tests {
slot: 0,
confirmations: None,
err: None,
status: Ok(()),
};
assert_eq!(
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_client::rpc_client::RpcClient;
use solana_tokens::{arg_parser::parse_args, args::Command, commands};
use std::{env, error::Error, path::Path, process};
use tokio::runtime::Runtime;
use url::Url;
fn main() -> Result<(), Box<dyn Error>> {
let command_args = parse_args(env::args_os())?;
@ -18,19 +16,14 @@ fn main() -> Result<(), Box<dyn Error>> {
Config::default()
};
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 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))?;
let client = RpcClient::new(json_rpc_url);
match command_args.command {
Command::DistributeTokens(args) => {
runtime.block_on(commands::process_allocations(&mut banks_client, &args))?;
commands::process_allocations(&client, &args)?;
}
Command::Balances(args) => {
runtime.block_on(commands::process_balances(&mut banks_client, &args))?;
commands::process_balances(&client, &args)?;
}
Command::TransactionLog(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_tokens::commands::test_process_distribute_tokens_with_client;
use std::fs::remove_dir_all;
use tokio::runtime::Runtime;
#[test]
fn test_process_distribute_with_rpc_client() {
@ -15,10 +14,8 @@ fn test_process_distribute_with_rpc_client() {
..
} = TestValidator::run();
Runtime::new().unwrap().block_on(async {
let mut banks_client = start_tcp_client(leader_data.rpc_banks).await.unwrap();
test_process_distribute_tokens_with_client(&mut banks_client, alice, None).await
});
let client = RpcClient::new_socket(leader_data.rpc);
test_process_distribute_tokens_with_client(&client, alice, None);
// Explicit cleanup, otherwise "pure virtual method called" crash in Docker
server.close().unwrap();