TransactionScheduler: Add funded check before graph insertion (#34699)

This commit is contained in:
Andrew Fitzgerald 2024-01-12 11:54:04 -08:00 committed by GitHub
parent 98a2873517
commit beef8476f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 78 additions and 14 deletions

View File

@ -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<Bank>,
mint_keypair: Keypair,
_ledger_path: TempDir,
_entry_receiver: Receiver<WorkingBankEntry>,
_record_receiver: Receiver<Record>,
@ -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,