Skip to content

Commit

Permalink
TransactionScheduler: Add funded check before graph insertion (#34699)
Browse files Browse the repository at this point in the history
  • Loading branch information
apfitzge authored Jan 12, 2024
1 parent 98a2873 commit beef847
Showing 1 changed file with 78 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use {
},
crate::banking_stage::{
consume_worker::ConsumeWorkerMetrics,
consumer::Consumer,
decision_maker::{BufferedPacketsDecision, DecisionMaker},
immutable_deserialized_packet::ImmutableDeserializedPacket,
packet_deserializer::PacketDeserializer,
Expand Down Expand Up @@ -163,8 +164,17 @@ 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
Consumer::check_fee_payer_unlocked(bank, tx.message(), &mut error_counters)
})
.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 +590,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 +606,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 +618,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 +652,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 +672,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 +732,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 +746,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 +793,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 +807,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 +859,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 +875,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 +888,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 +930,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 +946,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 +999,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 +1014,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

0 comments on commit beef847

Please sign in to comment.