Skip to content

Commit

Permalink
TransactionScheduler: Add funded check before graph insertion
Browse files Browse the repository at this point in the history
  • Loading branch information
apfitzge committed Jan 8, 2024
1 parent 6bc110c commit cc756c3
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 18 deletions.
126 changes: 109 additions & 17 deletions core/src/banking_stage/transaction_scheduler/scheduler_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ use {
crossbeam_channel::RecvTimeoutError,
solana_accounts_db::transaction_error_metrics::TransactionErrorMetrics,
solana_measure::measure_us,
solana_runtime::{bank::Bank, bank_forks::BankForks},
solana_program_runtime::compute_budget_processor::process_compute_budget_instructions,
solana_runtime::{accounts::validate_fee_payer, bank::Bank, bank_forks::BankForks},
solana_sdk::{
clock::MAX_PROCESSING_AGE, saturating_add_assign, timing::AtomicInterval,
transaction::SanitizedTransaction,
clock::MAX_PROCESSING_AGE,
feature_set, saturating_add_assign,
timing::AtomicInterval,
transaction::{SanitizedTransaction, TransactionError},
},
std::{
sync::{Arc, RwLock},
Expand Down Expand Up @@ -163,8 +166,43 @@ impl SchedulerController {
&mut error_counters,
);

for ((check_result, _), result) in check_results.into_iter().zip(results.iter_mut()) {
*result = check_result.is_ok();
let fee_check_results: Vec<_> = check_results
.into_iter()
.zip(transactions)
.map(|((result, _nonce), tx)| {
result?; // if there's already error do nothing
let fee_payer = tx.message().fee_payer();
let budget_limits =
process_compute_budget_instructions(tx.message().program_instructions_iter())?
.into();
let fee = bank.fee_structure.calculate_fee(
tx.message(),
bank.get_lamports_per_signature(),
&budget_limits,
bank.feature_set.is_active(
&feature_set::include_loaded_accounts_data_size_in_fee_calculation::id(),
),
);
let (mut fee_payer_account, _slot) = bank
.rc
.accounts
.accounts_db
.load_with_fixed_root(&bank.ancestors, fee_payer)
.ok_or(TransactionError::AccountNotFound)?;

validate_fee_payer(
fee_payer,
&mut fee_payer_account,
0,
&mut error_counters,
bank.rent_collector(),
fee,
)
})
.collect();

for (fee_check_result, result) in fee_check_results.into_iter().zip(results.iter_mut()) {
*result = fee_check_result.is_ok();
}
}

Expand Down Expand Up @@ -580,7 +618,7 @@ mod tests {
solana_sdk::{
compute_budget::ComputeBudgetInstruction, hash::Hash, message::Message,
poh_config::PohConfig, pubkey::Pubkey, signature::Keypair, signer::Signer,
system_instruction, transaction::Transaction,
system_instruction, system_transaction, transaction::Transaction,
},
std::sync::{atomic::AtomicBool, Arc, RwLock},
tempfile::TempDir,
Expand All @@ -596,6 +634,7 @@ mod tests {
// such that our tests can be more easily set up and run.
struct TestFrame {
bank: Arc<Bank>,
mint_keypair: Keypair,
_ledger_path: TempDir,
_entry_receiver: Receiver<WorkingBankEntry>,
_record_receiver: Receiver<Record>,
Expand All @@ -607,7 +646,11 @@ mod tests {
}

fn create_test_frame(num_threads: usize) -> (TestFrame, SchedulerController) {
let GenesisConfigInfo { genesis_config, .. } = create_slow_genesis_config(10_000);
let GenesisConfigInfo {
genesis_config,
mint_keypair,
..
} = create_slow_genesis_config(u64::MAX);
let (bank, bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);

let ledger_path = get_tmp_ledger_path_auto_delete!();
Expand Down Expand Up @@ -637,6 +680,7 @@ mod tests {

let test_frame = TestFrame {
bank,
mint_keypair,
_ledger_path: ledger_path,
_entry_receiver: entry_receiver,
_record_receiver: record_receiver,
Expand All @@ -656,13 +700,26 @@ mod tests {
(test_frame, scheduler_controller)
}

fn prioritized_tranfer(
fn create_and_fund_prioritized_transfer(
bank: &Bank,
mint_keypair: &Keypair,
from_keypair: &Keypair,
to_pubkey: &Pubkey,
lamports: u64,
priority: u64,
recent_blockhash: Hash,
) -> Transaction {
// Fund the sending key, so that the transaction does not get filtered by the fee-payer check.
{
let transfer = system_transaction::transfer(
mint_keypair,
&from_keypair.pubkey(),
500_000, // just some amount that will always be enough
bank.last_blockhash(),
);
bank.process_transaction(&transfer).unwrap();
}

let transfer = system_instruction::transfer(&from_keypair.pubkey(), to_pubkey, lamports);
let prioritization = ComputeBudgetInstruction::set_compute_unit_price(priority);
let message = Message::new(&[transfer, prioritization], Some(&from_keypair.pubkey()));
Expand Down Expand Up @@ -703,6 +760,7 @@ mod tests {
let (test_frame, central_scheduler_banking_stage) = create_test_frame(1);
let TestFrame {
bank,
mint_keypair,
poh_recorder,
banking_packet_sender,
consume_work_receivers,
Expand All @@ -716,14 +774,18 @@ mod tests {
let scheduler_thread = std::thread::spawn(move || central_scheduler_banking_stage.run());

// Send packet batch to the scheduler - should do nothing until we become the leader.
let tx1 = prioritized_tranfer(
let tx1 = create_and_fund_prioritized_transfer(
bank,
mint_keypair,
&Keypair::new(),
&Pubkey::new_unique(),
1,
1,
bank.last_blockhash(),
);
let tx2 = prioritized_tranfer(
let tx2 = create_and_fund_prioritized_transfer(
bank,
mint_keypair,
&Keypair::new(),
&Pubkey::new_unique(),
1,
Expand Down Expand Up @@ -759,6 +821,7 @@ mod tests {
let (test_frame, central_scheduler_banking_stage) = create_test_frame(1);
let TestFrame {
bank,
mint_keypair,
poh_recorder,
banking_packet_sender,
consume_work_receivers,
Expand All @@ -772,8 +835,24 @@ mod tests {
let scheduler_thread = std::thread::spawn(move || central_scheduler_banking_stage.run());

let pk = Pubkey::new_unique();
let tx1 = prioritized_tranfer(&Keypair::new(), &pk, 1, 1, bank.last_blockhash());
let tx2 = prioritized_tranfer(&Keypair::new(), &pk, 1, 2, bank.last_blockhash());
let tx1 = create_and_fund_prioritized_transfer(
bank,
mint_keypair,
&Keypair::new(),
&pk,
1,
1,
bank.last_blockhash(),
);
let tx2 = create_and_fund_prioritized_transfer(
bank,
mint_keypair,
&Keypair::new(),
&pk,
1,
2,
bank.last_blockhash(),
);
let tx1_hash = tx1.message().hash();
let tx2_hash = tx2.message().hash();

Expand Down Expand Up @@ -808,6 +887,7 @@ mod tests {
let (test_frame, central_scheduler_banking_stage) = create_test_frame(1);
let TestFrame {
bank,
mint_keypair,
poh_recorder,
banking_packet_sender,
consume_work_receivers,
Expand All @@ -823,7 +903,9 @@ mod tests {
// Send multiple batches - all get scheduled
let txs1 = (0..2 * TARGET_NUM_TRANSACTIONS_PER_BATCH)
.map(|i| {
prioritized_tranfer(
create_and_fund_prioritized_transfer(
bank,
mint_keypair,
&Keypair::new(),
&Pubkey::new_unique(),
i as u64,
Expand All @@ -834,7 +916,9 @@ mod tests {
.collect_vec();
let txs2 = (0..2 * TARGET_NUM_TRANSACTIONS_PER_BATCH)
.map(|i| {
prioritized_tranfer(
create_and_fund_prioritized_transfer(
bank,
mint_keypair,
&Keypair::new(),
&Pubkey::new_unique(),
i as u64,
Expand Down Expand Up @@ -874,6 +958,7 @@ mod tests {
let (test_frame, central_scheduler_banking_stage) = create_test_frame(2);
let TestFrame {
bank,
mint_keypair,
poh_recorder,
banking_packet_sender,
consume_work_receivers,
Expand All @@ -889,7 +974,9 @@ mod tests {
// Send 4 transactions w/o conflicts. 2 should be scheduled on each thread
let txs = (0..4)
.map(|i| {
prioritized_tranfer(
create_and_fund_prioritized_transfer(
bank,
mint_keypair,
&Keypair::new(),
&Pubkey::new_unique(),
1,
Expand Down Expand Up @@ -940,6 +1027,7 @@ mod tests {
let (test_frame, central_scheduler_banking_stage) = create_test_frame(1);
let TestFrame {
bank,
mint_keypair,
poh_recorder,
banking_packet_sender,
consume_work_receivers,
Expand All @@ -954,14 +1042,18 @@ mod tests {
let scheduler_thread = std::thread::spawn(move || central_scheduler_banking_stage.run());

// Send packet batch to the scheduler - should do nothing until we become the leader.
let tx1 = prioritized_tranfer(
let tx1 = create_and_fund_prioritized_transfer(
bank,
mint_keypair,
&Keypair::new(),
&Pubkey::new_unique(),
1,
1,
bank.last_blockhash(),
);
let tx2 = prioritized_tranfer(
let tx2 = create_and_fund_prioritized_transfer(
bank,
mint_keypair,
&Keypair::new(),
&Pubkey::new_unique(),
1,
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/accounts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ fn accumulate_and_check_loaded_account_data_size(
}
}

fn validate_fee_payer(
pub fn validate_fee_payer(
payer_address: &Pubkey,
payer_account: &mut AccountSharedData,
payer_index: IndexOfAccount,
Expand Down

0 comments on commit cc756c3

Please sign in to comment.