diff --git a/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs b/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs index 930d2fe1d0..56a1ff2482 100644 --- a/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs +++ b/core/src/banking_stage/transaction_scheduler/scheduler_controller.rs @@ -10,6 +10,7 @@ use { }, crate::banking_stage::{ consume_worker::ConsumeWorkerMetrics, + consumer::Consumer, decision_maker::{BufferedPacketsDecision, DecisionMaker}, immutable_deserialized_packet::ImmutableDeserializedPacket, packet_deserializer::PacketDeserializer, @@ -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(); } } @@ -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, @@ -596,6 +606,7 @@ mod tests { // such that our tests can be more easily set up and run. struct TestFrame { bank: Arc, + mint_keypair: Keypair, _ledger_path: TempDir, _entry_receiver: Receiver, _record_receiver: Receiver, @@ -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!(); @@ -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, @@ -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())); @@ -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, @@ -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, @@ -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, @@ -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(); @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, @@ -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, @@ -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,