Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TransactionScheduler: Add funded check before graph insertion #34699

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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